]>
Commit | Line | Data |
---|---|---|
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 | 11 | void |
86c84d76 | 12 | flush_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 | 41 | void |
86c84d76 | 42 | ospf_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 |
94 | void |
95 | htonlsah(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 | |
109 | void | |
110 | ntohlsah(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 | |
124 | void | |
e81b440f | 125 | htonlsab(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 | |
135 | void | |
e81b440f | 136 | ntohlsab(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 |
147 | void |
148 | buf_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 | 184 | void |
d5d9693c | 185 | lsasum_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 | */ | |
212 | u16 | |
d5d9693c | 213 | lsasum_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 |
266 | int |
267 | lsa_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 | ||
296 | static int | |
297 | lsa_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 | ||
326 | static int | |
e81b440f | 327 | lsa_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 | ||
337 | static int | |
338 | lsa_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 | ||
352 | static int | |
353 | lsa_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 | ||
367 | static inline int | |
368 | pxlen(u32 *buf) | |
369 | { | |
370 | return *buf >> 24; | |
371 | } | |
372 | ||
373 | static int | |
374 | lsa_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 | ||
391 | static int | |
392 | lsa_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 | ||
400 | static int | |
401 | lsa_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 | ||
424 | static int | |
425 | lsa_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 | ||
448 | static int | |
449 | lsa_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 | ||
457 | static int | |
458 | lsa_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 | ||
478 | int | |
479 | lsa_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 | 519 | struct top_hash_entry * |
c3226991 | 520 | lsa_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 | } |