Annotation of embedaddon/bird/proto/ospf/lsalib.c, revision 1.1

1.1     ! misho       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>