File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf / packet.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Aug 22 12:33:54 2017 UTC (6 years, 10 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_3p0, v1_6_3, HEAD
bird 1.6.3

    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>