File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf / lsalib.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_8p3, v1_6_3p0, v1_6_3, HEAD
bird 1.6.3

    1: /*
    2:  *	BIRD -- OSPF
    3:  *
    4:  *	(c) 1999--2004 Ondrej Filip <feela@network.cz>
    5:  *	(c) 2009--2015 Ondrej Zajicek <santiago@crfreenet.org>
    6:  *	(c) 2009--2015 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: 
   13: #include "lib/fletcher16.h"
   14: 
   15: #ifndef CPU_BIG_ENDIAN
   16: void
   17: lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
   18: {
   19:   n->age = htons(h->age);
   20:   n->type_raw = htons(h->type_raw);
   21:   n->id = htonl(h->id);
   22:   n->rt = htonl(h->rt);
   23:   n->sn = htonl(h->sn);
   24:   n->checksum = htons(h->checksum);
   25:   n->length = htons(h->length);
   26: }
   27: 
   28: void
   29: lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
   30: {
   31:   h->age = ntohs(n->age);
   32:   h->type_raw = ntohs(n->type_raw);
   33:   h->id = ntohl(n->id);
   34:   h->rt = ntohl(n->rt);
   35:   h->sn = ntohl(n->sn);
   36:   h->checksum = ntohs(n->checksum);
   37:   h->length = ntohs(n->length);
   38: }
   39: 
   40: void
   41: lsa_hton_body(void *h, void *n, u16 len)
   42: {
   43:   u32 *hid = h;
   44:   u32 *nid = n;
   45:   uint i;
   46: 
   47:   for (i = 0; i < (len / sizeof(u32)); i++)
   48:     nid[i] = htonl(hid[i]);
   49: }
   50: 
   51: void
   52: lsa_ntoh_body(void *n, void *h, u16 len)
   53: {
   54:   u32 *nid = n;
   55:   u32 *hid = h;
   56:   uint i;
   57: 
   58:   for (i = 0; i < (len / sizeof(u32)); i++)
   59:     hid[i] = ntohl(nid[i]);
   60: }
   61: #endif /* little endian */
   62: 
   63: 
   64: 
   65: int
   66: lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa)
   67: {
   68:   /* Handle inactive vlinks */
   69:   if (ifa->state == OSPF_IS_DOWN)
   70:     return 0;
   71: 
   72:   /* 4.5.2 (Case 2) */
   73:   switch (LSA_SCOPE(type))
   74:   {
   75:   case LSA_SCOPE_LINK:
   76:     return ifa->iface_id == domain;
   77: 
   78:   case LSA_SCOPE_AREA:
   79:     return ifa->oa->areaid == domain;
   80: 
   81:   case LSA_SCOPE_AS:
   82:     if (ifa->type == OSPF_IT_VLINK)
   83:       return 0;
   84:     if (!oa_is_ext(ifa->oa))
   85:       return 0;
   86:     return 1;
   87: 
   88:   default:
   89:     log(L_ERR "OSPF: LSA with invalid scope");
   90:     return 0;
   91:   }
   92: }
   93: 
   94: 
   95: static int
   96: unknown_lsa_type(u32 type)
   97: {
   98:   switch (type)
   99:   {
  100:   case LSA_T_RT:
  101:   case LSA_T_NET:
  102:   case LSA_T_SUM_NET:
  103:   case LSA_T_SUM_RT:
  104:   case LSA_T_EXT:
  105:   case LSA_T_NSSA:
  106:   case LSA_T_LINK:
  107:   case LSA_T_PREFIX:
  108:     return 0;
  109: 
  110:   default:
  111:     return 1;
  112:   }
  113: }
  114: 
  115: #define LSA_V2_TMAX 8
  116: static const u16 lsa_v2_types[LSA_V2_TMAX] =
  117:   {0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA};
  118: 
  119: void
  120: lsa_get_type_domain_(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain)
  121: {
  122:   if (ospf_is_v2(ifa->oa->po))
  123:   {
  124:     itype = itype & LSA_T_V2_MASK;
  125:     itype = (itype < LSA_V2_TMAX) ? lsa_v2_types[itype] : 0;
  126:   }
  127:   else
  128:   {
  129:     /* For unkown LSAs without U-bit change scope to LSA_SCOPE_LINK */
  130:     if (unknown_lsa_type(itype) && !(itype & LSA_UBIT))
  131:       itype = itype & ~LSA_SCOPE_MASK;
  132:   }
  133: 
  134:   *otype = itype;
  135: 
  136:   switch (LSA_SCOPE(itype))
  137:   {
  138:   case LSA_SCOPE_LINK:
  139:     *domain = ifa->iface_id;
  140:     return;
  141: 
  142:   case LSA_SCOPE_AREA:
  143:     *domain = ifa->oa->areaid;
  144:     return;
  145: 
  146:   case LSA_SCOPE_AS:
  147:   default:
  148:     *domain = 0;
  149:     return;
  150:   }
  151: }
  152: 
  153: 
  154: void
  155: lsa_generate_checksum(struct ospf_lsa_header *lsa, const u8 *body)
  156: {
  157:   struct fletcher16_context ctx;
  158:   struct ospf_lsa_header hdr;
  159:   u16 len = lsa->length;
  160: 
  161:   /*
  162:    * lsa and body are in the host order, we need to compute Fletcher-16 checksum
  163:    * for data in the network order. We also skip the initial age field.
  164:    */
  165: 
  166:   lsa_hton_hdr(lsa, &hdr);
  167:   hdr.checksum = 0;
  168: 
  169:   fletcher16_init(&ctx);
  170:   fletcher16_update(&ctx, (u8 *) &hdr + 2, sizeof(struct ospf_lsa_header) - 2);
  171:   fletcher16_update_n32(&ctx, body, len - sizeof(struct ospf_lsa_header));
  172:   lsa->checksum = fletcher16_final(&ctx, len, OFFSETOF(struct ospf_lsa_header, checksum));
  173: }
  174: 
  175: u16
  176: lsa_verify_checksum(const void *lsa_n, int lsa_len)
  177: {
  178:   struct fletcher16_context ctx;
  179: 
  180:   /* The whole LSA is at lsa_n in net order, we just skip initial age field */
  181: 
  182:   fletcher16_init(&ctx);
  183:   fletcher16_update(&ctx, (u8 *) lsa_n + 2, lsa_len - 2);
  184: 
  185:   return fletcher16_compute(&ctx) == 0;
  186: }
  187: 
  188: 
  189: int
  190: lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
  191: 			/* Return codes from point of view of l1 */
  192: {
  193:   u32 sn1, sn2;
  194: 
  195:   sn1 = l1->sn - LSA_INITSEQNO + 1;
  196:   sn2 = l2->sn - LSA_INITSEQNO + 1;
  197: 
  198:   if (sn1 > sn2)
  199:     return CMP_NEWER;
  200:   if (sn1 < sn2)
  201:     return CMP_OLDER;
  202: 
  203:   if (l1->checksum != l2->checksum)
  204:     return l1->checksum < l2->checksum ? CMP_OLDER : CMP_NEWER;
  205: 
  206:   if ((l1->age == LSA_MAXAGE) && (l2->age != LSA_MAXAGE))
  207:     return CMP_NEWER;
  208:   if ((l2->age == LSA_MAXAGE) && (l1->age != LSA_MAXAGE))
  209:     return CMP_OLDER;
  210: 
  211:   if (ABS(l1->age - l2->age) > LSA_MAXAGEDIFF)
  212:     return l1->age < l2->age ? CMP_NEWER : CMP_OLDER;
  213: 
  214:   return CMP_SAME;
  215: }
  216: 
  217: 
  218: static inline int
  219: lsa_walk_rt2(struct ospf_lsa_rt_walk *rt)
  220: {
  221:   if (rt->buf >= rt->bufend)
  222:     return 0;
  223: 
  224:   struct ospf_lsa_rt2_link *l = rt->buf;
  225:   rt->buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
  226: 
  227:   rt->type = l->type;
  228:   rt->metric = l->metric;
  229:   rt->id = l->id;
  230:   rt->data = l->data;
  231:   return 1;
  232: }
  233: 
  234: static inline int
  235: lsa_walk_rt3(struct ospf_lsa_rt_walk *rt)
  236: {
  237:   while (rt->buf >= rt->bufend)
  238:   {
  239:     rt->en = ospf_hash_find_rt3_next(rt->en);
  240:     if (!rt->en)
  241:       return 0;
  242: 
  243:     rt->buf = rt->en->lsa_body;
  244:     rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
  245:     rt->buf += sizeof(struct ospf_lsa_rt);
  246:   }
  247: 
  248:   struct ospf_lsa_rt3_link *l = rt->buf;
  249:   rt->buf += sizeof(struct ospf_lsa_rt3_link);
  250: 
  251:   rt->type = l->type;
  252:   rt->metric = l->metric;
  253:   rt->lif = l->lif;
  254:   rt->nif = l->nif;
  255:   rt->id = l->id;
  256:   return 1;
  257: }
  258: 
  259: void
  260: lsa_walk_rt_init(struct ospf_proto *p, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt)
  261: {
  262:   rt->ospf2 = ospf_is_v2(p);
  263:   rt->id = rt->data = rt->lif = rt->nif = 0;
  264: 
  265:   if (rt->ospf2)
  266:     rt->en = act;
  267:   else
  268:     rt->en = ospf_hash_find_rt3_first(p->gr, act->domain, act->lsa.rt);
  269: 
  270:   rt->buf = rt->en->lsa_body;
  271:   rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
  272:   rt->buf += sizeof(struct ospf_lsa_rt);
  273: }
  274: 
  275: int
  276: lsa_walk_rt(struct ospf_lsa_rt_walk *rt)
  277: {
  278:   return rt->ospf2 ? lsa_walk_rt2(rt) : lsa_walk_rt3(rt);
  279: }
  280: 
  281: 
  282: void
  283: lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric)
  284: {
  285:   if (ospf2)
  286:   {
  287:     struct ospf_lsa_sum2 *ls = en->lsa_body;
  288:     *ip = ipa_from_u32(en->lsa.id & ls->netmask);
  289:     *pxlen = u32_masklen(ls->netmask);
  290:     *pxopts = 0;
  291:     *metric = ls->metric & LSA_METRIC_MASK;
  292:   }
  293:   else
  294:   {
  295:     struct ospf_lsa_sum3_net *ls = en->lsa_body;
  296:     u16 rest;
  297:     lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest);
  298:     *metric = ls->metric & LSA_METRIC_MASK;
  299:   }
  300: }
  301: 
  302: void
  303: lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options)
  304: {
  305:   if (ospf2)
  306:   {
  307:     struct ospf_lsa_sum2 *ls = en->lsa_body;
  308:     *drid = en->lsa.id;
  309:     *metric = ls->metric & LSA_METRIC_MASK;
  310:     *options = 0;
  311:   }
  312:   else
  313:   {
  314:     struct ospf_lsa_sum3_rt *ls = en->lsa_body;
  315:     *drid = ls->drid;
  316:     *metric = ls->metric & LSA_METRIC_MASK;
  317:     *options = ls->options & LSA_OPTIONS_MASK;
  318:   }
  319: }
  320: 
  321: void
  322: lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt)
  323: {
  324:   if (ospf2)
  325:   {
  326:     struct ospf_lsa_ext2 *ext = en->lsa_body;
  327:     rt->ip = ipa_from_u32(en->lsa.id & ext->netmask);
  328:     rt->pxlen = u32_masklen(ext->netmask);
  329:     rt->pxopts = 0;
  330:     rt->metric = ext->metric & LSA_METRIC_MASK;
  331:     rt->ebit = ext->metric & LSA_EXT2_EBIT;
  332: 
  333:     rt->fbit = ext->fwaddr;
  334:     rt->fwaddr = ipa_from_u32(ext->fwaddr);
  335: 
  336:     rt->tag = ext->tag;
  337:     rt->propagate = lsa_get_options(&en->lsa) & OPT_P;
  338:   }
  339:   else
  340:   {
  341:     struct ospf_lsa_ext3 *ext = en->lsa_body;
  342:     u16 rest;
  343:     u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest);
  344:     rt->metric = ext->metric & LSA_METRIC_MASK;
  345:     rt->ebit = ext->metric & LSA_EXT3_EBIT;
  346: 
  347:     rt->fbit = ext->metric & LSA_EXT3_FBIT;
  348:     if (rt->fbit)
  349:       buf = lsa_get_ipv6_addr(buf, &rt->fwaddr);
  350:     else
  351:       rt->fwaddr = IPA_NONE;
  352: 
  353:     rt->tag = (ext->metric & LSA_EXT3_TBIT) ? *buf++ : 0;
  354:     rt->propagate = rt->pxopts & OPT_PX_P;
  355:   }
  356: }
  357: 
  358: #define HDRLEN sizeof(struct ospf_lsa_header)
  359: 
  360: static int
  361: lsa_validate_rt2(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
  362: {
  363:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
  364:     return 0;
  365: 
  366:   uint i = 0;
  367:   void *buf = body;
  368:   void *bufend = buf + lsa->length - HDRLEN;
  369:   buf += sizeof(struct ospf_lsa_rt);
  370: 
  371:   while (buf < bufend)
  372:   {
  373:     struct ospf_lsa_rt2_link *l = buf;
  374:     buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
  375:     i++;
  376: 
  377:     if (buf > bufend)
  378:       return 0;
  379: 
  380:     if (!((l->type == LSART_PTP) ||
  381: 	  (l->type == LSART_NET) ||
  382: 	  (l->type == LSART_STUB) ||
  383: 	  (l->type == LSART_VLNK)))
  384:       return 0;
  385:   }
  386: 
  387:   if ((body->options & LSA_RT2_LINKS) != i)
  388:     return 0;
  389: 
  390:   return 1;
  391: }
  392: 
  393: 
  394: static int
  395: lsa_validate_rt3(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
  396: {
  397:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
  398:     return 0;
  399: 
  400:   void *buf = body;
  401:   void *bufend = buf + lsa->length - HDRLEN;
  402:   buf += sizeof(struct ospf_lsa_rt);
  403: 
  404:   while (buf < bufend)
  405:   {
  406:     struct ospf_lsa_rt3_link *l = buf;
  407:     buf += sizeof(struct ospf_lsa_rt3_link);
  408: 
  409:     if (buf > bufend)
  410:       return 0;
  411: 
  412:     if (!((l->type == LSART_PTP) ||
  413: 	  (l->type == LSART_NET) ||
  414: 	  (l->type == LSART_VLNK)))
  415:       return 0;
  416:   }
  417:   return 1;
  418: }
  419: 
  420: static int
  421: lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body UNUSED)
  422: {
  423:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_net)))
  424:     return 0;
  425: 
  426:   return 1;
  427: }
  428: 
  429: static int
  430: lsa_validate_sum2(struct ospf_lsa_header *lsa, struct ospf_lsa_sum2 *body)
  431: {
  432:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum2)))
  433:     return 0;
  434: 
  435:   /* First field should have TOS = 0, we ignore other TOS fields */
  436:   if ((body->metric & LSA_SUM2_TOS) != 0)
  437:     return 0;
  438: 
  439:   return 1;
  440: }
  441: 
  442: static inline int
  443: pxlen(u32 *buf)
  444: {
  445:   return *buf >> 24;
  446: }
  447: 
  448: static int
  449: lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
  450: {
  451:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + 4))
  452:     return 0;
  453: 
  454:   u8 pxl = pxlen(body->prefix);
  455:   if (pxl > MAX_PREFIX_LENGTH)
  456:     return 0;
  457: 
  458:   if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) +
  459: 		      IPV6_PREFIX_SPACE(pxl)))
  460:     return 0;
  461: 
  462:   return 1;
  463: }
  464: 
  465: static int
  466: lsa_validate_sum3_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body UNUSED)
  467: {
  468:   if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt)))
  469:     return 0;
  470: 
  471:   return 1;
  472: }
  473: 
  474: static int
  475: lsa_validate_ext2(struct ospf_lsa_header *lsa, struct ospf_lsa_ext2 *body)
  476: {
  477:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext2)))
  478:     return 0;
  479: 
  480:   /* First field should have TOS = 0, we ignore other TOS fields */
  481:   if ((body->metric & LSA_EXT2_TOS) != 0)
  482:     return 0;
  483: 
  484:   return 1;
  485: }
  486: 
  487: static int
  488: lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
  489: {
  490:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext3) + 4))
  491:     return 0;
  492: 
  493:   u8 pxl = pxlen(body->rest);
  494:   if (pxl > MAX_PREFIX_LENGTH)
  495:     return 0;
  496: 
  497:   int len = IPV6_PREFIX_SPACE(pxl);
  498:   if (body->metric & LSA_EXT3_FBIT) // forwardinf address
  499:     len += 16;
  500:   if (body->metric & LSA_EXT3_TBIT) // route tag
  501:     len += 4;
  502:   if (*body->rest & 0xFFFF) // referenced LS type field
  503:     len += 4;
  504: 
  505:   if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext3) + len))
  506:     return 0;
  507: 
  508:   return 1;
  509: }
  510: 
  511: static int
  512: lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, uint offset, u8 *pbuf)
  513: {
  514:   uint bound = lsa->length - HDRLEN - 4;
  515:   u32 i;
  516: 
  517:   for (i = 0; i < pxcount; i++)
  518:     {
  519:       if (offset > bound)
  520: 	return 0;
  521: 
  522:       u8 pxl = pxlen((u32 *) (pbuf + offset));
  523:       if (pxl > MAX_PREFIX_LENGTH)
  524: 	return 0;
  525: 
  526:       offset += IPV6_PREFIX_SPACE(pxl);
  527:     }
  528: 
  529:   if (lsa->length != (HDRLEN + offset))
  530:     return 0;
  531: 
  532:   return 1;
  533: }
  534: 
  535: static int
  536: lsa_validate_link(struct ospf_lsa_header *lsa, struct ospf_lsa_link *body)
  537: {
  538:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_link)))
  539:     return 0;
  540: 
  541:   return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_link), (u8 *) body);
  542: }
  543: 
  544: static int
  545: lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
  546: {
  547:   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_prefix)))
  548:     return 0;
  549: 
  550:   return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body);
  551: }
  552: 
  553: 
  554: /**
  555:  * lsa_validate - check whether given LSA is valid
  556:  * @lsa: LSA header
  557:  * @lsa_type: one of %LSA_T_xxx
  558:  * @ospf2: %true means OSPF version 2, %false means OSPF version 3
  559:  * @body: pointer to LSA body
  560:  *
  561:  * Checks internal structure of given LSA body (minimal length,
  562:  * consistency). Returns true if valid.
  563:  */
  564: int
  565: lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body)
  566: {
  567:   if (ospf2)
  568:   {
  569:     switch (lsa_type)
  570:     {
  571:     case LSA_T_RT:
  572:       return lsa_validate_rt2(lsa, body);
  573:     case LSA_T_NET:
  574:       return lsa_validate_net(lsa, body);
  575:     case LSA_T_SUM_NET:
  576:       return lsa_validate_sum2(lsa, body);
  577:     case LSA_T_SUM_RT:
  578:       return lsa_validate_sum2(lsa, body);
  579:     case LSA_T_EXT:
  580:     case LSA_T_NSSA:
  581:       return lsa_validate_ext2(lsa, body);
  582:     default:
  583:       return 0;	/* Should not happen, unknown LSAs are already rejected */
  584:     }
  585:   }
  586:   else
  587:   {
  588:     switch (lsa_type)
  589:     {
  590:     case LSA_T_RT:
  591:       return lsa_validate_rt3(lsa, body);
  592:     case LSA_T_NET:
  593:       return lsa_validate_net(lsa, body);
  594:     case LSA_T_SUM_NET:
  595:       return lsa_validate_sum3_net(lsa, body);
  596:     case LSA_T_SUM_RT:
  597:       return lsa_validate_sum3_rt(lsa, body);
  598:     case LSA_T_EXT:
  599:     case LSA_T_NSSA:
  600:       return lsa_validate_ext3(lsa, body);
  601:     case LSA_T_LINK:
  602:       return lsa_validate_link(lsa, body);
  603:     case LSA_T_PREFIX:
  604:       return lsa_validate_prefix(lsa, body);
  605:     default:
  606:       return 1;	/* Unknown LSAs are OK in OSPFv3 */
  607:     }
  608:   }
  609: }

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