Annotation of embedaddon/bird/proto/ospf/packet.c, revision 1.1.1.2

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 = ifa->autype;
                     33: }
                     34: 
                     35: /* We assume OSPFv2 in ospf_pkt_finalize() */
                     36: static void
                     37: ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
                     38: {
                     39:   struct password_item *pass = NULL;
                     40:   union ospf_auth *auth = (void *) (pkt + 1);
                     41: 
                     42:   pkt->checksum = 0;
                     43:   pkt->autype = ifa->autype;
                     44:   bzero(auth, sizeof(union ospf_auth));
                     45: 
                     46:   /* Compatibility note: auth may contain anything if autype is
                     47:      none, but nonzero values do not work with Mikrotik OSPF */
                     48: 
                     49:   switch (ifa->autype)
                     50:   {
                     51:   case OSPF_AUTH_SIMPLE:
                     52:     pass = password_find(ifa->passwords, 1);
                     53:     if (!pass)
                     54:     {
                     55:       log(L_ERR "No suitable password found for authentication");
                     56:       return;
                     57:     }
                     58:     strncpy(auth->password, pass->password, sizeof(auth->password));
1.1.1.2 ! misho      59:     /* fallthrough */
1.1       misho      60: 
                     61:   case OSPF_AUTH_NONE:
                     62:     {
                     63:       void *body = (void *) (auth + 1);
                     64:       uint blen = *plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth);
                     65:       pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
                     66:     }
                     67:     break;
                     68: 
                     69:   case OSPF_AUTH_CRYPT:
                     70:     pass = password_find(ifa->passwords, 0);
                     71:     if (!pass)
                     72:     {
                     73:       log(L_ERR "No suitable password found for authentication");
                     74:       return;
                     75:     }
                     76: 
                     77:     /* Perhaps use random value to prevent replay attacks after
                     78:        reboot when system does not have independent RTC? */
                     79:     if (!ifa->csn)
                     80:     {
                     81:       ifa->csn = (u32) now;
                     82:       ifa->csn_use = now;
                     83:     }
                     84: 
                     85:     /* We must have sufficient delay between sending a packet and increasing
                     86:        CSN to prevent reordering of packets (in a network) with different CSNs */
                     87:     if ((now - ifa->csn_use) > 1)
                     88:       ifa->csn++;
                     89: 
                     90:     ifa->csn_use = now;
                     91: 
                     92:     uint auth_len = mac_type_length(pass->alg);
                     93:     byte *auth_tail = ((byte *) pkt + *plen);
                     94:     *plen += auth_len;
                     95: 
                     96:     ASSERT(*plen < ifa->sk->tbsize);
                     97: 
                     98:     auth->c32.zero = 0;
                     99:     auth->c32.keyid = pass->id;
                    100:     auth->c32.len = auth_len;
                    101:     auth->c32.csn = htonl(ifa->csn);
                    102: 
                    103:     /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
                    104:     if (pass->alg < ALG_HMAC)
                    105:       strncpy(auth_tail, pass->password, auth_len);
                    106:     else
                    107:       memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
                    108: 
                    109:     mac_fill(pass->alg, pass->password, pass->length,
                    110:             (byte *) pkt, *plen, auth_tail);
                    111:     break;
                    112: 
                    113:   default:
                    114:     bug("Unknown authentication type");
                    115:   }
                    116: }
                    117: 
                    118: 
                    119: /* We assume OSPFv2 in ospf_pkt_checkauth() */
                    120: static int
                    121: ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len)
                    122: {
                    123:   struct ospf_proto *p = ifa->oa->po;
                    124:   union ospf_auth *auth = (void *) (pkt + 1);
                    125:   struct password_item *pass = NULL;
                    126:   const char *err_dsc = NULL;
                    127:   uint err_val = 0;
                    128: 
                    129:   uint plen = ntohs(pkt->length);
                    130:   u8 autype = pkt->autype;
                    131: 
                    132:   if (autype != ifa->autype)
                    133:     DROP("authentication method mismatch", autype);
                    134: 
                    135:   switch (autype)
                    136:   {
                    137:   case OSPF_AUTH_NONE:
                    138:     return 1;
                    139: 
                    140:   case OSPF_AUTH_SIMPLE:
                    141:     pass = password_find(ifa->passwords, 1);
                    142:     if (!pass)
                    143:       DROP1("no password found");
                    144: 
                    145:     if (!password_verify(pass, auth->password, sizeof(auth->password)))
                    146:       DROP("wrong password", pass->id);
                    147: 
                    148:     return 1;
                    149: 
                    150:   case OSPF_AUTH_CRYPT:
                    151:     pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
                    152:     if (!pass)
                    153:       DROP("no suitable password found", auth->c32.keyid);
                    154: 
                    155:     uint auth_len = mac_type_length(pass->alg);
                    156: 
                    157:     if (plen + auth->c32.len > len)
                    158:       DROP("packet length mismatch", len);
                    159: 
                    160:     if (auth->c32.len != auth_len)
                    161:       DROP("wrong authentication length", auth->c32.len);
                    162: 
                    163:     u32 rcv_csn = ntohl(auth->c32.csn);
                    164:     if (n && (rcv_csn < n->csn))
                    165:       // DROP("lower sequence number", rcv_csn);
                    166:     {
                    167:       /* We want to report both new and old CSN */
                    168:       LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
                    169:                   "lower sequence number (rcv %u, old %u)",
                    170:                   n->rid, ifa->ifname, rcv_csn, n->csn);
                    171:       return 0;
                    172:     }
                    173: 
                    174:     byte *auth_tail = ((byte *) pkt) + plen;
                    175:     byte *auth_data = alloca(auth_len);
                    176:     memcpy(auth_data, auth_tail, auth_len);
                    177: 
                    178:     /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
                    179:     if (pass->alg < ALG_HMAC)
                    180:       strncpy(auth_tail, pass->password, auth_len);
                    181:     else
                    182:       memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
                    183: 
                    184:     if (!mac_verify(pass->alg, pass->password, pass->length,
                    185:                    (byte *) pkt, plen + auth_len, auth_data))
                    186:       DROP("wrong authentication code", pass->id);
                    187: 
                    188:     if (n)
                    189:       n->csn = rcv_csn;
                    190: 
                    191:     return 1;
                    192: 
                    193:   default:
                    194:     bug("Unknown authentication type");
                    195:   }
                    196: 
                    197: drop:
                    198:   LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
                    199:               (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
                    200: 
                    201:   return 0;
                    202: }
                    203: 
                    204: /**
                    205:  * ospf_rx_hook
                    206:  * @sk: socket we received the packet.
                    207:  * @len: size of the packet
                    208:  *
                    209:  * This is the entry point for messages from neighbors. Many checks (like
                    210:  * authentication, checksums, size) are done before the packet is passed to
                    211:  * non generic functions.
                    212:  */
                    213: int
                    214: ospf_rx_hook(sock *sk, uint len)
                    215: {
                    216:   /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter
                    217:      out other packets at kernel level and we receive all packets on all sockets */
                    218:   if (sk->lifindex != sk->iface->index)
                    219:     return 1;
                    220: 
                    221:   DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
                    222:       sk->iface->name, sk->faddr, sk->laddr);
                    223: 
                    224:   /* Initially, the packet is associated with the 'master' iface */
                    225:   struct ospf_iface *ifa = sk->data;
                    226:   struct ospf_proto *p = ifa->oa->po;
                    227:   const char *err_dsc = NULL;
                    228:   uint err_val = 0;
                    229: 
                    230:   /* Should not happen */
                    231:   if (ifa->state <= OSPF_IS_LOOP)
                    232:     return 1;
                    233: 
                    234:   int src_local, dst_local, dst_mcast;
                    235:   src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
                    236:   dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
                    237:   dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
                    238: 
                    239:   if (ospf_is_v2(p))
                    240:   {
                    241:     /* First, we eliminate packets with strange address combinations.
                    242:      * In OSPFv2, they might be for other ospf_ifaces (with different IP
                    243:      * prefix) on the same real iface, so we don't log it. We enforce
                    244:      * that (src_local || dst_local), therefore we are eliminating all
                    245:      * such cases.
                    246:      */
                    247:     if (dst_mcast && !src_local)
                    248:       return 1;
                    249:     if (!dst_mcast && !dst_local)
                    250:       return 1;
                    251: 
                    252:     /* Ignore my own broadcast packets */
                    253:     if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
                    254:       return 1;
                    255:   }
                    256:   else
                    257:   {
                    258:     /* In OSPFv3, src_local and dst_local mean link-local.
                    259:      * RFC 5340 says that local (non-vlink) packets use
                    260:      * link-local src address, but does not enforce it. Strange.
                    261:      */
                    262:     if (dst_mcast && !src_local)
                    263:       LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s",
                    264:                   sk->faddr, ifa->ifname);
                    265:   }
                    266: 
                    267:   /* Second, we check packet length, checksum, and the protocol version */
                    268:   struct ospf_packet *pkt = (void *) sk_rx_buffer(sk, &len);
                    269: 
                    270: 
                    271:   if (pkt == NULL)
                    272:     DROP("bad IP header", len);
                    273: 
                    274:   if (ifa->check_ttl && (sk->rcv_ttl < 255))
                    275:     DROP("wrong TTL", sk->rcv_ttl);
                    276: 
                    277:   if (len < sizeof(struct ospf_packet))
                    278:     DROP("too short", len);
                    279: 
                    280:   if (pkt->version != ospf_get_version(p))
                    281:     DROP("version mismatch", pkt->version);
                    282: 
                    283:   uint plen = ntohs(pkt->length);
                    284:   if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
                    285:     DROP("invalid length", plen);
                    286: 
                    287:   if (sk->flags & SKF_TRUNCATED)
                    288:   {
                    289:     /* If we have dynamic buffers and received truncated message, we expand RX buffer */
                    290: 
                    291:     uint bs = plen + 256;
                    292:     bs = BIRD_ALIGN(bs, 1024);
                    293: 
                    294:     if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
                    295:       sk_set_rbsize(sk, bs);
                    296: 
                    297:     DROP("truncated", plen);
                    298:   }
                    299: 
                    300:   if (plen > len)
                    301:     DROP("length mismatch", plen);
                    302: 
                    303:   if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
                    304:   {
                    305:     uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth);
                    306:     uint blen = plen - hlen;
                    307:     void *body = ((void *) pkt) + hlen;
                    308: 
                    309:     if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
                    310:       DROP1("invalid checksum");
                    311:   }
                    312: 
                    313:   /* Third, we resolve associated iface and handle vlinks. */
                    314: 
                    315:   u32 areaid = ntohl(pkt->areaid);
                    316:   u32 rid = ntohl(pkt->routerid);
                    317:   u8 instance_id = pkt->instance_id;
                    318: 
                    319:   if (areaid == ifa->oa->areaid)
                    320:   {
                    321:     /* Matching area ID */
                    322: 
                    323:     if (instance_id != ifa->instance_id)
                    324:       return 1;
                    325: 
                    326:     /* It is real iface, source should be local (in OSPFv2) */
                    327:     if (ospf_is_v2(p) && !src_local)
                    328:       DROP1("strange source address");
                    329: 
                    330:     goto found;
                    331:   }
                    332:   else if ((areaid == 0) && !dst_mcast)
                    333:   {
                    334:     /* Backbone area ID and possible vlink packet */
                    335: 
                    336:     if ((p->areano == 1) || !oa_is_ext(ifa->oa))
                    337:       return 1;
                    338: 
                    339:     struct ospf_iface *iff = NULL;
                    340:     WALK_LIST(iff, p->iface_list)
                    341:     {
                    342:       if ((iff->type == OSPF_IT_VLINK) &&
                    343:          (iff->voa == ifa->oa) &&
                    344:          (iff->instance_id == instance_id) &&
                    345:          (iff->vid == rid))
                    346:       {
                    347:        /* Vlink should be UP */
                    348:        if (iff->state != OSPF_IS_PTP)
                    349:          return 1;
                    350: 
                    351:        ifa = iff;
                    352:        goto found;
                    353:       }
                    354:     }
                    355: 
                    356:     /*
                    357:      * Cannot find matching vlink. It is either misconfigured vlink; NBMA or
                    358:      * PtMP with misconfigured area ID, or packet for some other instance (that
                    359:      * is possible even if instance_id == ifa->instance_id, because it may be
                    360:      * also vlink packet in the other instance, which is different namespace).
                    361:      */
                    362: 
                    363:     return 1;
                    364:   }
                    365:   else
                    366:   {
                    367:     /* Non-matching area ID but cannot be vlink packet */
                    368: 
                    369:     if (instance_id != ifa->instance_id)
                    370:       return 1;
                    371: 
                    372:     DROP("area mismatch", areaid);
                    373:   }
                    374: 
                    375: 
                    376: found:
                    377:   if (ifa->stub)           /* This shouldn't happen */
                    378:     return 1;
                    379: 
                    380:   if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0))
                    381:     return 1;
                    382: 
                    383:   if (rid == p->router_id)
                    384:     DROP1("my own router ID");
                    385: 
                    386:   if (rid == 0)
                    387:     DROP1("zero router ID");
                    388: 
                    389:   /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
                    390:   uint t = ifa->type;
                    391:   struct ospf_neighbor *n;
                    392:   if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
                    393:     n = find_neigh_by_ip(ifa, sk->faddr);
                    394:   else
                    395:     n = find_neigh(ifa, rid);
                    396: 
                    397:   if (!n && (pkt->type != HELLO_P))
                    398:   {
                    399:     OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
                    400:               rid, ifa->ifname, sk->faddr);
                    401:     return 1;
                    402:   }
                    403: 
                    404:   /* ospf_pkt_checkauth() has its own error logging */
                    405:   if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, len))
                    406:     return 1;
                    407: 
                    408:   switch (pkt->type)
                    409:   {
                    410:   case HELLO_P:
                    411:     ospf_receive_hello(pkt, ifa, n, sk->faddr);
                    412:     break;
                    413: 
                    414:   case DBDES_P:
                    415:     ospf_receive_dbdes(pkt, ifa, n);
                    416:     break;
                    417: 
                    418:   case LSREQ_P:
                    419:     ospf_receive_lsreq(pkt, ifa, n);
                    420:     break;
                    421: 
                    422:   case LSUPD_P:
                    423:     ospf_receive_lsupd(pkt, ifa, n);
                    424:     break;
                    425: 
                    426:   case LSACK_P:
                    427:     ospf_receive_lsack(pkt, ifa, n);
                    428:     break;
                    429: 
                    430:   default:
                    431:     DROP("invalid packet type", pkt->type);
                    432:   };
                    433:   return 1;
                    434: 
                    435: drop:
                    436:   LOG_PKT("Bad packet from %I via %s - %s (%u)",
                    437:          sk->faddr, ifa->ifname, err_dsc, err_val);
                    438: 
                    439:   return 1;
                    440: }
                    441: 
                    442: /*
                    443: void
                    444: ospf_tx_hook(sock * sk)
                    445: {
                    446:   struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
                    447: //  struct proto *p = (struct proto *) (ifa->oa->p);
                    448:   log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
                    449: }
                    450: */
                    451: 
                    452: void
                    453: ospf_err_hook(sock * sk, int err)
                    454: {
                    455:   struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
                    456:   struct ospf_proto *p = ifa->oa->po;
                    457:   log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err);
                    458: }
                    459: 
                    460: void
                    461: ospf_verr_hook(sock *sk, int err)
                    462: {
                    463:   struct ospf_proto *p = (struct ospf_proto *) (sk->data);
                    464:   log(L_ERR "%s: Vlink socket error: %M", p->p.name, err);
                    465: }
                    466: 
                    467: void
                    468: ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
                    469: {
                    470:   sock *sk = ifa->sk;
                    471:   struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
                    472:   uint plen = ntohs(pkt->length);
                    473: 
                    474:   if (ospf_is_v2(ifa->oa->po))
                    475:     ospf_pkt_finalize(ifa, pkt, &plen);
                    476: 
                    477:   int done = sk_send_to(sk, plen, dst, 0);
                    478:   if (!done)
                    479:     log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
                    480: }
                    481: 
                    482: void
                    483: ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
                    484: {
                    485:   struct ospf_neighbor *n;
                    486: 
                    487:   WALK_LIST(n, ifa->neigh_list)
                    488:     if (n->state >= state)
                    489:       ospf_send_to(ifa, n->ip);
                    490: }
                    491: 
                    492: void
                    493: ospf_send_to_bdr(struct ospf_iface *ifa)
                    494: {
                    495:   if (ipa_nonzero(ifa->drip))
                    496:     ospf_send_to(ifa, ifa->drip);
                    497:   if (ipa_nonzero(ifa->bdrip))
                    498:     ospf_send_to(ifa, ifa->bdrip);
                    499: }

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