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

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