File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf / packet.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 19:50:23 2021 UTC (3 years, 3 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_8p3, HEAD
bird 1.6.8

    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:     /* fallthrough */
   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>