Annotation of embedaddon/bird2/proto/ospf/packet.c, revision 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>