Annotation of embedaddon/bird/proto/ospf/lsalib.c, revision 1.1.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>