]> git.ipfire.org Git - thirdparty/bird.git/blame - proto/ospf/lsalib.c
Fix configure to enable warnings and fix most of them.
[thirdparty/bird.git] / proto / ospf / lsalib.c
CommitLineData
f45fd316
OF
1/*
2 * BIRD -- OSPF
3 *
6f3203fa 4 * (c) 1999--2004 Ondrej Filip <feela@network.cz>
f45fd316
OF
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9#include "ospf.h"
10
c45f48fb 11void
86c84d76 12flush_lsa(struct top_hash_entry *en, struct proto_ospf *po)
c45f48fb 13{
86c84d76
OF
14 struct proto *p = &po->proto;
15
2e10a170 16 OSPF_TRACE(D_EVENTS,
34a877cc 17 "Going to remove LSA Type: %04x, Id: %R, Rt: %R, Age: %u, Seqno: 0x%x",
3aab39f5 18 en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
b224ca32 19 s_rem_node(SNODE en);
2e10a170
OF
20 if (en->lsa_body != NULL)
21 mb_free(en->lsa_body);
22 en->lsa_body = NULL;
86c84d76 23 ospf_hash_delete(po->gr, en);
c45f48fb
OF
24}
25
e9ab0b42
OF
26/**
27 * ospf_age
86c84d76 28 * @po: ospf protocol
e9ab0b42 29 *
86c84d76 30 * This function is periodicaly invoked from ospf_disp(). It computes the new
baa5dd6c
OF
31 * age of all LSAs and old (@age is higher than %LSA_MAXAGE) LSAs are flushed
32 * whenever possible. If an LSA originated by the router itself is older
33 * than %LSREFRESHTIME a new instance is originated.
e9ab0b42 34 *
baa5dd6c
OF
35 * The RFC says that a router should check the checksum of every LSA to detect
36 * hardware problems. BIRD does not do this to minimalize CPU utilization.
25a3f3da 37 *
baa5dd6c 38 * If routing table calculation is scheduled, it also invalidates the old routing
25a3f3da 39 * table calculation results.
e9ab0b42 40 */
c45f48fb 41void
86c84d76 42ospf_age(struct proto_ospf *po)
c45f48fb 43{
86c84d76 44 struct proto *p = &po->proto;
2e10a170 45 struct top_hash_entry *en, *nxt;
86c84d76 46 int flush = can_flush_lsa(po);
d1660fd3 47
86c84d76 48 if (po->cleanup) OSPF_TRACE(D_EVENTS, "Running ospf_age cleanup");
025b0e85 49
86c84d76 50 WALK_SLIST_DELSAFE(en, nxt, po->lsal)
c45f48fb 51 {
86c84d76 52 if (po->cleanup)
25a3f3da 53 {
2e10a170
OF
54 en->color = OUTSPF;
55 en->dist = LSINFINITY;
56 en->nhi = NULL;
3b16080c
OF
57 en->nh = IPA_NONE;
58 en->lb = IPA_NONE;
3aab39f5
OZ
59 DBG("Infinitying Type: %u, Id: %R, Rt: %R\n", en->lsa.type,
60 en->lsa.id, en->lsa.rt);
25a3f3da 61 }
2e10a170 62 if (en->lsa.age == LSA_MAXAGE)
d1660fd3 63 {
2e10a170 64 if (flush)
86c84d76 65 flush_lsa(en, po);
2eac33f7 66 continue;
d1660fd3 67 }
8a70a13e 68 if ((en->lsa.rt == po->router_id) && (en->lsa.age >= LSREFRESHTIME))
d1660fd3 69 {
3aab39f5
OZ
70 OSPF_TRACE(D_EVENTS, "Refreshing my LSA: Type: %u, Id: %R, Rt: %R",
71 en->lsa.type, en->lsa.id, en->lsa.rt);
2e10a170
OF
72 en->lsa.sn++;
73 en->lsa.age = 0;
74 en->inst_t = now;
75 en->ini_age = 0;
d5d9693c 76 lsasum_calculate(&en->lsa, en->lsa_body);
c3226991 77 ospf_lsupd_flood(po, NULL, NULL, &en->lsa, en->domain, 1);
2e10a170 78 continue;
d1660fd3 79 }
2e10a170 80 if ((en->lsa.age = (en->ini_age + (now - en->inst_t))) >= LSA_MAXAGE)
d1660fd3 81 {
2e10a170 82 if (flush)
dab66519 83 {
86c84d76 84 flush_lsa(en, po);
b8f17cf1 85 schedule_rtcalc(po);
dab66519 86 }
2e10a170
OF
87 else
88 en->lsa.age = LSA_MAXAGE;
d1660fd3 89 }
c45f48fb 90 }
86c84d76 91 po->cleanup = 0;
c45f48fb
OF
92}
93
f45fd316
OF
94void
95htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
96{
2e10a170 97 n->age = htons(h->age);
c3226991 98#ifdef OSPFv2
2e10a170 99 n->options = h->options;
c3226991 100#endif
061ab802 101 n->type = htont(h->type);
2e10a170
OF
102 n->id = htonl(h->id);
103 n->rt = htonl(h->rt);
104 n->sn = htonl(h->sn);
105 n->checksum = htons(h->checksum);
106 n->length = htons(h->length);
c15e5690 107}
f45fd316
OF
108
109void
110ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
111{
2e10a170 112 h->age = ntohs(n->age);
c3226991 113#ifdef OSPFv2
2e10a170 114 h->options = n->options;
c3226991 115#endif
061ab802 116 h->type = ntoht(n->type);
2e10a170
OF
117 h->id = ntohl(n->id);
118 h->rt = ntohl(n->rt);
119 h->sn = ntohl(n->sn);
120 h->checksum = ntohs(n->checksum);
121 h->length = ntohs(n->length);
c15e5690 122}
f45fd316
OF
123
124void
e81b440f 125htonlsab(void *h, void *n, u16 len)
f45fd316 126{
c15e5690
OZ
127 u32 *hid = h;
128 u32 *nid = n;
e81b440f 129 unsigned i;
f45fd316 130
c15e5690
OZ
131 for (i = 0; i < (len / sizeof(u32)); i++)
132 nid[i] = htonl(hid[i]);
133}
f45fd316
OF
134
135void
e81b440f 136ntohlsab(void *n, void *h, u16 len)
f45fd316 137{
c15e5690
OZ
138 u32 *nid = n;
139 u32 *hid = h;
e81b440f 140 unsigned i;
f45fd316 141
c15e5690
OZ
142 for (i = 0; i < (len / sizeof(u32)); i++)
143 hid[i] = ntohl(nid[i]);
144}
f45fd316 145
34a877cc 146/*
061ab802
OZ
147void
148buf_dump(const char *hdr, const byte *buf, int blen)
149{
150 char b2[1024];
151 char *bp;
152 int first = 1;
153 int i;
154
155 const char *lhdr = hdr;
156
157 bp = b2;
158 for(i = 0; i < blen; i++)
159 {
160 if ((i > 0) && ((i % 16) == 0))
161 {
162 *bp = 0;
163 log(L_WARN "%s\t%s", lhdr, b2);
164 lhdr = "";
165 bp = b2;
166 }
167
168 bp += snprintf(bp, 1022, "%02x ", buf[i]);
169
170 }
171
172 *bp = 0;
173 log(L_WARN "%s\t%s", lhdr, b2);
174}
34a877cc 175*/
061ab802 176
499cb346
OF
177#define MODX 4102 /* larges signed value without overflow */
178
179/* Fletcher Checksum -- Refer to RFC1008. */
180#define MODX 4102
181#define LSA_CHECKSUM_OFFSET 15
182
183/* FIXME This is VERY uneficient, I have huge endianity problems */
499cb346 184void
d5d9693c 185lsasum_calculate(struct ospf_lsa_header *h, void *body)
394acced 186{
061ab802 187 u16 length = h->length;
2e10a170 188
f9c799a0 189 // log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
2e10a170 190 htonlsah(h, h);
e81b440f 191 htonlsab(body, body, length - sizeof(struct ospf_lsa_header));
061ab802 192
f9c799a0 193 /*
061ab802
OZ
194 char buf[1024];
195 memcpy(buf, h, sizeof(struct ospf_lsa_header));
196 memcpy(buf + sizeof(struct ospf_lsa_header), body, length - sizeof(struct ospf_lsa_header));
197 buf_dump("CALC", buf, length);
f9c799a0 198 */
394acced 199
d5d9693c 200 (void) lsasum_check(h, body);
2e10a170 201
f9c799a0 202 // log(L_WARN "Checksum result %4x", h->checksum);
061ab802 203
2e10a170 204 ntohlsah(h, h);
e81b440f 205 ntohlsab(body, body, length - sizeof(struct ospf_lsa_header));
394acced
OF
206}
207
208/*
209 * Note, that this function expects that LSA is in big endianity
210 * It also returns value in big endian
211 */
212u16
d5d9693c 213lsasum_check(struct ospf_lsa_header *h, void *body)
499cb346
OF
214{
215 u8 *sp, *ep, *p, *q, *b;
216 int c0 = 0, c1 = 0;
217 int x, y;
c11007bc 218 u16 length;
499cb346 219
c11007bc 220 b = body;
061ab802 221 sp = (char *) h;
c3226991 222 sp += 2; /* Skip Age field */
2e10a170 223 length = ntohs(h->length) - 2;
394acced 224 h->checksum = 0;
499cb346
OF
225
226 for (ep = sp + length; sp < ep; sp = q)
2e10a170 227 { /* Actually MODX is very large, do we need the for-cyclus? */
394acced 228 q = sp + MODX;
2e10a170
OF
229 if (q > ep)
230 q = ep;
394acced 231 for (p = sp; p < q; p++)
499cb346 232 {
394acced
OF
233 /*
234 * I count with bytes from header and than from body
235 * but if there is no body, it's appended to header
236 * (probably checksum in update receiving) and I go on
237 * after header
238 */
2e10a170 239 if ((b == NULL) || (p < (u8 *) (h + 1)))
394acced 240 {
2e10a170 241 c0 += *p;
394acced
OF
242 }
243 else
244 {
2e10a170 245 c0 += *(b + (p - sp) - sizeof(struct ospf_lsa_header) + 2);
394acced
OF
246 }
247
248 c1 += c0;
499cb346 249 }
394acced
OF
250 c0 %= 255;
251 c1 %= 255;
252 }
499cb346
OF
253
254 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
2e10a170
OF
255 if (x <= 0)
256 x += 255;
499cb346 257 y = 510 - c0 - x;
2e10a170
OF
258 if (y > 255)
259 y -= 255;
499cb346 260
2e10a170
OF
261 ((u8 *) & h->checksum)[0] = x;
262 ((u8 *) & h->checksum)[1] = y;
c11007bc 263 return h->checksum;
499cb346
OF
264}
265
db9fb727
OF
266int
267lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
394acced 268 /* Return codes from point of view of l1 */
db9fb727 269{
2e10a170 270 u32 sn1, sn2;
37282678 271
2e10a170
OF
272 sn1 = l1->sn - LSA_INITSEQNO + 1;
273 sn2 = l2->sn - LSA_INITSEQNO + 1;
37282678 274
2e10a170
OF
275 if (sn1 > sn2)
276 return CMP_NEWER;
277 if (sn1 < sn2)
278 return CMP_OLDER;
ef6f26b4 279
2e10a170
OF
280 if (l1->checksum != l2->checksum)
281 return l1->checksum < l2->checksum ? CMP_OLDER : CMP_NEWER;
ef6f26b4 282
2e10a170
OF
283 if ((l1->age == LSA_MAXAGE) && (l2->age != LSA_MAXAGE))
284 return CMP_NEWER;
285 if ((l2->age == LSA_MAXAGE) && (l1->age != LSA_MAXAGE))
286 return CMP_OLDER;
ef6f26b4 287
2e10a170
OF
288 if (ABS(l1->age - l2->age) > LSA_MAXAGEDIFF)
289 return l1->age < l2->age ? CMP_NEWER : CMP_OLDER;
ef6f26b4
OF
290
291 return CMP_SAME;
db9fb727
OF
292}
293
a6bc04d5
OZ
294#define HDRLEN sizeof(struct ospf_lsa_header)
295
296static int
297lsa_validate_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
298{
299 unsigned int i, max;
300
301 if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
302 return 0;
303
304 struct ospf_lsa_rt_link *rtl = (struct ospf_lsa_rt_link *) (body + 1);
305 max = lsa_rt_count(lsa);
306
307#ifdef OSPFv2
308 if (body->links != max)
309 return 0;
310#endif
311
312 for (i = 0; i < max; i++)
313 {
314 u8 type = rtl[i].type;
315 if (!((type == LSART_PTP) ||
316 (type == LSART_NET) ||
317#ifdef OSPFv2
318 (type == LSART_STUB) ||
319#endif
320 (type == LSART_VLNK)))
321 return 0;
322 }
323 return 1;
324}
325
326static int
e81b440f 327lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body UNUSED)
a6bc04d5
OZ
328{
329 if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_net)))
330 return 0;
331
332 return 1;
333}
334
335#ifdef OSPFv2
336
337static int
338lsa_validate_sum(struct ospf_lsa_header *lsa, struct ospf_lsa_sum *body)
339{
340 if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum)))
341 return 0;
342
343 /* First field should have TOS = 0, we ignore other TOS fields */
344 if ((body->metric & LSA_SUM_TOS) != 0)
345 return 0;
346
347 return 1;
348}
349#define lsa_validate_sum_net(A,B) lsa_validate_sum(A,B)
350#define lsa_validate_sum_rt(A,B) lsa_validate_sum(A,B)
351
352static int
353lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext *body)
354{
355 if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext)))
356 return 0;
357
358 /* First field should have TOS = 0, we ignore other TOS fields */
359 if ((body->metric & LSA_EXT_TOS) != 0)
360 return 0;
361
362 return 1;
363}
364
365#else /* OSPFv3 */
366
367static inline int
368pxlen(u32 *buf)
369{
370 return *buf >> 24;
371}
372
373static int
374lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_net *body)
375{
376 if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum_net) + 4))
377 return 0;
378
379 u8 pxl = pxlen(body->prefix);
380 if (pxl > MAX_PREFIX_LENGTH)
381 return 0;
382
383 if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum_net) +
384 IPV6_PREFIX_SPACE(pxl)))
385 return 0;
386
387 return 1;
388}
389
390
391static int
392lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_rt *body)
393{
394 if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum_rt)))
395 return 0;
396
397 return 1;
398}
399
400static int
401lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext *body)
402{
403 if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext) + 4))
404 return 0;
405
406 u8 pxl = pxlen(body->rest);
407 if (pxl > MAX_PREFIX_LENGTH)
408 return 0;
409
410 int len = IPV6_PREFIX_SPACE(pxl);
411 if (body->metric & LSA_EXT_FBIT) // forwardinf address
412 len += 16;
413 if (body->metric & LSA_EXT_TBIT) // route tag
414 len += 4;
415 if (*body->rest & 0xFFFF) // referenced LS type field
416 len += 4;
417
418 if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext) + len))
419 return 0;
420
421 return 1;
422}
423
424static int
425lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, unsigned int offset, u8 *pbuf)
426{
427 unsigned int bound = lsa->length - HDRLEN - 4;
428 u32 i;
429
430 for (i = 0; i < pxcount; i++)
431 {
432 if (offset > bound)
433 return 0;
434
435 u8 pxl = pxlen((u32 *) (pbuf + offset));
436 if (pxl > MAX_PREFIX_LENGTH)
437 return 0;
438
439 offset += IPV6_PREFIX_SPACE(pxl);
440 }
441
442 if (lsa->length != (HDRLEN + offset))
443 return 0;
444
445 return 1;
446}
447
448static int
449lsa_validate_link(struct ospf_lsa_header *lsa, struct ospf_lsa_link *body)
450{
451 if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_link)))
452 return 0;
453
454 return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_link), (u8 *) body);
455}
456
457static int
458lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
459{
460 if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_prefix)))
461 return 0;
462
463 return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body);
464}
465
466#endif
467
468
469/**
470 * lsa_validate - check whether given LSA is valid
471 * @lsa: LSA header
472 * @body: pointer to LSA body
473 *
474 * Checks internal structure of given LSA body (minimal length,
475 * consistency). Returns true if valid.
476 */
477
478int
479lsa_validate(struct ospf_lsa_header *lsa, void *body)
480{
481 switch (lsa->type)
482 {
483 case LSA_T_RT:
484 return lsa_validate_rt(lsa, body);
485 case LSA_T_NET:
486 return lsa_validate_net(lsa, body);
487 case LSA_T_SUM_NET:
488 return lsa_validate_sum_net(lsa, body);
489 case LSA_T_SUM_RT:
490 return lsa_validate_sum_rt(lsa, body);
491 case LSA_T_EXT:
492 return lsa_validate_ext(lsa, body);
493#ifdef OSPFv3
494 case LSA_T_LINK:
495 return lsa_validate_link(lsa, body);
496 case LSA_T_PREFIX:
497 return lsa_validate_prefix(lsa, body);
498#endif
499 default:
500 /* In OSPFv3, unknown LSAs are OK,
501 In OSPFv2, unknown LSAs are already rejected
502 */
503 return 1;
504 }
505}
506
e9ab0b42
OF
507/**
508 * lsa_install_new - install new LSA into database
c3226991 509 * @po: OSPF protocol
e9ab0b42 510 * @lsa: LSA header
c3226991 511 * @domain: domain of LSA
6567e6cf 512 * @body: pointer to LSA body
c3226991 513
e9ab0b42
OF
514 *
515 * This function ensures installing new LSA into LSA database. Old instance is
4ca0d084 516 * replaced. Several actions are taken to detect if new routing table
e9ab0b42
OF
517 * calculation is necessary. This is described in 13.2 of RFC 2328.
518 */
d8852b36 519struct top_hash_entry *
c3226991 520lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body)
d8852b36 521{
39e517d4 522 /* LSA can be temporarrily, but body must be mb_allocated. */
2e10a170 523 int change = 0;
d8852b36
OF
524 struct top_hash_entry *en;
525
b49e6f5a 526 if ((en = ospf_hash_find_header(po->gr, domain, lsa)) == NULL)
d8852b36 527 {
b49e6f5a 528 en = ospf_hash_get_header(po->gr, domain, lsa);
2e10a170 529 change = 1;
d8852b36
OF
530 }
531 else
532 {
c3226991
OZ
533 if ((en->lsa.length != lsa->length)
534#ifdef OSPFv2
535 || (en->lsa.options != lsa->options)
536#endif
537 || (en->lsa.age == LSA_MAXAGE)
538 || (lsa->age == LSA_MAXAGE)
539 || memcmp(en->lsa_body, body, lsa->length - sizeof(struct ospf_lsa_header)))
2e10a170 540 change = 1;
c3226991 541
273fd2c1 542 s_rem_node(SNODE en);
85195f1a
OF
543 }
544
3aab39f5
OZ
545 DBG("Inst lsa: Id: %R, Rt: %R, Type: %u, Age: %u, Sum: %u, Sn: 0x%x\n",
546 lsa->id, lsa->rt, lsa->type, lsa->age, lsa->checksum, lsa->sn);
273fd2c1 547
86c84d76 548 s_add_tail(&po->lsal, SNODE en);
2e10a170
OF
549 en->inst_t = now;
550 if (en->lsa_body != NULL)
551 mb_free(en->lsa_body);
552 en->lsa_body = body;
553 memcpy(&en->lsa, lsa, sizeof(struct ospf_lsa_header));
554 en->ini_age = en->lsa.age;
555
556 if (change)
b8f17cf1 557 schedule_rtcalc(po);
2e10a170 558
d8852b36
OF
559 return en;
560}