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>