Annotation of embedaddon/bird2/proto/ospf/packet.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     BIRD -- OSPF
                      3:  *
                      4:  *     (c) 1999--2005 Ondrej Filip <feela@network.cz>
                      5:  *     (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
                      6:  *     (c) 2009--2014 CZ.NIC z.s.p.o.
                      7:  *
                      8:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      9:  */
                     10: 
                     11: #include "ospf.h"
                     12: #include "nest/password.h"
                     13: #include "lib/md5.h"
                     14: #include "lib/mac.h"
                     15: #include "lib/socket.h"
                     16: 
                     17: void
                     18: ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
                     19: {
                     20:   struct ospf_proto *p = ifa->oa->po;
                     21:   struct ospf_packet *pkt;
                     22: 
                     23:   pkt = (struct ospf_packet *) buf;
                     24: 
                     25:   pkt->version = ospf_get_version(p);
                     26:   pkt->type = h_type;
                     27:   pkt->length = htons(ospf_pkt_maxsize(ifa));
                     28:   pkt->routerid = htonl(p->router_id);
                     29:   pkt->areaid = htonl(ifa->oa->areaid);
                     30:   pkt->checksum = 0;
                     31:   pkt->instance_id = ifa->instance_id;
                     32:   pkt->autype = ospf_is_v2(p) ? ifa->autype : 0;
                     33: }
                     34: 
                     35: /* We assume OSPFv2 in ospf_pkt_finalize() */
                     36: static void
                     37: ospf_pkt_finalize2(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
                     38: {
                     39:   struct ospf_proto *p = ifa->oa->po;
                     40:   struct password_item *pass = NULL;
                     41:   union ospf_auth2 *auth = (void *) (pkt + 1);
                     42:   memset(auth, 0, sizeof(union ospf_auth2));
                     43: 
                     44:   /* Compatibility note: auth may contain anything if autype is
                     45:      none, but nonzero values do not work with Mikrotik OSPF */
                     46: 
                     47:   pkt->checksum = 0;
                     48:   pkt->autype = ifa->autype;
                     49: 
                     50:   switch (ifa->autype)
                     51:   {
                     52:   case OSPF_AUTH_SIMPLE:
                     53:     pass = password_find(ifa->passwords, 1);
                     54:     if (!pass)
                     55:     {
                     56:       log(L_ERR "No suitable password found for authentication");
                     57:       return;
                     58:     }
                     59:     strncpy(auth->password, pass->password, sizeof(auth->password));
                     60:     /* fallthrough */
                     61: 
                     62:   case OSPF_AUTH_NONE:
                     63:     {
                     64:       void *body = (void *) (auth + 1);
                     65:       uint blen = *plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth2);
                     66:       pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
                     67:     }
                     68:     break;
                     69: 
                     70:   case OSPF_AUTH_CRYPT:
                     71:     pass = password_find(ifa->passwords, 0);
                     72:     if (!pass)
                     73:     {
                     74:       log(L_ERR "%s: No suitable password found for authentication", p->p.name);
                     75:       return;
                     76:     }
                     77: 
                     78:     /* Perhaps use random value to prevent replay attacks after
                     79:        reboot when system does not have independent RTC? */
                     80:     if (!ifa->csn)
                     81:     {
                     82:       ifa->csn = (u32) (current_real_time() TO_S);
                     83:       ifa->csn_use = current_time();
                     84:     }
                     85: 
                     86:     /* We must have sufficient delay between sending a packet and increasing
                     87:        CSN to prevent reordering of packets (in a network) with different CSNs */
                     88:     if ((current_time() - ifa->csn_use) > 1 S)
                     89:       ifa->csn++;
                     90: 
                     91:     ifa->csn_use = current_time();
                     92: 
                     93:     uint auth_len = mac_type_length(pass->alg);
                     94:     byte *auth_tail = ((byte *) pkt + *plen);
                     95:     *plen += auth_len;
                     96: 
                     97:     ASSERT(*plen < ifa->sk->tbsize);
                     98: 
                     99:     auth->c32.zero = 0;
                    100:     auth->c32.keyid = pass->id;
                    101:     auth->c32.len = auth_len;
                    102:     auth->c32.csn = htonl(ifa->csn);
                    103: 
                    104:     /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
                    105:     if (pass->alg < ALG_HMAC)
                    106:       strncpy(auth_tail, pass->password, auth_len);
                    107:     else
                    108:       memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
                    109: 
                    110:     mac_fill(pass->alg, pass->password, pass->length, (byte *) pkt, *plen, auth_tail);
                    111:     break;
                    112: 
                    113:   default:
                    114:     bug("Unknown authentication type");
                    115:   }
                    116: }
                    117: 
                    118: /*
                    119:  * Return an extra packet size that should be added to a final packet size
                    120:  */
                    121: static void
                    122: ospf_pkt_finalize3(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen, ip_addr src)
                    123: {
                    124:   struct ospf_proto *p = ifa->oa->po;
                    125:   struct ospf_auth3 *auth = (void *) ((byte *) pkt + *plen);
                    126: 
                    127:   pkt->checksum = 0;
                    128:   pkt->autype = 0;
                    129: 
                    130:   if (ifa->autype != OSPF_AUTH_CRYPT)
                    131:     return;
                    132: 
                    133:   struct password_item *pass = password_find(ifa->passwords, 0);
                    134:   if (!pass)
                    135:   {
                    136:     log(L_ERR "%s: No suitable password found for authentication", p->p.name);
                    137:     return;
                    138:   }
                    139: 
                    140:   /* FIXME: Ensure persistence */
                    141:   p->csn64++;
                    142: 
                    143:   uint mac_len = mac_type_length(pass->alg);
                    144:   uint auth_len = sizeof(struct ospf_auth3) + mac_len;
                    145:   *plen += auth_len;
                    146: 
                    147:   ASSERT(*plen < ifa->sk->tbsize);
                    148: 
                    149:   memset(auth, 0, sizeof(struct ospf_auth3));
                    150:   auth->type = htons(OSPF3_AUTH_HMAC);
                    151:   auth->length = htons(auth_len);
                    152:   auth->reserved = 0;
                    153:   auth->sa_id = htons(pass->id);
                    154:   put_u64(&auth->csn, p->csn64);
                    155: 
                    156:   /* Initialize with src IP address padded with HMAC_MAGIC */
                    157:   put_ip6(auth->data, ipa_to_ip6(src));
                    158:   memset32(auth->data + 16, HMAC_MAGIC, (mac_len - 16) / 4);
                    159: 
                    160:   /* Attach OSPFv3 Cryptographic Protocol ID to the key */
                    161:   uint pass_len = pass->length + 2;
                    162:   byte *pass_key = alloca(pass_len);
                    163:   memcpy(pass_key, pass->password, pass->length);
                    164:   put_u16(pass_key + pass->length, OSPF3_CRYPTO_ID);
                    165: 
                    166:   mac_fill(pass->alg, pass_key, pass_len, (byte *) pkt, *plen, auth->data);
                    167: }
                    168: 
                    169: 
                    170: static int
                    171: ospf_pkt_checkauth2(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len)
                    172: {
                    173:   struct ospf_proto *p = ifa->oa->po;
                    174:   union ospf_auth2 *auth = (void *) (pkt + 1);
                    175:   struct password_item *pass = NULL;
                    176:   const char *err_dsc = NULL;
                    177:   uint err_val = 0;
                    178: 
                    179:   uint plen = ntohs(pkt->length);
                    180:   u8 autype = pkt->autype;
                    181: 
                    182:   if (autype != ifa->autype)
                    183:     DROP("authentication method mismatch", autype);
                    184: 
                    185:   switch (autype)
                    186:   {
                    187:   case OSPF_AUTH_NONE:
                    188:     return 1;
                    189: 
                    190:   case OSPF_AUTH_SIMPLE:
                    191:     pass = password_find(ifa->passwords, 1);
                    192:     if (!pass)
                    193:       DROP1("no password found");
                    194: 
                    195:     if (!password_verify(pass, auth->password, sizeof(auth->password)))
                    196:       DROP("wrong password", pass->id);
                    197: 
                    198:     return 1;
                    199: 
                    200:   case OSPF_AUTH_CRYPT:
                    201:     pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
                    202:     if (!pass)
                    203:       DROP("no suitable password found", auth->c32.keyid);
                    204: 
                    205:     uint auth_len = mac_type_length(pass->alg);
                    206: 
                    207:     if (plen + auth->c32.len > len)
                    208:       DROP("packet length mismatch", len);
                    209: 
                    210:     if (auth->c32.len != auth_len)
                    211:       DROP("wrong authentication length", auth->c32.len);
                    212: 
                    213:     u32 rcv_csn = ntohl(auth->c32.csn);
                    214:     if (n && (rcv_csn < n->csn))
                    215:       // DROP("lower sequence number", rcv_csn);
                    216:     {
                    217:       /* We want to report both new and old CSN */
                    218:       LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
                    219:                   "lower sequence number (rcv %u, old %u)",
                    220:                   n->rid, ifa->ifname, rcv_csn, n->csn);
                    221:       return 0;
                    222:     }
                    223: 
                    224:     byte *auth_tail = ((byte *) pkt) + plen;
                    225:     byte *auth_data = alloca(auth_len);
                    226:     memcpy(auth_data, auth_tail, auth_len);
                    227: 
                    228:     /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
                    229:     if (pass->alg < ALG_HMAC)
                    230:       strncpy(auth_tail, pass->password, auth_len);
                    231:     else
                    232:       memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
                    233: 
                    234:     if (!mac_verify(pass->alg, pass->password, pass->length,
                    235:                    (byte *) pkt, plen + auth_len, auth_data))
                    236:       DROP("wrong authentication code", pass->id);
                    237: 
                    238:     if (n)
                    239:       n->csn = rcv_csn;
                    240: 
                    241:     return 1;
                    242: 
                    243:   default:
                    244:     bug("Unknown authentication type");
                    245:   }
                    246: 
                    247: drop:
                    248:   LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
                    249:               (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
                    250: 
                    251:   return 0;
                    252: }
                    253: 
                    254: static int
                    255: ospf_pkt_checkauth3(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len, ip_addr src)
                    256: {
                    257:   struct ospf_proto *p = ifa->oa->po;
                    258:   const char *err_dsc = NULL;
                    259:   uint err_val = 0;
                    260: 
                    261:   uint plen = ntohs(pkt->length);
                    262:   uint opts, lls_present, auth_present;
                    263: 
                    264:   /*
                    265:    * When autentication is not enabled, ignore the trailer. This is different
                    266:    * from OSPFv2, but it is necessary in order to support migration modes. Note
                    267:    * that regular authenticated packets do not have valid checksum and will be
                    268:    * dropped by OS on non-authenticated ifaces.
                    269:    */
                    270:   if (ifa->autype != OSPF_AUTH_CRYPT)
                    271:     return 1;
                    272: 
                    273:   switch(pkt->type)
                    274:   {
                    275:   case HELLO_P:
                    276:     opts = ospf_hello3_options(pkt);
                    277:     lls_present = opts & OPT_L_V3;
                    278:     auth_present = opts & OPT_AT;
                    279:     break;
                    280: 
                    281:   case DBDES_P:
                    282:     opts = ospf_dbdes3_options(pkt);
                    283:     lls_present = opts & OPT_L_V3;
                    284:     auth_present = opts & OPT_AT;
                    285:     break;
                    286: 
                    287:   default:
                    288:     lls_present = 0;
                    289:     auth_present = n->options & OPT_AT;
                    290:   }
                    291: 
                    292:   if (!auth_present)
                    293:     DROP1("missing authentication trailer");
                    294: 
                    295:   if (lls_present)
                    296:   {
                    297:     if ((plen + sizeof(struct ospf_lls)) > len)
                    298:       DROP("packet length mismatch", len);
                    299: 
                    300:     struct ospf_lls *lls = (void *) ((byte *) pkt + plen);
                    301:     plen += ntohs(lls->length);
                    302:   }
                    303: 
                    304:   if ((plen + sizeof(struct ospf_auth3)) > len)
                    305:     DROP("packet length mismatch", len);
                    306: 
                    307:   struct ospf_auth3 *auth = (void *) ((byte *) pkt + plen);
                    308: 
                    309:   uint rcv_auth_type = ntohs(auth->type);
                    310:   if (rcv_auth_type != OSPF3_AUTH_HMAC)
                    311:     DROP("authentication method mismatch", rcv_auth_type);
                    312: 
                    313:   uint rcv_auth_len = ntohs(auth->length);
                    314:   if (plen + rcv_auth_len > len)
                    315:     DROP("packet length mismatch", len);
                    316: 
                    317:   uint rcv_key_id = ntohs(auth->sa_id);
                    318:   struct password_item *pass = password_find_by_id(ifa->passwords, rcv_key_id);
                    319:   if (!pass)
                    320:     DROP("no suitable password found", rcv_key_id);
                    321: 
                    322:   uint mac_len = mac_type_length(pass->alg);
                    323:   if (rcv_auth_len != (sizeof(struct ospf_auth3) + mac_len))
                    324:     DROP("wrong authentication length", rcv_auth_len);
                    325: 
                    326:   uint pt = pkt->type - 1;
                    327:   u64 rcv_csn = get_u64(&auth->csn);
                    328:   if (n && (rcv_csn <= n->csn64[pt]))
                    329:   {
                    330:     /* We want to report both new and old CSN */
                    331:     LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
                    332:                 "lower sequence number (rcv %u, old %u)",
                    333:                 n->rid, ifa->ifname, (uint) rcv_csn, (uint) n->csn64[pt]);
                    334:     return 0;
                    335:   }
                    336: 
                    337:   /* Save the received authentication data */
                    338:   byte *auth_data = alloca(mac_len);
                    339:   memcpy(auth_data, auth->data, mac_len);
                    340: 
                    341:   /* Initialize with src IP address padded with HMAC_MAGIC */
                    342:   put_ip6(auth->data, ipa_to_ip6(src));
                    343:   memset32(auth->data + 16, HMAC_MAGIC, (mac_len - 16) / 4);
                    344: 
                    345:   /* Attach OSPFv3 Cryptographic Protocol ID to the key */
                    346:   uint pass_len = pass->length + 2;
                    347:   byte *pass_key = alloca(pass_len);
                    348:   memcpy(pass_key, pass->password, pass->length);
                    349:   put_u16(pass_key + pass->length, OSPF3_CRYPTO_ID);
                    350: 
                    351:   if (!mac_verify(pass->alg, pass_key, pass_len,
                    352:                  (byte *) pkt, plen + rcv_auth_len, auth_data))
                    353:     DROP("wrong authentication code", pass->id);
                    354: 
                    355:   if (n)
                    356:     n->csn64[pt] = rcv_csn;
                    357: 
                    358:   return 1;
                    359: 
                    360: drop:
                    361:   LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
                    362:               (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
                    363: 
                    364:   return 0;
                    365: }
                    366: 
                    367: /**
                    368:  * ospf_rx_hook
                    369:  * @sk: socket we received the packet.
                    370:  * @len: length of the packet
                    371:  *
                    372:  * This is the entry point for messages from neighbors. Many checks (like
                    373:  * authentication, checksums, size) are done before the packet is passed to
                    374:  * non generic functions.
                    375:  */
                    376: int
                    377: ospf_rx_hook(sock *sk, uint len)
                    378: {
                    379:   /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter
                    380:      out other packets at kernel level and we receive all packets on all sockets */
                    381:   if (sk->lifindex != sk->iface->index)
                    382:     return 1;
                    383: 
                    384:   DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
                    385:       sk->iface->name, sk->faddr, sk->laddr);
                    386: 
                    387:   /* Initially, the packet is associated with the 'master' iface */
                    388:   struct ospf_iface *ifa = sk->data;
                    389:   struct ospf_proto *p = ifa->oa->po;
                    390:   const char *err_dsc = NULL;
                    391:   uint err_val = 0;
                    392: 
                    393:   /* Should not happen */
                    394:   if (ifa->state <= OSPF_IS_LOOP)
                    395:     return 1;
                    396: 
                    397:   int src_local, dst_local, dst_mcast;
                    398:   src_local = ipa_in_netX(sk->faddr, &ifa->addr->prefix);
                    399:   dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
                    400:   dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
                    401: 
                    402:   if (ospf_is_v2(p))
                    403:   {
                    404:     /* First, we eliminate packets with strange address combinations.
                    405:      * In OSPFv2, they might be for other ospf_ifaces (with different IP
                    406:      * prefix) on the same real iface, so we don't log it. We enforce
                    407:      * that (src_local || dst_local), therefore we are eliminating all
                    408:      * such cases.
                    409:      */
                    410:     if (dst_mcast && !src_local)
                    411:       return 1;
                    412:     if (!dst_mcast && !dst_local)
                    413:       return 1;
                    414: 
                    415:     /* Ignore my own broadcast packets */
                    416:     if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
                    417:       return 1;
                    418:   }
                    419:   else
                    420:   {
                    421:     /* In OSPFv3, src_local and dst_local mean link-local.
                    422:      * RFC 5340 says that local (non-vlink) packets use
                    423:      * link-local src address, but does not enforce it. Strange.
                    424:      */
                    425:     if (dst_mcast && !src_local)
                    426:       LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s",
                    427:                   sk->faddr, ifa->ifname);
                    428:   }
                    429: 
                    430:   /* Second, we check packet length, checksum, and the protocol version */
                    431:   struct ospf_packet *pkt = (void *) sk_rx_buffer(sk, &len);
                    432: 
                    433: 
                    434:   if (pkt == NULL)
                    435:     DROP("bad IP header", len);
                    436: 
                    437:   if (len < sizeof(struct ospf_packet))
                    438:     DROP("too short", len);
                    439: 
                    440:   if (pkt->version != ospf_get_version(p))
                    441:     DROP("version mismatch", pkt->version);
                    442: 
                    443:   uint plen = ntohs(pkt->length);
                    444:   if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
                    445:     DROP("invalid length", plen);
                    446: 
                    447:   if (sk->flags & SKF_TRUNCATED)
                    448:   {
                    449:     /* If we have dynamic buffers and received truncated message, we expand RX buffer */
                    450: 
                    451:     uint bs = plen + 256;
                    452:     bs = BIRD_ALIGN(bs, 1024);
                    453: 
                    454:     if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
                    455:       sk_set_rbsize(sk, bs);
                    456: 
                    457:     DROP("truncated", plen);
                    458:   }
                    459: 
                    460:   if (plen > len)
                    461:     DROP("length mismatch", plen);
                    462: 
                    463:   if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
                    464:   {
                    465:     uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth2);
                    466:     uint blen = plen - hlen;
                    467:     void *body = ((void *) pkt) + hlen;
                    468: 
                    469:     if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
                    470:       DROP("invalid checksum", ntohs(pkt->checksum));
                    471:   }
                    472: 
                    473:   /* Third, we resolve associated iface and handle vlinks. */
                    474: 
                    475:   u32 areaid = ntohl(pkt->areaid);
                    476:   u32 rid = ntohl(pkt->routerid);
                    477:   u8 instance_id = pkt->instance_id;
                    478: 
                    479:   if (areaid == ifa->oa->areaid)
                    480:   {
                    481:     /* Matching area ID */
                    482: 
                    483:     if (instance_id != ifa->instance_id)
                    484:       return 1;
                    485: 
                    486:     /* It is real iface, source should be local (in OSPFv2) */
                    487:     if (ospf_is_v2(p) && !src_local)
                    488:       DROP1("strange source address");
                    489: 
                    490:     goto found;
                    491:   }
                    492:   else if ((areaid == 0) && !dst_mcast)
                    493:   {
                    494:     /* Backbone area ID and possible vlink packet */
                    495: 
                    496:     if ((p->areano == 1) || !oa_is_ext(ifa->oa))
                    497:       return 1;
                    498: 
                    499:     struct ospf_iface *iff = NULL;
                    500:     WALK_LIST(iff, p->iface_list)
                    501:     {
                    502:       if ((iff->type == OSPF_IT_VLINK) &&
                    503:          (iff->voa == ifa->oa) &&
                    504:          (iff->instance_id == instance_id) &&
                    505:          (iff->vid == rid))
                    506:       {
                    507:        /* Vlink should be UP */
                    508:        if (iff->state != OSPF_IS_PTP)
                    509:          return 1;
                    510: 
                    511:        ifa = iff;
                    512:        goto found;
                    513:       }
                    514:     }
                    515: 
                    516:     /*
                    517:      * Cannot find matching vlink. It is either misconfigured vlink; NBMA or
                    518:      * PtMP with misconfigured area ID, or packet for some other instance (that
                    519:      * is possible even if instance_id == ifa->instance_id, because it may be
                    520:      * also vlink packet in the other instance, which is different namespace).
                    521:      */
                    522: 
                    523:     return 1;
                    524:   }
                    525:   else
                    526:   {
                    527:     /* Non-matching area ID but cannot be vlink packet */
                    528: 
                    529:     if (instance_id != ifa->instance_id)
                    530:       return 1;
                    531: 
                    532:     DROP("area mismatch", areaid);
                    533:   }
                    534: 
                    535: 
                    536: found:
                    537:   if (ifa->stub)           /* This shouldn't happen */
                    538:     return 1;
                    539: 
                    540:   if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0))
                    541:     return 1;
                    542: 
                    543:   /* TTL check must be done after instance dispatch */
                    544:   if (ifa->check_ttl && (sk->rcv_ttl < 255))
                    545:     DROP("wrong TTL", sk->rcv_ttl);
                    546: 
                    547:   if (rid == p->router_id)
                    548:     DROP1("my own router ID");
                    549: 
                    550:   if (rid == 0)
                    551:     DROP1("zero router ID");
                    552: 
                    553:   /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
                    554:   uint t = ifa->type;
                    555:   struct ospf_neighbor *n;
                    556:   if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
                    557:     n = find_neigh_by_ip(ifa, sk->faddr);
                    558:   else
                    559:     n = find_neigh(ifa, rid);
                    560: 
                    561:   if (!n && (pkt->type != HELLO_P))
                    562:   {
                    563:     OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
                    564:               rid, ifa->ifname, sk->faddr);
                    565:     return 1;
                    566:   }
                    567: 
                    568:   /* Check packet type here, ospf_pkt_checkauth3() expects valid values */
                    569:   if (pkt->type < HELLO_P || pkt->type > LSACK_P)
                    570:     DROP("invalid packet type", pkt->type);
                    571: 
                    572:   /* ospf_pkt_checkauth() has its own error logging */
                    573:   if ((ospf_is_v2(p) ?
                    574:        !ospf_pkt_checkauth2(n, ifa, pkt, len) :
                    575:        !ospf_pkt_checkauth3(n, ifa, pkt, len, sk->faddr)))
                    576:     return 1;
                    577: 
                    578:   switch (pkt->type)
                    579:   {
                    580:   case HELLO_P:
                    581:     ospf_receive_hello(pkt, ifa, n, sk->faddr);
                    582:     break;
                    583: 
                    584:   case DBDES_P:
                    585:     ospf_receive_dbdes(pkt, ifa, n);
                    586:     break;
                    587: 
                    588:   case LSREQ_P:
                    589:     ospf_receive_lsreq(pkt, ifa, n);
                    590:     break;
                    591: 
                    592:   case LSUPD_P:
                    593:     ospf_receive_lsupd(pkt, ifa, n);
                    594:     break;
                    595: 
                    596:   case LSACK_P:
                    597:     ospf_receive_lsack(pkt, ifa, n);
                    598:     break;
                    599:   };
                    600:   return 1;
                    601: 
                    602: drop:
                    603:   LOG_PKT("Bad packet from %I via %s - %s (%u)",
                    604:          sk->faddr, ifa->ifname, err_dsc, err_val);
                    605: 
                    606:   return 1;
                    607: }
                    608: 
                    609: /*
                    610: void
                    611: ospf_tx_hook(sock * sk)
                    612: {
                    613:   struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
                    614: //  struct proto *p = (struct proto *) (ifa->oa->p);
                    615:   log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
                    616: }
                    617: */
                    618: 
                    619: void
                    620: ospf_err_hook(sock * sk, int err)
                    621: {
                    622:   struct ospf_iface *ifa = (struct ospf_iface *) (sk->data);
                    623:   struct ospf_proto *p = ifa->oa->po;
                    624:   log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err);
                    625: }
                    626: 
                    627: void
                    628: ospf_verr_hook(sock *sk, int err)
                    629: {
                    630:   struct ospf_proto *p = (struct ospf_proto *) (sk->data);
                    631:   log(L_ERR "%s: Vlink socket error: %M", p->p.name, err);
                    632: }
                    633: 
                    634: void
                    635: ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
                    636: {
                    637:   sock *sk = ifa->sk;
                    638:   struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
                    639:   uint plen = ntohs(pkt->length);
                    640: 
                    641:   if (ospf_is_v2(ifa->oa->po))
                    642:     ospf_pkt_finalize2(ifa, pkt, &plen);
                    643:   else
                    644:     ospf_pkt_finalize3(ifa, pkt, &plen, sk->saddr);
                    645: 
                    646:   int done = sk_send_to(sk, plen, dst, 0);
                    647:   if (!done)
                    648:     log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
                    649: }
                    650: 
                    651: void
                    652: ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
                    653: {
                    654:   struct ospf_neighbor *n;
                    655: 
                    656:   WALK_LIST(n, ifa->neigh_list)
                    657:     if (n->state >= state)
                    658:       ospf_send_to(ifa, n->ip);
                    659: }
                    660: 
                    661: void
                    662: ospf_send_to_bdr(struct ospf_iface *ifa)
                    663: {
                    664:   if (ipa_nonzero2(ifa->drip))
                    665:     ospf_send_to(ifa, ifa->drip);
                    666:   if (ipa_nonzero2(ifa->bdrip))
                    667:     ospf_send_to(ifa, ifa->bdrip);
                    668: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>