iof-bird-daemon / proto / ospf / lsalib.c @ 8e433d6a
History | View | Annotate | Download (13.3 KB)
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) |
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 |
} |