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: #define HDRLEN sizeof(struct ospf_lsa_header)
16:
17:
18: #ifndef CPU_BIG_ENDIAN
19: void
20: lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
21: {
22: n->age = htons(h->age);
23: n->type_raw = htons(h->type_raw);
24: n->id = htonl(h->id);
25: n->rt = htonl(h->rt);
26: n->sn = htonl(h->sn);
27: n->checksum = htons(h->checksum);
28: n->length = htons(h->length);
29: }
30:
31: void
32: lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
33: {
34: h->age = ntohs(n->age);
35: h->type_raw = ntohs(n->type_raw);
36: h->id = ntohl(n->id);
37: h->rt = ntohl(n->rt);
38: h->sn = ntohl(n->sn);
39: h->checksum = ntohs(n->checksum);
40: h->length = ntohs(n->length);
41: }
42:
43: void
44: lsa_hton_body(void *h, void *n, u16 len)
45: {
46: u32 *hid = h;
47: u32 *nid = n;
48: uint i;
49:
50: for (i = 0; i < (len / sizeof(u32)); i++)
51: nid[i] = htonl(hid[i]);
52: }
53:
54: void
55: lsa_ntoh_body(void *n, void *h, u16 len)
56: {
57: u32 *nid = n;
58: u32 *hid = h;
59: uint i;
60:
61: for (i = 0; i < (len / sizeof(u32)); i++)
62: hid[i] = ntohl(nid[i]);
63: }
64: #endif /* little endian */
65:
66:
67: int
68: lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa)
69: {
70: /* Handle inactive vlinks */
71: if (ifa->state == OSPF_IS_DOWN)
72: return 0;
73:
74: /* 4.5.2 (Case 2) */
75: switch (LSA_SCOPE(type))
76: {
77: case LSA_SCOPE_LINK:
78: return ifa->iface_id == domain;
79:
80: case LSA_SCOPE_AREA:
81: return ifa->oa->areaid == domain;
82:
83: case LSA_SCOPE_AS:
84: if (ifa->type == OSPF_IT_VLINK)
85: return 0;
86: if (!oa_is_ext(ifa->oa))
87: return 0;
88: return 1;
89:
90: default:
91: log(L_ERR "OSPF: LSA with invalid scope");
92: return 0;
93: }
94: }
95:
96: int
97: lsa_is_acceptable(u32 type, struct ospf_neighbor *n, struct ospf_proto *p)
98: {
99: if (ospf_is_v2(p))
100: {
101: /* Do not check NSSA-LSA here, as OPT_N is only in HELLO packets */
102:
103: if (lsa_is_opaque(type))
104: return !!(n->options & OPT_O);
105:
106: return 1;
107: }
108: else
109: {
110: /*
111: * There should be check whether receiving router understands that type
112: * of LSA (for LSA types with U-bit == 0). But as we do not support any
113: * optional LSA types, this is not needed yet.
114: */
115:
116: return 1;
117: }
118: }
119:
120: static int
121: unknown_lsa_type(u32 type)
122: {
123: switch (type)
124: {
125: case LSA_T_RT:
126: case LSA_T_NET:
127: case LSA_T_SUM_NET:
128: case LSA_T_SUM_RT:
129: case LSA_T_EXT:
130: case LSA_T_NSSA:
131: case LSA_T_LINK:
132: case LSA_T_PREFIX:
133: case LSA_T_RI_LINK:
134: case LSA_T_RI_AREA:
135: case LSA_T_RI_AS:
136: return 0;
137:
138: default:
139: return 1;
140: }
141: }
142:
143: /* Maps OSPFv2 types to OSPFv3 types */
144: static const u16 lsa_v2_types[] = {
145: 0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA,
146: 0, LSA_T_OPAQUE_LINK, LSA_T_OPAQUE_AREA, LSA_T_OPAQUE_AS
147: };
148:
149: /* Maps OSPFv2 opaque types to OSPFv3 function codes */
150: static const u16 opaque_lsa_types[] = {
151: [LSA_OT_GR] = LSA_T_GR,
152: [LSA_OT_RI] = LSA_T_RI_,
153: };
154:
155: /* Maps (subset of) OSPFv3 function codes to OSPFv2 opaque types */
156: static const u8 opaque_lsa_types_inv[] = {
157: [LSA_T_GR] = LSA_OT_GR,
158: [LSA_T_RI_] = LSA_OT_RI,
159: };
160:
161: #define LOOKUP(a, i) ({ uint _i = (i); (_i < ARRAY_SIZE(a)) ? a[_i] : 0; })
162:
163: void
164: lsa_get_type_domain_(u32 type, u32 id, struct ospf_iface *ifa, u32 *otype, u32 *domain)
165: {
166: if (ospf_is_v2(ifa->oa->po))
167: {
168: type = type & LSA_T_V2_MASK;
169: type = LOOKUP(lsa_v2_types, type);
170:
171: uint code;
172: if (LSA_FUNCTION(type) == LSA_T_OPAQUE_)
173: if (code = LOOKUP(opaque_lsa_types, id >> 24))
174: {
175: type = code | LSA_UBIT | LSA_SCOPE(type);
176:
177: /* Hack for Grace-LSA: It does not use U-bit for link-scoped LSAs */
178: if (type == (LSA_T_GR | LSA_UBIT))
179: type = LSA_T_GR;
180: }
181: }
182: else
183: {
184: /* For unkown LSAs without U-bit change scope to LSA_SCOPE_LINK */
185: if (unknown_lsa_type(type) && !(type & LSA_UBIT))
186: type = type & ~LSA_SCOPE_MASK;
187: }
188:
189: *otype = type;
190:
191: switch (LSA_SCOPE(type))
192: {
193: case LSA_SCOPE_LINK:
194: *domain = ifa->iface_id;
195: return;
196:
197: case LSA_SCOPE_AREA:
198: *domain = ifa->oa->areaid;
199: return;
200:
201: case LSA_SCOPE_AS:
202: default:
203: *domain = 0;
204: return;
205: }
206: }
207:
208: int
209: lsa_is_opaque(u32 type)
210: {
211: u32 fn = LSA_FUNCTION(type);
212: return LOOKUP(opaque_lsa_types_inv, fn) || (fn == LSA_T_OPAQUE_);
213: }
214:
215: u32
216: lsa_get_opaque_type(u32 type)
217: {
218: return LOOKUP(opaque_lsa_types_inv, LSA_FUNCTION(type));
219: }
220:
221:
222: void
223: lsa_generate_checksum(struct ospf_lsa_header *lsa, const u8 *body)
224: {
225: struct fletcher16_context ctx;
226: struct ospf_lsa_header hdr;
227: u16 len = lsa->length;
228:
229: /*
230: * lsa and body are in the host order, we need to compute Fletcher-16 checksum
231: * for data in the network order. We also skip the initial age field.
232: */
233:
234: lsa_hton_hdr(lsa, &hdr);
235: hdr.checksum = 0;
236:
237: fletcher16_init(&ctx);
238: fletcher16_update(&ctx, (u8 *) &hdr + 2, sizeof(struct ospf_lsa_header) - 2);
239: fletcher16_update_n32(&ctx, body, len - sizeof(struct ospf_lsa_header));
240: lsa->checksum = fletcher16_final(&ctx, len, OFFSETOF(struct ospf_lsa_header, checksum));
241: }
242:
243: u16
244: lsa_verify_checksum(const void *lsa_n, int lsa_len)
245: {
246: struct fletcher16_context ctx;
247:
248: /* The whole LSA is at lsa_n in net order, we just skip initial age field */
249:
250: fletcher16_init(&ctx);
251: fletcher16_update(&ctx, (u8 *) lsa_n + 2, lsa_len - 2);
252:
253: return fletcher16_compute(&ctx) == 0;
254: }
255:
256:
257: int
258: lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
259: /* Return codes from point of view of l1 */
260: {
261: u32 sn1, sn2;
262:
263: sn1 = l1->sn - LSA_INITSEQNO + 1;
264: sn2 = l2->sn - LSA_INITSEQNO + 1;
265:
266: if (sn1 > sn2)
267: return CMP_NEWER;
268: if (sn1 < sn2)
269: return CMP_OLDER;
270:
271: if (l1->checksum != l2->checksum)
272: return l1->checksum < l2->checksum ? CMP_OLDER : CMP_NEWER;
273:
274: if ((l1->age == LSA_MAXAGE) && (l2->age != LSA_MAXAGE))
275: return CMP_NEWER;
276: if ((l2->age == LSA_MAXAGE) && (l1->age != LSA_MAXAGE))
277: return CMP_OLDER;
278:
279: if (ABS(l1->age - l2->age) > LSA_MAXAGEDIFF)
280: return l1->age < l2->age ? CMP_NEWER : CMP_OLDER;
281:
282: return CMP_SAME;
283: }
284:
285:
286: #define LSA_TLV_LENGTH(tlv) \
287: (sizeof(struct ospf_tlv) + BIRD_ALIGN((tlv)->length, 4))
288:
289: #define LSA_NEXT_TLV(tlv) \
290: ((struct ospf_tlv *) ((byte *) (tlv) + LSA_TLV_LENGTH(tlv)))
291:
292: #define LSA_WALK_TLVS(tlv,buf,len) \
293: for(struct ospf_tlv *tlv = (void *) (buf); \
294: (byte *) tlv < (byte *) (buf) + (len); \
295: tlv = LSA_NEXT_TLV(tlv))
296:
297: struct ospf_tlv *
298: lsa_get_tlv(struct top_hash_entry *en, uint type)
299: {
300: LSA_WALK_TLVS(tlv, en->lsa_body, en->lsa.length - HDRLEN)
301: if (tlv->type == type)
302: return tlv;
303:
304: return NULL;
305: }
306:
307: int
308: lsa_validate_tlvs(byte *buf, uint len)
309: {
310: byte *pos = buf;
311: byte *end = buf + len;
312:
313: while (pos < end)
314: {
315: if ((pos + sizeof(struct ospf_tlv)) > end)
316: return 0;
317:
318: struct ospf_tlv *tlv = (void *) pos;
319: uint len = LSA_TLV_LENGTH(tlv);
320:
321: if ((pos + len) > end)
322: return 0;
323:
324: pos += len;
325: }
326:
327: return 1;
328: }
329:
330:
331: static inline int
332: lsa_walk_rt2(struct ospf_lsa_rt_walk *rt)
333: {
334: if (rt->buf >= rt->bufend)
335: return 0;
336:
337: struct ospf_lsa_rt2_link *l = rt->buf;
338: rt->buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
339:
340: rt->type = l->type;
341: rt->metric = l->metric;
342: rt->id = l->id;
343: rt->data = l->data;
344: return 1;
345: }
346:
347: static inline int
348: lsa_walk_rt3(struct ospf_lsa_rt_walk *rt)
349: {
350: while (rt->buf >= rt->bufend)
351: {
352: rt->en = ospf_hash_find_rt3_next(rt->en);
353: if (!rt->en)
354: return 0;
355:
356: rt->buf = rt->en->lsa_body;
357: rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
358: rt->buf += sizeof(struct ospf_lsa_rt);
359: }
360:
361: struct ospf_lsa_rt3_link *l = rt->buf;
362: rt->buf += sizeof(struct ospf_lsa_rt3_link);
363:
364: rt->type = l->type;
365: rt->metric = l->metric;
366: rt->lif = l->lif;
367: rt->nif = l->nif;
368: rt->id = l->id;
369: return 1;
370: }
371:
372: void
373: lsa_walk_rt_init(struct ospf_proto *p, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt)
374: {
375: rt->ospf2 = ospf_is_v2(p);
376: rt->id = rt->data = rt->lif = rt->nif = 0;
377:
378: if (rt->ospf2)
379: rt->en = act;
380: else
381: rt->en = ospf_hash_find_rt3_first(p->gr, act->domain, act->lsa.rt);
382:
383: rt->buf = rt->en->lsa_body;
384: rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
385: rt->buf += sizeof(struct ospf_lsa_rt);
386: }
387:
388: int
389: lsa_walk_rt(struct ospf_lsa_rt_walk *rt)
390: {
391: return rt->ospf2 ? lsa_walk_rt2(rt) : lsa_walk_rt3(rt);
392: }
393:
394:
395: void
396: lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, int af, net_addr *net, u8 *pxopts, u32 *metric)
397: {
398: if (ospf2)
399: {
400: uint opts = lsa_get_options(&en->lsa);
401: struct ospf_lsa_sum2 *ls = en->lsa_body;
402: net_fill_ip4(net, ip4_from_u32(en->lsa.id & ls->netmask), u32_masklen(ls->netmask));
403: *pxopts = (opts & OPT_DN) ? OPT_PX_DN : 0;
404: *metric = ls->metric & LSA_METRIC_MASK;
405: }
406: else
407: {
408: struct ospf_lsa_sum3_net *ls = en->lsa_body;
409: ospf3_get_prefix(ls->prefix, af, net, pxopts, NULL);
410: *metric = ls->metric & LSA_METRIC_MASK;
411: }
412: }
413:
414: void
415: lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options)
416: {
417: if (ospf2)
418: {
419: struct ospf_lsa_sum2 *ls = en->lsa_body;
420: *drid = en->lsa.id;
421: *metric = ls->metric & LSA_METRIC_MASK;
422: *options = 0;
423: }
424: else
425: {
426: struct ospf_lsa_sum3_rt *ls = en->lsa_body;
427: *drid = ls->drid;
428: *metric = ls->metric & LSA_METRIC_MASK;
429: *options = ls->options & LSA_OPTIONS_MASK;
430: }
431: }
432:
433: void
434: lsa_parse_ext(struct top_hash_entry *en, int ospf2, int af, struct ospf_lsa_ext_local *rt)
435: {
436: if (ospf2)
437: {
438: struct ospf_lsa_ext2 *ext = en->lsa_body;
439: net_fill_ip4(&rt->net,
440: ip4_from_u32(en->lsa.id & ext->netmask),
441: u32_masklen(ext->netmask));
442: rt->pxopts = 0;
443: rt->metric = ext->metric & LSA_METRIC_MASK;
444: rt->ebit = ext->metric & LSA_EXT2_EBIT;
445:
446: rt->fbit = ext->fwaddr;
447: rt->fwaddr = ipa_from_u32(ext->fwaddr);
448:
449: rt->tag = ext->tag;
450: rt->propagate = lsa_get_options(&en->lsa) & OPT_P;
451: rt->downwards = lsa_get_options(&en->lsa) & OPT_DN;
452: }
453: else
454: {
455: struct ospf_lsa_ext3 *ext = en->lsa_body;
456: u32 *buf = ospf3_get_prefix(ext->rest, af, &rt->net, &rt->pxopts, NULL);
457: rt->metric = ext->metric & LSA_METRIC_MASK;
458: rt->ebit = ext->metric & LSA_EXT3_EBIT;
459:
460: rt->fbit = ext->metric & LSA_EXT3_FBIT;
461: if (rt->fbit)
462: buf = ospf3_get_addr(buf, af, &rt->fwaddr);
463: else
464: rt->fwaddr = IPA_NONE;
465:
466: rt->tag = (ext->metric & LSA_EXT3_TBIT) ? *buf++ : 0;
467: rt->propagate = rt->pxopts & OPT_PX_P;
468: rt->downwards = rt->pxopts & OPT_PX_DN;
469: }
470: }
471:
472:
473: static int
474: lsa_validate_rt2(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
475: {
476: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
477: return 0;
478:
479: uint i = 0;
480: void *buf = body;
481: void *bufend = buf + lsa->length - HDRLEN;
482: buf += sizeof(struct ospf_lsa_rt);
483:
484: while (buf < bufend)
485: {
486: struct ospf_lsa_rt2_link *l = buf;
487: buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
488: i++;
489:
490: if (buf > bufend)
491: return 0;
492:
493: if (!((l->type == LSART_PTP) ||
494: (l->type == LSART_NET) ||
495: (l->type == LSART_STUB) ||
496: (l->type == LSART_VLNK)))
497: return 0;
498: }
499:
500: if ((body->options & LSA_RT2_LINKS) != i)
501: return 0;
502:
503: return 1;
504: }
505:
506:
507: static int
508: lsa_validate_rt3(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
509: {
510: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
511: return 0;
512:
513: void *buf = body;
514: void *bufend = buf + lsa->length - HDRLEN;
515: buf += sizeof(struct ospf_lsa_rt);
516:
517: while (buf < bufend)
518: {
519: struct ospf_lsa_rt3_link *l = buf;
520: buf += sizeof(struct ospf_lsa_rt3_link);
521:
522: if (buf > bufend)
523: return 0;
524:
525: if (!((l->type == LSART_PTP) ||
526: (l->type == LSART_NET) ||
527: (l->type == LSART_VLNK)))
528: return 0;
529: }
530: return 1;
531: }
532:
533: static int
534: lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body UNUSED)
535: {
536: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_net)))
537: return 0;
538:
539: return 1;
540: }
541:
542: static int
543: lsa_validate_sum2(struct ospf_lsa_header *lsa, struct ospf_lsa_sum2 *body)
544: {
545: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum2)))
546: return 0;
547:
548: /* First field should have TOS = 0, we ignore other TOS fields */
549: if ((body->metric & LSA_SUM2_TOS) != 0)
550: return 0;
551:
552: return 1;
553: }
554:
555: static inline int
556: pxlen(u32 *buf)
557: {
558: return *buf >> 24;
559: }
560:
561: static int
562: lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
563: {
564: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + 4))
565: return 0;
566:
567: u8 pxl = pxlen(body->prefix);
568: if (pxl > IP6_MAX_PREFIX_LENGTH)
569: return 0;
570:
571: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) +
572: IPV6_PREFIX_SPACE(pxl)))
573: return 0;
574:
575: return 1;
576: }
577:
578: static int
579: lsa_validate_sum3_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body UNUSED)
580: {
581: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt)))
582: return 0;
583:
584: return 1;
585: }
586:
587: static int
588: lsa_validate_ext2(struct ospf_lsa_header *lsa, struct ospf_lsa_ext2 *body)
589: {
590: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext2)))
591: return 0;
592:
593: /* First field should have TOS = 0, we ignore other TOS fields */
594: if ((body->metric & LSA_EXT2_TOS) != 0)
595: return 0;
596:
597: return 1;
598: }
599:
600: static int
601: lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
602: {
603: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext3) + 4))
604: return 0;
605:
606: u8 pxl = pxlen(body->rest);
607: if (pxl > IP6_MAX_PREFIX_LENGTH)
608: return 0;
609:
610: int len = IPV6_PREFIX_SPACE(pxl);
611: if (body->metric & LSA_EXT3_FBIT) // forwarding address
612: len += 16;
613: if (body->metric & LSA_EXT3_TBIT) // route tag
614: len += 4;
615: if (*body->rest & 0xFFFF) // referenced LS type field
616: len += 4;
617:
618: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext3) + len))
619: return 0;
620:
621: return 1;
622: }
623:
624: static int
625: lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, uint offset, u8 *pbuf)
626: {
627: uint bound = lsa->length - HDRLEN - 4;
628: u32 i;
629:
630: for (i = 0; i < pxcount; i++)
631: {
632: if (offset > bound)
633: return 0;
634:
635: u8 pxl = pxlen((u32 *) (pbuf + offset));
636: if (pxl > IP6_MAX_PREFIX_LENGTH)
637: return 0;
638:
639: offset += IPV6_PREFIX_SPACE(pxl);
640: }
641:
642: if (lsa->length != (HDRLEN + offset))
643: return 0;
644:
645: return 1;
646: }
647:
648: static int
649: lsa_validate_link(struct ospf_lsa_header *lsa, struct ospf_lsa_link *body)
650: {
651: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_link)))
652: return 0;
653:
654: return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_link), (u8 *) body);
655: }
656:
657: static int
658: lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
659: {
660: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_prefix)))
661: return 0;
662:
663: return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body);
664: }
665:
666: static int
667: lsa_validate_gr(struct ospf_lsa_header *lsa, void *body)
668: {
669: return lsa_validate_tlvs(body, lsa->length - HDRLEN);
670: }
671:
672: static int
673: lsa_validate_ri(struct ospf_lsa_header *lsa UNUSED, struct ospf_lsa_net *body UNUSED)
674: {
675: /*
676: * There should be proper validation. But we do not really process RI LSAs, so
677: * we can just accept them like another unknown opaque LSAs.
678: */
679:
680: return 1;
681: }
682:
683:
684: /**
685: * lsa_validate - check whether given LSA is valid
686: * @lsa: LSA header
687: * @lsa_type: internal LSA type (%LSA_T_xxx)
688: * @ospf2: %true for OSPFv2, %false for OSPFv3
689: * @body: pointer to LSA body
690: *
691: * Checks internal structure of given LSA body (minimal length,
692: * consistency). Returns true if valid.
693: */
694: int
695: lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body)
696: {
697: if (ospf2)
698: {
699: switch (lsa_type)
700: {
701: case LSA_T_RT:
702: return lsa_validate_rt2(lsa, body);
703: case LSA_T_NET:
704: return lsa_validate_net(lsa, body);
705: case LSA_T_SUM_NET:
706: return lsa_validate_sum2(lsa, body);
707: case LSA_T_SUM_RT:
708: return lsa_validate_sum2(lsa, body);
709: case LSA_T_EXT:
710: case LSA_T_NSSA:
711: return lsa_validate_ext2(lsa, body);
712: case LSA_T_GR:
713: return lsa_validate_gr(lsa, body);
714: case LSA_T_RI_LINK:
715: case LSA_T_RI_AREA:
716: case LSA_T_RI_AS:
717: return lsa_validate_ri(lsa, body);
718: case LSA_T_OPAQUE_LINK:
719: case LSA_T_OPAQUE_AREA:
720: case LSA_T_OPAQUE_AS:
721: return 1; /* Unknown Opaque LSAs */
722: default:
723: return 0; /* Should not happen, unknown LSAs are already rejected */
724: }
725: }
726: else
727: {
728: switch (lsa_type)
729: {
730: case LSA_T_RT:
731: return lsa_validate_rt3(lsa, body);
732: case LSA_T_NET:
733: return lsa_validate_net(lsa, body);
734: case LSA_T_SUM_NET:
735: return lsa_validate_sum3_net(lsa, body);
736: case LSA_T_SUM_RT:
737: return lsa_validate_sum3_rt(lsa, body);
738: case LSA_T_EXT:
739: case LSA_T_NSSA:
740: return lsa_validate_ext3(lsa, body);
741: case LSA_T_LINK:
742: return lsa_validate_link(lsa, body);
743: case LSA_T_PREFIX:
744: return lsa_validate_prefix(lsa, body);
745: case LSA_T_GR:
746: return lsa_validate_gr(lsa, body);
747: case LSA_T_RI_LINK:
748: case LSA_T_RI_AREA:
749: case LSA_T_RI_AS:
750: return lsa_validate_ri(lsa, body);
751: default:
752: return 1; /* Unknown LSAs are OK in OSPFv3 */
753: }
754: }
755: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>