Tomato 1.28
[tomato.git] / release / src / router / zebra / ospf6d / ospf6_lsa.c
blob34d030538dda076c04f4b1e04dd5aa3861e914dc
1 /*
2 * LSA function
3 * Copyright (C) 1999 Yasuhiro Ohara
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include <zebra.h>
25 /* Include other stuffs */
26 #include "version.h"
27 #include "log.h"
28 #include "getopt.h"
29 #include "linklist.h"
30 #include "thread.h"
31 #include "command.h"
32 #include "memory.h"
33 #include "sockunion.h"
34 #include "if.h"
35 #include "prefix.h"
36 #include "stream.h"
37 #include "thread.h"
38 #include "filter.h"
39 #include "zclient.h"
40 #include "table.h"
41 #include "plist.h"
43 #include "ospf6_proto.h"
44 #include "ospf6_prefix.h"
45 #include "ospf6_lsa.h"
46 #include "ospf6_lsdb.h"
47 #include "ospf6_message.h"
48 #include "ospf6_dump.h"
50 #include "ospf6_top.h"
51 #include "ospf6_area.h"
52 #include "ospf6_interface.h"
53 #include "ospf6_neighbor.h"
54 #include "ospf6_redistribute.h"
55 #include "ospf6_ism.h"
56 #include "ospf6_nsm.h"
57 #include "ospf6_dbex.h"
59 #define HEADER_DEPENDENCY
60 #include "ospf6d.h"
61 #undef HEADER_DEPENDENCY
63 char *ospf6_lsa_type_strings[] =
65 "None", "Router", "Network", "InterPrefix", "InterRouter",
66 "ASExternal", "GroupMembership", "Type7", "Link", "IntraPrefix",
67 NULL
70 char *ospf6_router_lsd_type_strings[] =
71 { "None", "PointToPoint", "Transit", "Stub", "Virtual", NULL };
73 char *
74 ospf6_lsa_print_id (struct ospf6_lsa_header *lsa_header, char *buf, int size)
76 char adv_router[64];
77 inet_ntop (AF_INET, &lsa_header->advrtr, adv_router, sizeof (adv_router));
78 snprintf (buf, size, "%s[id:%lu %s]",
79 ospf6_lsa_type_string (lsa_header->type),
80 (unsigned long) ntohl (lsa_header->ls_id), adv_router);
81 return buf;
84 /* test LSAs identity */
85 int
86 ospf6_lsa_issame (struct ospf6_lsa_header *lsh1,
87 struct ospf6_lsa_header *lsh2)
89 assert (lsh1 && lsh2);
91 if (lsh1->advrtr != lsh2->advrtr)
92 return 0;
94 if (lsh1->ls_id != lsh2->ls_id)
95 return 0;
97 if (lsh1->type != lsh2->type)
98 return 0;
100 return 1;
103 /* RFC2328: Section 13.2 */
105 ospf6_lsa_differ (struct ospf6_lsa *lsa1,
106 struct ospf6_lsa *lsa2)
108 int diff;
109 struct ospf6_lsa_header *lsh1, *lsh2;
111 ospf6_lsa_age_current (lsa1);
112 ospf6_lsa_age_current (lsa2);
113 lsh1 = (struct ospf6_lsa_header *) lsa1->lsa_hdr;
114 lsh2 = (struct ospf6_lsa_header *) lsa2->lsa_hdr;
116 if (! ospf6_lsa_issame (lsh1, lsh2))
117 return 1;
119 /* check Options field */
120 /* xxx */
122 if (ntohs (lsh1->age) == MAXAGE && ntohs (lsh2->age) != MAXAGE)
123 return 1;
124 if (ntohs (lsh1->age) != MAXAGE && ntohs (lsh2->age) == MAXAGE)
125 return 1;
127 /* compare body */
128 if (ntohs (lsh1->length) != ntohs (lsh2->length))
129 return 1;
131 diff = memcmp (lsh1 + 1, lsh2 + 1,
132 ntohs (lsh1->length) - sizeof (struct ospf6_lsa_header));
134 return diff;
138 ospf6_lsa_match (u_int16_t type, u_int32_t ls_id, u_int32_t advrtr,
139 struct ospf6_lsa_header *lsh)
141 if (lsh->advrtr != advrtr)
142 return 0;
144 if (lsh->ls_id != ls_id)
145 return 0;
147 if (lsh->type != type)
148 return 0;
150 return 1;
153 /* ospf6 age functions */
154 /* calculate birth and set expire timer */
155 static void
156 ospf6_lsa_age_set (struct ospf6_lsa *lsa)
158 struct timeval now;
160 assert (lsa && lsa->lsa_hdr);
162 if (gettimeofday (&now, (struct timezone *)NULL) < 0)
163 zlog_warn ("Lsa: gettimeofday failed, may fail LSA AGEs: %s",
164 strerror (errno));
166 lsa->birth = now.tv_sec - ntohs (lsa->lsa_hdr->lsh_age);
167 lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
168 lsa->birth + MAXAGE - now.tv_sec);
169 return;
172 /* this function calculates current age from its birth,
173 then update age field of LSA header. return value is current age */
174 u_int16_t
175 ospf6_lsa_age_current (struct ospf6_lsa *lsa)
177 struct timeval now;
178 u_int32_t ulage;
179 u_int16_t age;
180 struct ospf6_lsa_header *lsa_header;
182 assert (lsa);
183 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
184 assert (lsa_header);
186 /* current time */
187 if (gettimeofday (&now, (struct timezone *)NULL) < 0)
188 zlog_warn ("Lsa: gettimeofday failed, may fail ages: %s",
189 strerror (errno));
191 /* calculate age */
192 ulage = now.tv_sec - lsa->birth;
194 /* if over MAXAGE, set to it */
195 if (ulage > MAXAGE)
196 age = MAXAGE;
197 else
198 age = ulage;
200 lsa_header->age = htons (age);
201 return age;
204 /* returns 1 if LSA's age is MAXAGE. else returns 0 */
206 ospf6_lsa_is_maxage (struct ospf6_lsa *lsa)
208 if (ospf6_lsa_age_current (lsa) == MAXAGE)
209 return 1;
210 return 0;
213 /* update age field of LSA header with adding InfTransDelay */
214 void
215 ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
217 unsigned short age;
218 struct ospf6_lsa_header *lsa_header;
220 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
221 age = ospf6_lsa_age_current (lsa) + transdelay;
222 if (age > MAXAGE)
223 age = MAXAGE;
224 lsa_header->age = htons (age);
225 return;
228 void
229 ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
231 /* log */
232 if (IS_OSPF6_DUMP_LSA)
233 zlog_info ("Lsa: Premature aging: %s", lsa->str);
235 if (lsa->expire)
236 thread_cancel (lsa->expire);
237 lsa->expire = (struct thread *) NULL;
238 if (lsa->refresh)
239 thread_cancel (lsa->refresh);
240 lsa->refresh = (struct thread *) NULL;
242 lsa->birth = 0;
243 thread_execute (master, ospf6_lsa_expire, lsa, 0);
246 /* check which is more recent. if a is more recent, return -1;
247 if the same, return 0; otherwise(b is more recent), return 1 */
249 ospf6_lsa_check_recent (struct ospf6_lsa *a, struct ospf6_lsa *b)
251 signed long seqnuma, seqnumb;
252 u_int16_t cksuma, cksumb;
253 u_int16_t agea, ageb;
255 assert (a && a->lsa_hdr);
256 assert (b && b->lsa_hdr);
257 assert (ospf6_lsa_issame ((struct ospf6_lsa_header *) a->lsa_hdr,
258 (struct ospf6_lsa_header *) b->lsa_hdr));
260 seqnuma = ((signed long) ntohl (a->lsa_hdr->lsh_seqnum))
261 - (signed long)INITIAL_SEQUENCE_NUMBER;
262 seqnumb = ((signed long) ntohl (b->lsa_hdr->lsh_seqnum))
263 - (signed long)INITIAL_SEQUENCE_NUMBER;
265 /* compare by sequence number */
266 /* xxx, care about LS sequence number wrapping */
267 recent_reason = "seqnum";
268 if (IS_OSPF6_DUMP_LSA && seqnuma != seqnumb)
269 zlog_info ("LSA: recent: %s:[seqnum %d] %s:[seqnum %d]",
270 a->str, ntohl(a->header->seqnum),
271 b->str, ntohl(b->header->seqnum));
272 if (seqnuma > seqnumb)
273 return -1;
274 else if (seqnuma < seqnumb)
275 return 1;
277 /* Checksum */
278 cksuma = ntohs (a->header->checksum);
279 cksumb = ntohs (b->header->checksum);
280 if (cksuma > cksumb)
281 return -1;
282 if (cksuma < cksumb)
283 return 0;
285 /* Age check */
286 agea = ospf6_lsa_age_current (a);
287 ageb = ospf6_lsa_age_current (b);
289 /* MaxAge check */
290 recent_reason = "max age";
291 if (IS_OSPF6_DUMP_LSA &&
292 ((agea == OSPF6_LSA_MAXAGE && ageb != OSPF6_LSA_MAXAGE) ||
293 (agea != OSPF6_LSA_MAXAGE && ageb == OSPF6_LSA_MAXAGE)))
294 zlog_info ("LSA: recent: %s:[age %hu] %s:[age %hu]", a->str, agea, b->str, ageb);
295 if (agea == OSPF6_LSA_MAXAGE && ageb != OSPF6_LSA_MAXAGE)
296 return -1;
297 else if (agea != OSPF6_LSA_MAXAGE && ageb == OSPF6_LSA_MAXAGE)
298 return 1;
300 recent_reason = "age differ";
301 if (IS_OSPF6_DUMP_LSA &&
302 ((agea > ageb && agea - ageb >= OSPF6_LSA_MAXAGEDIFF) ||
303 (agea < ageb && ageb - agea >= OSPF6_LSA_MAXAGEDIFF)))
304 zlog_info ("LSA: recent: %s:[age %hu] %s:[age %hu]", a->str, agea, b->str, ageb);
305 if (agea > ageb && agea - ageb >= OSPF6_LSA_MAXAGEDIFF)
306 return 1;
307 else if (agea < ageb && ageb - agea >= OSPF6_LSA_MAXAGEDIFF)
308 return -1;
310 /* neither recent */
311 recent_reason = "the same instance";
312 if (IS_OSPF6_DUMP_LSA)
313 zlog_info ("LSA: recent: %s == %s", a->str, b->str);
314 return 0;
318 ospf6_lsa_lsd_num (struct ospf6_lsa_header *lsa_header)
320 int ldnum = 0;
321 u_int16_t len;
323 len = ntohs (lsa_header->length);
324 len -= sizeof (struct ospf6_lsa_header);
325 if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER))
327 len -= sizeof (struct ospf6_router_lsa);
328 ldnum = len / sizeof (struct ospf6_router_lsd);
330 else /* (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK)) */
332 len -= sizeof (struct ospf6_network_lsa);
333 ldnum = len / sizeof (u_int32_t);
336 return ldnum;
339 void *
340 ospf6_lsa_lsd_get (int index, struct ospf6_lsa_header *lsa_header)
342 void *p;
343 struct ospf6_router_lsa *router_lsa;
344 struct ospf6_router_lsd *router_lsd;
345 struct ospf6_network_lsa *network_lsa;
346 struct ospf6_network_lsd *network_lsd;
348 if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER))
350 router_lsa = (struct ospf6_router_lsa *) (lsa_header + 1);
351 router_lsd = (struct ospf6_router_lsd *) (router_lsa + 1);
352 router_lsd += index;
353 p = (void *) router_lsd;
355 else if (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK))
357 network_lsa = (struct ospf6_network_lsa *) (lsa_header + 1);
358 network_lsd = (struct ospf6_network_lsd *) (network_lsa + 1);
359 network_lsd += index;
360 p = (void *) network_lsd;
362 else
364 p = (void *) NULL;
367 return p;
370 /* network_lsd <-> router_lsd */
371 static int
372 ospf6_lsa_lsd_network_reference_match (struct ospf6_network_lsd *network_lsd1,
373 struct ospf6_lsa_header *lsa_header1,
374 struct ospf6_router_lsd *router_lsd2,
375 struct ospf6_lsa_header *lsa_header2)
377 if (network_lsd1->adv_router != lsa_header2->advrtr)
378 return 0;
379 if (router_lsd2->type != OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK)
380 return 0;
381 if (router_lsd2->neighbor_router_id != lsa_header1->advrtr)
382 return 0;
383 if (router_lsd2->neighbor_interface_id != lsa_header1->ls_id)
384 return 0;
385 return 1;
388 /* router_lsd <-> router_lsd */
389 static int
390 ospf6_lsa_lsd_router_reference_match (struct ospf6_router_lsd *router_lsd1,
391 struct ospf6_lsa_header *lsa_header1,
392 struct ospf6_router_lsd *router_lsd2,
393 struct ospf6_lsa_header *lsa_header2)
395 if (router_lsd1->type != OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
396 return 0;
397 if (router_lsd2->type != OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
398 return 0;
399 if (router_lsd1->neighbor_router_id != lsa_header2->advrtr)
400 return 0;
401 if (router_lsd2->neighbor_router_id != lsa_header1->advrtr)
402 return 0;
403 if (router_lsd1->neighbor_interface_id != router_lsd2->interface_id)
404 return 0;
405 if (router_lsd2->neighbor_interface_id != router_lsd1->interface_id)
406 return 0;
407 return 1;
411 ospf6_lsa_lsd_is_refer_ok (int index1, struct ospf6_lsa_header *lsa_header1,
412 int index2, struct ospf6_lsa_header *lsa_header2)
414 struct ospf6_router_lsd *r1, *r2;
415 struct ospf6_network_lsd *n;
417 r1 = (struct ospf6_router_lsd *) NULL;
418 r2 = (struct ospf6_router_lsd *) NULL;
419 n = (struct ospf6_network_lsd *) NULL;
420 if (lsa_header1->type == htons (OSPF6_LSA_TYPE_ROUTER))
421 r1 = (struct ospf6_router_lsd *) ospf6_lsa_lsd_get (index1, lsa_header1);
422 else
423 n = (struct ospf6_network_lsd *) ospf6_lsa_lsd_get (index1, lsa_header1);
425 if (lsa_header2->type == htons (OSPF6_LSA_TYPE_ROUTER))
426 r2 = (struct ospf6_router_lsd *) ospf6_lsa_lsd_get (index2, lsa_header2);
427 else
428 n = (struct ospf6_network_lsd *) ospf6_lsa_lsd_get (index2, lsa_header2);
430 if (r1 && r2)
431 return ospf6_lsa_lsd_router_reference_match (r1, lsa_header1,
432 r2, lsa_header2);
433 else if (r1 && n)
434 return ospf6_lsa_lsd_network_reference_match (n, lsa_header2,
435 r1, lsa_header1);
436 else if (n && r2)
437 return ospf6_lsa_lsd_network_reference_match (n, lsa_header1,
438 r2, lsa_header2);
439 return 0;
442 /* vty function for LSAs */
443 void
444 ospf6_lsa_show_body_unknown (struct vty *vty,
445 struct ospf6_lsa_header *lsa_header)
447 vty_out (vty, " Unknown Type%s", VTY_NEWLINE);
450 void
451 ospf6_lsa_show_body_router (struct vty *vty,
452 struct ospf6_lsa_header *lsa_header)
454 int lsdnum;
455 char buf[32];
456 struct ospf6_router_lsa *router_lsa;
457 struct ospf6_router_lsd *router_lsd;
459 assert (lsa_header);
460 router_lsa = (struct ospf6_router_lsa *)(lsa_header + 1);
461 router_lsd = (struct ospf6_router_lsd *)(router_lsa + 1);
463 lsdnum = ospf6_lsa_lsd_num (lsa_header);
464 assert (lsdnum >= 0);
466 while (lsdnum --)
468 vty_out (vty, " Type: %s Metric: %d%s",
469 ospf6_router_lsd_type_strings[router_lsd->type],
470 ntohs(router_lsd->metric), VTY_NEWLINE);
471 vty_out (vty, " Interface ID: %d%s",
472 ntohl (router_lsd->interface_id), VTY_NEWLINE);
473 vty_out (vty, " Neighbor Interface ID: %d%s",
474 ntohl (router_lsd->neighbor_interface_id), VTY_NEWLINE);
475 vty_out (vty, " Neighbor Router ID: %s%s",
476 inet_ntop (AF_INET, &router_lsd->neighbor_router_id,
477 buf, sizeof (buf)), VTY_NEWLINE);
478 router_lsd++;
482 void
483 ospf6_lsa_show_body_network (struct vty *vty,
484 struct ospf6_lsa_header *lsa_header)
486 int lsdnum;
487 struct ospf6_network_lsa *lsa;
488 u_int32_t *router_id;
489 char buf[128];
491 assert (lsa_header);
492 lsa = (struct ospf6_network_lsa *) (lsa_header + 1);
493 router_id = (u_int32_t *)(lsa + 1);
495 ospf6_opt_capability_string (lsa->options, buf, sizeof (buf));
496 vty_out (vty, " Options: %s%s", buf, VTY_NEWLINE);
498 lsdnum = ospf6_lsa_lsd_num (lsa_header);
499 assert (lsdnum >= 0);
501 while (lsdnum--)
503 inet_ntop (AF_INET, router_id, buf, sizeof (buf));
504 vty_out (vty, " Attached Router: %s%s", buf, VTY_NEWLINE);
505 router_id ++;
509 void
510 ospf6_lsa_show_body_inter_prefix (struct vty *vty,
511 struct ospf6_lsa_header *lsa_header)
513 struct ospf6_lsa_inter_area_prefix_lsa *inter_prefix_lsa;
514 struct ospf6_prefix *prefix;
515 struct in6_addr in6;
516 char buf[128];
518 assert (lsa_header);
519 inter_prefix_lsa = (struct ospf6_lsa_inter_area_prefix_lsa *) (lsa_header + 1);
521 /* Metric */
522 vty_out (vty, " Metric: %d%s", ntohl (inter_prefix_lsa->metric),
523 VTY_NEWLINE);
525 prefix = (struct ospf6_prefix *)(inter_prefix_lsa + 1);
527 /* Prefix Options */
528 ospf6_prefix_options_str (prefix, buf, sizeof (buf));
529 vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE);
531 /* Address Prefix */
532 ospf6_prefix_in6_addr (prefix, &in6);
533 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
534 vty_out (vty, " Prefix: %s/%d%s",
535 buf, prefix->prefix_length, VTY_NEWLINE);
538 void
539 ospf6_lsa_show_body_inter_router (struct vty *vty,
540 struct ospf6_lsa_header *lsa_header)
542 struct ospf6_lsa_inter_area_router_lsa *inter_router_lsa;
543 char buf[128];
545 assert (lsa_header);
546 inter_router_lsa = (struct ospf6_lsa_inter_area_router_lsa *) (lsa_header + 1);
548 /* Options */
549 ospf6_opt_capability_string (inter_router_lsa->options, buf, sizeof (buf));
550 vty_out (vty, " Options: %s%s", buf, VTY_NEWLINE);
552 /* Metric */
553 vty_out (vty, " Metric: %d%s", ntohl (inter_router_lsa->metric),
554 VTY_NEWLINE);
556 /* Destination Router ID */
557 inet_ntop (AF_INET, &inter_router_lsa->router_id, buf, sizeof (buf));
558 vty_out (vty, " Destination Router ID: %s", buf);
561 void
562 ospf6_lsa_show_body_as_external (struct vty *vty,
563 struct ospf6_lsa_header *lsa_header)
565 struct ospf6_as_external_lsa *elsa;
566 char buf[128], *ptr;
567 struct in6_addr in6;
569 assert (lsa_header);
570 elsa = (struct ospf6_as_external_lsa *)(lsa_header + 1);
572 /* bits */
573 snprintf (buf, sizeof (buf), "%s%s%s",
574 (ASE_LSA_ISSET (elsa, ASE_LSA_BIT_E) ? "E" : "-"),
575 (ASE_LSA_ISSET (elsa, ASE_LSA_BIT_F) ? "F" : "-"),
576 (ASE_LSA_ISSET (elsa, ASE_LSA_BIT_T) ? "T" : "-"));
578 vty_out (vty, " Bits: %s%s", buf, VTY_NEWLINE);
579 vty_out (vty, " Metric: %5hu%s", ntohs (elsa->ase_metric), VTY_NEWLINE);
581 ospf6_prefix_options_str (&elsa->ospf6_prefix, buf, sizeof (buf));
582 vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE);
584 vty_out (vty, " Referenced LSType: %d%s",
585 ntohs (elsa->ospf6_prefix.prefix_refer_lstype), VTY_NEWLINE);
587 ospf6_prefix_in6_addr (&elsa->ospf6_prefix, &in6);
588 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
589 vty_out (vty, " Prefix: %s/%d%s",
590 buf, elsa->ospf6_prefix.prefix_length, VTY_NEWLINE);
592 /* Forwarding-Address */
593 if (ASE_LSA_ISSET (elsa, ASE_LSA_BIT_F))
595 ptr = ((char *)(elsa + 1))
596 + OSPF6_PREFIX_SPACE (elsa->ospf6_prefix.prefix_length);
597 inet_ntop (AF_INET6, (struct in6_addr *) ptr, buf, sizeof (buf));
598 vty_out (vty, " Forwarding-Address: %s%s", buf, VTY_NEWLINE);
602 void
603 ospf6_lsa_show_body_group_membership (struct vty *vty,
604 struct ospf6_lsa_header *lsa_header)
608 void
609 ospf6_lsa_show_body_type_7 (struct vty *vty,
610 struct ospf6_lsa_header *lsa_header)
614 void
615 ospf6_lsa_show_body_link (struct vty *vty,
616 struct ospf6_lsa_header *lsa_header)
618 struct ospf6_link_lsa *llsap;
619 int prefixnum;
620 struct ospf6_prefix *prefix;
621 char buf[128];
622 struct in6_addr in6;
624 assert (lsa_header);
626 llsap = (struct ospf6_link_lsa *) (lsa_header + 1);
627 prefixnum = ntohl (llsap->llsa_prefix_num);
629 inet_ntop (AF_INET6, (void *)&llsap->llsa_linklocal, buf, sizeof (buf));
630 vty_out (vty, " LinkLocal Address: %s%s", buf, VTY_NEWLINE);
631 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE);
633 prefix = (struct ospf6_prefix *)(llsap + 1);
635 while (prefixnum--)
637 ospf6_prefix_options_str (prefix, buf, sizeof (buf));
638 vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE);
640 ospf6_prefix_in6_addr (prefix, &in6);
641 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
642 vty_out (vty, " Prefix: %s/%d%s",
643 buf, prefix->prefix_length, VTY_NEWLINE);
645 prefix = OSPF6_NEXT_PREFIX (prefix);
649 void
650 ospf6_lsa_show_body_intra_prefix (struct vty *vty,
651 struct ospf6_lsa_header *lsa_header)
653 struct ospf6_intra_area_prefix_lsa *iap_lsa;
654 struct ospf6_prefix *prefix;
655 unsigned short prefixnum;
656 char buf[128];
657 struct in6_addr in6;
659 assert (lsa_header);
660 iap_lsa = (struct ospf6_intra_area_prefix_lsa *) (lsa_header + 1);
661 prefixnum = ntohs (iap_lsa->prefix_number);
663 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE);
664 vty_out (vty, " Referenced LS Type: %s%s",
665 ospf6_lsa_type_string (iap_lsa->refer_lstype),
666 VTY_NEWLINE);
667 vty_out (vty, " Referenced LS ID: %d%s",
668 ntohl (iap_lsa->refer_lsid), VTY_NEWLINE);
669 inet_ntop (AF_INET, &iap_lsa->refer_advrtr, buf, sizeof (buf));
670 vty_out (vty, " Referenced Advertising Router: %s%s",
671 buf, VTY_NEWLINE);
673 prefix = (struct ospf6_prefix *)(iap_lsa + 1);
674 while (prefixnum--)
676 ospf6_prefix_options_str (prefix, buf, sizeof (buf));
677 vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE);
679 ospf6_prefix_in6_addr (prefix, &in6);
680 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
681 vty_out (vty, " Prefix: %s/%d%s",
682 buf, prefix->prefix_length, VTY_NEWLINE);
684 prefix = OSPF6_NEXT_PREFIX (prefix);
688 void
689 (*ospf6_lsa_show_body[OSPF6_LSA_TYPE_MAX]) (struct vty *,
690 struct ospf6_lsa_header *) =
692 ospf6_lsa_show_body_unknown,
693 ospf6_lsa_show_body_router,
694 ospf6_lsa_show_body_network,
695 ospf6_lsa_show_body_inter_prefix,
696 ospf6_lsa_show_body_inter_router,
697 ospf6_lsa_show_body_as_external,
698 ospf6_lsa_show_body_group_membership,
699 ospf6_lsa_show_body_type_7,
700 ospf6_lsa_show_body_link,
701 ospf6_lsa_show_body_intra_prefix,
704 void
705 ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
707 struct ospf6_lsa_header *lsa_header;
708 char advrtr[64];
710 assert (lsa);
711 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
712 assert (lsa_header);
714 inet_ntop (AF_INET, &lsa_header->advrtr, advrtr, sizeof (advrtr));
716 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
717 ospf6_lsa_type_string (lsa_header->type), VTY_NEWLINE);
718 vty_out (vty, "Link State ID: %d%s", ntohl (lsa_header->ls_id),
719 VTY_NEWLINE);
720 vty_out (vty, "Advertising Router: %s%s", advrtr, VTY_NEWLINE);
721 vty_out (vty, "LS Sequence Number: %#x%s", ntohl (lsa_header->seqnum),
722 VTY_NEWLINE);
723 vty_out (vty, "CheckSum: %#hx Length: %hu%s", ntohs (lsa_header->checksum),
724 ntohs (lsa_header->length), VTY_NEWLINE);
726 if (OSPF6_LSA_TYPESW_ISKNOWN (lsa_header->type))
727 (*ospf6_lsa_show_body [OSPF6_LSA_TYPESW (lsa_header->type)])
728 (vty, lsa_header);
729 else
730 ospf6_lsa_show_body_unknown (vty, lsa_header);
732 vty_out (vty, "%s", VTY_NEWLINE);
735 /* OSPFv3 LSA creation/deletion function */
737 /* calculate LS sequence number for my new LSA.
738 return value is network byte order */
739 static signed long
740 ospf6_seqnum_new (u_int16_t type, u_int32_t id, u_int32_t adv_router)
742 struct ospf6_lsa *lsa;
743 signed long seqnum;
745 /* get current database copy */
746 lsa = ospf6_lsdb_lookup (type, id, adv_router);
748 /* if current database copy not found, return InitialSequenceNumber */
749 if (!lsa)
750 seqnum = INITIAL_SEQUENCE_NUMBER;
751 else
752 seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
754 return (htonl (seqnum));
757 static void
758 ospf6_lsa_header_set (u_int16_t type, u_int32_t ls_id, u_int32_t advrtr,
759 struct ospf6_lsa_header *lsa_header, int bodysize)
761 /* fill LSA header */
762 lsa_header->age = 0;
763 lsa_header->type = type;
764 lsa_header->ls_id = ls_id;
765 lsa_header->advrtr = advrtr;
766 lsa_header->seqnum =
767 ospf6_seqnum_new (lsa_header->type, lsa_header->ls_id,
768 lsa_header->advrtr);
769 lsa_header->length = htons (sizeof (struct ospf6_lsa_header) + bodysize);
771 /* LSA checksum */
772 ospf6_lsa_checksum (lsa_header);
775 struct ospf6_lsa *
776 ospf6_lsa_create (struct ospf6_lsa_header *source)
778 struct ospf6_lsa *lsa = NULL;
779 struct ospf6_lsa_header *lsa_header = NULL;
780 u_int16_t lsa_size = 0;
781 char buf[128];
783 /* whole length of this LSA */
784 lsa_size = ntohs (source->length);
786 /* allocate memory for this LSA */
787 lsa_header = (struct ospf6_lsa_header *)
788 XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
789 if (! lsa_header)
791 zlog_err ("Lsa: Can't allocate memory for LSA Header");
792 return (struct ospf6_lsa *) NULL;
794 memset (lsa_header, 0, lsa_size);
796 /* copy LSA from source */
797 memcpy (lsa_header, source, lsa_size);
799 /* LSA information structure */
800 /* allocate memory */
801 lsa = (struct ospf6_lsa *)
802 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
803 memset (lsa, 0, sizeof (struct ospf6_lsa));
805 /* dump string */
806 snprintf (lsa->str, sizeof (lsa->str), "%s(%s[%lu])",
807 ospf6_lsa_type_string (lsa_header->type),
808 inet_ntop (AF_INET, &lsa_header->advrtr, buf, sizeof (buf)),
809 (unsigned long) ntohl (lsa_header->ls_id));
811 lsa->lsa_hdr = (struct ospf6_lsa_hdr *) lsa_header;
812 lsa->header = (struct ospf6_lsa_header__ *) lsa_header;
814 lsa->summary = 0; /* this is not LSA summary */
816 /* calculate birth, expire and refresh of this lsa */
817 ospf6_lsa_age_set (lsa);
819 #ifdef DEBUG
820 if (IS_OSPF6_DUMP_LSA)
821 zlog_info ("Lsa: created %s(%#x)", lsa->str, lsa);
822 #endif /* DEBUG */
824 return lsa;
827 struct ospf6_lsa *
828 ospf6_lsa_summary_create (struct ospf6_lsa_header__ *source)
830 struct ospf6_lsa *lsa = NULL;
831 struct ospf6_lsa_header *lsa_header = NULL;
832 u_int16_t lsa_size = 0;
833 char buf[128];
835 /* LSA summary contains LSA Header only */
836 lsa_size = sizeof (struct ospf6_lsa_header);
838 /* allocate memory for this LSA */
839 lsa_header = (struct ospf6_lsa_header *)
840 XMALLOC (MTYPE_OSPF6_LSA_SUMMARY, lsa_size);
841 memset (lsa_header, 0, lsa_size);
843 /* copy LSA from source */
844 memcpy (lsa_header, source, lsa_size);
846 /* LSA information structure */
847 /* allocate memory */
848 lsa = (struct ospf6_lsa *)
849 XMALLOC (MTYPE_OSPF6_LSA_SUMMARY, sizeof (struct ospf6_lsa));
850 memset (lsa, 0, sizeof (struct ospf6_lsa));
852 /* dump string */
853 snprintf (lsa->str, sizeof (lsa->str), "%s(%s[%lu])[S]",
854 ospf6_lsa_type_string (lsa_header->type),
855 inet_ntop (AF_INET, &lsa_header->advrtr, buf, sizeof (buf)),
856 (unsigned long) ntohl (lsa_header->ls_id));
858 lsa->lsa_hdr = (struct ospf6_lsa_hdr *) lsa_header;
859 lsa->header = (struct ospf6_lsa_header__ *) lsa_header;
861 lsa->summary = 1; /* this is LSA summary */
863 /* calculate birth, expire and refresh of this lsa */
864 ospf6_lsa_age_set (lsa);
866 #ifdef DEBUG
867 if (IS_OSPF6_DUMP_LSA)
868 zlog_info ("Lsa: created summary %s(%#x)", lsa->str, lsa);
869 #endif /* DEBUG */
871 return lsa;
874 void
875 ospf6_lsa_delete (struct ospf6_lsa *lsa)
877 /* just to make sure */
878 if (lsa->lock != 0)
880 zlog_err ("Can't delete %s: lock: %ld", lsa->str, lsa->lock);
881 return;
884 /* cancel threads */
885 if (lsa->expire)
886 thread_cancel (lsa->expire);
887 lsa->expire = (struct thread *) NULL;
888 if (lsa->refresh)
889 thread_cancel (lsa->refresh);
890 lsa->refresh = (struct thread *) NULL;
892 if (IS_OSPF6_DUMP_LSA)
894 if (lsa->summary)
895 zlog_info ("LSA: delete summary %s(%p)", lsa->str, lsa);
896 else
897 zlog_info ("LSA: delete %s(%p)", lsa->str, lsa);
900 /* do free */
901 if (lsa->summary)
902 XFREE (MTYPE_OSPF6_LSA_SUMMARY, lsa->header);
903 else
904 XFREE (MTYPE_OSPF6_LSA, lsa->header);
905 lsa->header = NULL;
907 if (lsa->summary)
908 XFREE (MTYPE_OSPF6_LSA_SUMMARY, lsa);
909 else
910 XFREE (MTYPE_OSPF6_LSA, lsa);
913 /* increment reference counter of struct ospf6_lsa */
914 void
915 ospf6_lsa_lock (struct ospf6_lsa *lsa)
917 lsa->lock++;
918 return;
921 /* decrement reference counter of struct ospf6_lsa */
922 void
923 ospf6_lsa_unlock (struct ospf6_lsa *lsa)
925 /* decrement reference counter */
926 if (lsa->lock > 0)
927 lsa->lock--;
928 else
929 zlog_warn ("Can't unlock %s: already no lock", lsa->str);
932 /* check necessity to update LSA:
933 returns 1 if it's necessary to reoriginate */
934 static int
935 ospf6_lsa_is_really_reoriginate (struct ospf6_lsa *new)
937 struct ospf6_lsa *old;
938 int diff;
940 /* find previous LSA */
941 old = ospf6_lsdb_lookup (new->header->type, new->header->id,
942 new->header->adv_router);
943 if (! old)
944 return 1;
946 /* Check if this is refresh */
947 if (old->refresh == (struct thread *) NULL)
949 zlog_warn ("LSA: reoriginate: %s: cause it's refresh", new->str);
950 return 1;
953 /* Are these contents different ? */
954 diff = ospf6_lsa_differ (new, old);
956 if (diff)
957 return 1;
959 if (IS_OSPF6_DUMP_LSA)
960 zlog_info ("LSA: Suppress updating %s", new->str);
961 return 0;
964 /* RFC2740 3.4.3.1 Router-LSA */
965 void
966 ospf6_lsa_update_router (u_int32_t area_id)
968 char buffer [MAXLSASIZE];
969 u_int16_t size;
970 struct ospf6_lsa *lsa, *prev_lsa;
971 struct ospf6_area *o6a;
972 int count;
974 struct ospf6_router_lsa *router_lsa;
975 struct ospf6_router_lsd *router_lsd;
976 listnode i;
977 struct ospf6_interface *o6i;
978 struct ospf6_neighbor *o6n = NULL;
980 o6a = ospf6_area_lookup (area_id, ospf6);
981 if (! o6a)
983 inet_ntop (AF_INET, &area_id, buffer, sizeof (buffer));
984 zlog_warn ("LSA: Update Router-LSA: No such area: %s", buffer);
985 return;
988 if (IS_OSPF6_DUMP_LSA)
989 zlog_info ("Lsa: Update Router-LSA for %s", o6a->str);
991 /* find previous LSA */
992 prev_lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_ROUTER),
993 htonl (0), o6a->ospf6->router_id);
995 size = sizeof (struct ospf6_router_lsa);
996 memset (buffer, 0, sizeof (buffer));
997 router_lsa = (struct ospf6_router_lsa *)
998 (buffer + sizeof (struct ospf6_lsa_header));
1000 OSPF6_OPT_CLEAR_ALL (router_lsa->options);
1001 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
1002 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
1003 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
1004 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
1005 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
1006 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
1008 OSPF6_ROUTER_LSA_CLEAR_ALL_BITS (router_lsa);
1009 OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_B);
1011 if (ospf6_is_asbr (o6a->ospf6))
1012 OSPF6_ROUTER_LSA_SET (router_lsa, OSPF6_ROUTER_LSA_BIT_E);
1013 else
1014 OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_E);
1016 OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_V);
1017 OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_W);
1019 /* describe links for each interfaces */
1020 router_lsd = (struct ospf6_router_lsd *) (router_lsa + 1);
1021 for (i = listhead (o6a->if_list); i; nextnode (i))
1023 o6i = (struct ospf6_interface *) getdata (i);
1024 assert (o6i);
1026 /* Interfaces in state Down or Loopback are not described */
1027 if (o6i->state == IFS_DOWN || o6i->state == IFS_LOOPBACK)
1028 continue;
1030 /* Nor are interfaces without any full adjacencies described */
1031 count = 0;
1032 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
1033 if (count == 0)
1034 continue;
1036 /* Point-to-Point interfaces */
1037 if (if_is_pointopoint (o6i->interface))
1039 if (listcount (o6i->neighbor_list) == 0)
1040 continue;
1042 if (listcount (o6i->neighbor_list) != 1)
1043 zlog_warn ("LSA: Multiple neighbors on PoinToPoint: %s",
1044 o6i->interface->name);
1046 o6n = (struct ospf6_neighbor *)
1047 getdata (listhead (o6i->neighbor_list));
1048 assert (o6n);
1050 router_lsd->type = OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT;
1051 router_lsd->metric = htons (o6i->cost);
1052 router_lsd->interface_id = htonl (o6i->if_id);
1053 router_lsd->neighbor_interface_id = htonl (o6n->ifid);
1054 router_lsd->neighbor_router_id = o6n->router_id;
1056 size += sizeof (struct ospf6_router_lsd);
1057 router_lsd ++;
1059 continue;
1062 /* Broadcast and NBMA interfaces */
1063 if (if_is_broadcast (o6i->interface))
1065 /* If this router is not DR,
1066 and If this router not fully adjacent with DR,
1067 this interface is not transit yet: ignore. */
1068 if (o6i->state != IFS_DR)
1070 o6n = ospf6_neighbor_lookup (o6i->dr, o6i); /* find DR */
1071 assert (o6n);
1072 if (o6n->state != NBS_FULL)
1073 continue;
1075 else
1077 count = 0;
1078 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
1079 if (count == 0)
1080 continue;
1083 router_lsd->type = OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK;
1084 router_lsd->metric = htons (o6i->cost);
1085 router_lsd->interface_id = htonl (o6i->if_id);
1086 if (o6i->state != IFS_DR)
1088 router_lsd->neighbor_interface_id = htonl (o6n->ifid);
1089 router_lsd->neighbor_router_id = o6n->router_id;
1091 else
1093 router_lsd->neighbor_interface_id = htonl (o6i->if_id);
1094 router_lsd->neighbor_router_id = o6i->area->ospf6->router_id;
1097 size += sizeof (struct ospf6_router_lsd);
1098 router_lsd ++;
1100 continue;
1103 /* Virtual links */
1104 /* xxx */
1105 /* Point-to-Multipoint interfaces */
1106 /* xxx */
1109 /* Fill LSA Header */
1110 ospf6_lsa_header_set (htons (OSPF6_LSA_TYPE_ROUTER), htonl (0),
1111 o6a->ospf6->router_id,
1112 (struct ospf6_lsa_header *)buffer, size);
1114 /* create LSA */
1115 lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
1116 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
1117 OSPF6_LS_REFRESH_TIME);
1118 lsa->scope = (void *) o6a;
1120 if (ospf6_lsa_is_really_reoriginate (lsa))
1122 ospf6_dbex_remove_from_all_retrans_list (lsa);
1123 ospf6_dbex_flood (lsa, NULL);
1124 ospf6_lsdb_install (lsa);
1126 else
1127 ospf6_lsa_delete (lsa);
1130 /* RFC2740 3.4.3.2 Network-LSA */
1131 void
1132 ospf6_lsa_update_network (char *ifname)
1134 char buffer [MAXLSASIZE];
1135 u_int16_t size;
1136 struct ospf6_lsa *lsa, *prev_lsa;
1137 struct interface *ifp;
1138 struct ospf6_interface *o6i;
1139 int count;
1141 struct ospf6_network_lsa *nlsa;
1142 listnode i;
1143 struct ospf6_neighbor *o6n;
1144 u_int32_t *router_id;
1146 ifp = if_lookup_by_name (ifname);
1147 if (! ifp)
1149 zlog_warn ("LSA: Update Network: No such Interface: %s", ifname);
1150 return;
1152 o6i = (struct ospf6_interface *) ifp->info;
1153 if (! o6i)
1155 zlog_warn ("LSA: Update Network: Interface not enabled: %s", ifname);
1156 return;
1159 /* find previous LSA */
1160 prev_lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_NETWORK),
1161 htonl (o6i->if_id),
1162 o6i->area->ospf6->router_id);
1164 /* Don't originate Network-LSA if not DR */
1165 if (o6i->state != IFS_DR)
1167 if (IS_OSPF6_DUMP_LSA)
1168 zlog_info ("LSA Update Network: Interface %s is not DR",
1169 o6i->interface->name);
1170 if (prev_lsa)
1171 ospf6_lsa_premature_aging (prev_lsa);
1172 return;
1175 /* If none of neighbor is adjacent to us */
1176 count = 0;
1177 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
1178 if (count == 0)
1180 if (IS_OSPF6_DUMP_LSA)
1181 zlog_info ("LSA Update Network: Interface %s is Stub",
1182 o6i->interface->name);
1183 if (prev_lsa)
1184 ospf6_lsa_premature_aging (prev_lsa);
1185 return;
1188 if (IS_OSPF6_DUMP_LSA)
1189 zlog_info ("LSA Update Network: Interface %s", o6i->interface->name);
1191 /* prepare buffer */
1192 size = sizeof (struct ospf6_network_lsa);
1193 memset (buffer, 0, sizeof (buffer));
1194 nlsa = (struct ospf6_network_lsa *)
1195 (buffer + sizeof (struct ospf6_lsa_header));
1196 router_id = (u_int32_t *)(nlsa + 1);
1198 /* set fields of myself */
1199 *router_id++ = o6i->area->ospf6->router_id;
1200 size += sizeof (u_int32_t);
1201 nlsa->options[0] |= o6i->area->options[0];
1202 nlsa->options[1] |= o6i->area->options[1];
1203 nlsa->options[2] |= o6i->area->options[2];
1205 /* Walk through neighbors */
1206 for (i = listhead (o6i->neighbor_list); i; nextnode (i))
1208 o6n = (struct ospf6_neighbor *) getdata (i);
1210 if (o6n->state != NBS_FULL)
1211 continue;
1213 /* set this neighbor's Router-ID to LSA */
1214 *router_id++ = o6n->router_id;
1215 size += sizeof (u_int32_t);
1217 /* options field is logical OR */
1218 nlsa->options[0] |= o6n->options[0];
1219 nlsa->options[1] |= o6n->options[1];
1220 nlsa->options[2] |= o6n->options[2];
1223 /* Fill LSA Header */
1224 ospf6_lsa_header_set (htons (OSPF6_LSA_TYPE_NETWORK), htonl (o6i->if_id),
1225 o6i->area->ospf6->router_id,
1226 (struct ospf6_lsa_header *) buffer, size);
1228 /* create LSA */
1229 lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
1230 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
1231 OSPF6_LS_REFRESH_TIME);
1232 lsa->scope = (void *) o6i->area;
1234 if (ospf6_lsa_is_really_reoriginate (lsa))
1236 ospf6_dbex_remove_from_all_retrans_list (lsa);
1237 ospf6_dbex_flood (lsa, NULL);
1238 ospf6_lsdb_install (lsa);
1240 else
1241 ospf6_lsa_delete (lsa);
1244 /* RFC2740 3.4.3.5 AS-External-LSA */
1245 void
1246 ospf6_lsa_update_as_external (u_int32_t lsid)
1248 char buffer [MAXLSASIZE];
1249 u_int16_t size;
1250 struct ospf6_lsa *lsa, *prev_lsa;
1252 struct ospf6_as_external_lsa *elsa;
1253 struct route_node *rn, *target;
1254 struct ospf6_redistribute_info *info = NULL;
1255 char *p;
1257 /* find previous LSA */
1258 prev_lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
1259 ntohl (lsid), ospf6->router_id);
1261 /* find corresponding route node */
1262 target = NULL;
1263 for (rn = route_top (ospf6->external_table); rn; rn = route_next (rn))
1265 info = (struct ospf6_redistribute_info *) rn->info;
1266 if (info && info->id == lsid)
1267 target = rn;
1270 if (! target)
1272 if (IS_OSPF6_DUMP_LSA)
1273 zlog_info ("LSA: Don't create AS-External-LSA for ID %d: No entry",
1274 lsid);
1276 if (prev_lsa)
1278 zlog_info ("LSA: Delete old Self-originated AS-External-LSA");
1279 ospf6_lsa_premature_aging (prev_lsa);
1281 return;
1284 if (IS_OSPF6_DUMP_LSA)
1285 zlog_info ("LSA Update AS-External: ID:%d", lsid);
1287 /* prepare buffer */
1288 size = sizeof (struct ospf6_as_external_lsa);
1289 memset (buffer, 0, sizeof (buffer));
1290 elsa = (struct ospf6_as_external_lsa *)
1291 (buffer + sizeof (struct ospf6_lsa_header));
1292 p = (char *) (elsa + 1);
1294 info = (struct ospf6_redistribute_info *) target->info;
1295 if (info->metric_type == 2)
1296 ASE_LSA_SET (elsa, ASE_LSA_BIT_E); /* type2 */
1297 else
1298 ASE_LSA_CLEAR (elsa, ASE_LSA_BIT_E); /* type1 */
1300 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forward))
1301 ASE_LSA_SET (elsa, ASE_LSA_BIT_F); /* forwarding address */
1302 else
1303 ASE_LSA_CLEAR (elsa, ASE_LSA_BIT_F); /* forwarding address */
1305 ASE_LSA_CLEAR (elsa, ASE_LSA_BIT_T); /* external route tag */
1307 /* don't know how to use */
1308 elsa->ase_pre_metric = 0;
1310 /* set metric. note: related to E bit */
1311 elsa->ase_metric = htons (info->metric);
1313 /* prefixlen */
1314 elsa->ospf6_prefix.prefix_length = target->p.prefixlen;
1316 /* PrefixOptions */
1317 elsa->ospf6_prefix.prefix_options = info->prefix_options;
1319 /* don't use refer LS-type */
1320 elsa->ospf6_prefix.prefix_refer_lstype = htons (0);
1322 /* set Prefix */
1323 memcpy (p, &target->p.u.prefix6, OSPF6_PREFIX_SPACE (target->p.prefixlen));
1324 ospf6_prefix_apply_mask (&elsa->ospf6_prefix);
1325 size += OSPF6_PREFIX_SPACE (target->p.prefixlen);
1326 p += OSPF6_PREFIX_SPACE (target->p.prefixlen);
1328 /* Forwarding address */
1329 if (ASE_LSA_ISSET (elsa, ASE_LSA_BIT_F))
1331 memcpy (p, &info->forward, sizeof (struct in6_addr));
1332 size += sizeof (struct in6_addr);
1333 p += sizeof (struct in6_addr);
1336 /* External Route Tag */
1337 if (ASE_LSA_ISSET (elsa, ASE_LSA_BIT_T))
1339 /* xxx */
1342 /* Fill LSA Header */
1343 ospf6_lsa_header_set (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), htonl (lsid),
1344 ospf6->router_id,
1345 (struct ospf6_lsa_header *) buffer, size);
1347 /* create LSA */
1348 lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
1349 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
1350 OSPF6_LS_REFRESH_TIME);
1351 lsa->scope = (void *) ospf6;
1353 if (ospf6_lsa_is_really_reoriginate (lsa))
1355 ospf6_dbex_remove_from_all_retrans_list (lsa);
1356 ospf6_dbex_flood (lsa, NULL);
1357 ospf6_lsdb_install (lsa);
1359 else
1360 ospf6_lsa_delete (lsa);
1363 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
1364 void
1365 ospf6_lsa_update_intra_prefix_transit (char *ifname)
1367 char buffer [MAXLSASIZE];
1368 u_int16_t size;
1369 struct ospf6_lsa *lsa, *prev_lsa;
1370 struct interface *ifp;
1371 struct ospf6_interface *o6i;
1372 int count;
1374 struct ospf6_intra_area_prefix_lsa *intra_prefix_lsa;
1375 struct ospf6_lsdb_node *node;
1376 struct ospf6_neighbor *o6n;
1377 struct ospf6_prefix *o6_pstart, *o6_pcurrent, *o6_p1, *o6_p2;
1378 struct ospf6_link_lsa *link_body;
1379 u_int16_t prefix_number, link_prefix_number;
1380 struct in6_addr in6;
1381 char buf[128];
1382 int duplicate;
1384 ifp = if_lookup_by_name (ifname);
1385 if (! ifp)
1387 zlog_warn ("LSA: Update Intra-Area-Prefix-LSA(Transit): "
1388 "No such Interface: %s", ifname);
1389 return;
1391 o6i = (struct ospf6_interface *) ifp->info;
1392 if (! o6i)
1394 zlog_warn ("LSA: Update Intra-Area-Prefix-LSA(Transit): "
1395 "Interface not enabled: %s", ifname);
1396 return;
1399 /* find previous LSA */
1400 prev_lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
1401 htonl (o6i->if_id),
1402 o6i->area->ospf6->router_id);
1404 /* Don't originate Network-LSA if not DR */
1405 if (o6i->state != IFS_DR)
1407 if (IS_OSPF6_DUMP_LSA)
1408 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1409 "Interface %s is not DR", o6i->interface->name);
1410 if (prev_lsa)
1411 ospf6_lsa_premature_aging (prev_lsa);
1412 return;
1415 /* If none of neighbor is adjacent to us */
1416 count = 0;
1417 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
1418 if (count == 0)
1420 if (IS_OSPF6_DUMP_LSA)
1421 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1422 "Interface %s is Stub", o6i->interface->name);
1423 if (prev_lsa)
1424 ospf6_lsa_premature_aging (prev_lsa);
1425 return;
1428 if (IS_OSPF6_DUMP_LSA)
1429 zlog_info ("LSA Update Intra-Area-Prefix(Transit): Interface %s",
1430 o6i->interface->name);
1432 /* prepare buffer */
1433 size = sizeof (struct ospf6_intra_area_prefix_lsa);
1434 memset (buffer, 0, sizeof (buffer));
1435 intra_prefix_lsa = (struct ospf6_intra_area_prefix_lsa *)
1436 (buffer + sizeof (struct ospf6_lsa_header));
1437 o6_pstart = (struct ospf6_prefix *)(intra_prefix_lsa + 1);
1438 o6_pcurrent = o6_pstart;
1439 prefix_number = 0;
1441 /* Set Referenced LSA field */
1442 intra_prefix_lsa->refer_lstype = htons (OSPF6_LSA_TYPE_NETWORK);
1443 intra_prefix_lsa->refer_lsid = htonl (o6i->if_id);
1444 intra_prefix_lsa->refer_advrtr = o6i->area->ospf6->router_id;
1446 /* foreach Link-LSA associated with this Link */
1447 for (node = ospf6_lsdb_head (o6i->lsdb); node; node = ospf6_lsdb_next (node))
1449 if (node->lsa->header->type != htons (OSPF6_LSA_TYPE_LINK))
1450 continue;
1452 if (ospf6_lsa_is_maxage (node->lsa))
1453 continue;
1455 if (IS_OSPF6_DUMP_LSA)
1456 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1457 "Checking %s", node->lsa->str);
1459 if (node->lsa->header->adv_router != o6i->area->ospf6->router_id)
1461 o6n = ospf6_neighbor_lookup (node->lsa->header->adv_router, o6i);
1462 if (! o6n || o6n->state != NBS_FULL)
1464 if (IS_OSPF6_DUMP_LSA)
1465 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1466 "neighbor not found or not FULL");
1467 continue;
1471 /* For each Prefix in this Link-LSA */
1472 link_body = (struct ospf6_link_lsa *) (node->lsa->header + 1);
1473 link_prefix_number = ntohl (link_body->llsa_prefix_num);
1475 if (IS_OSPF6_DUMP_LSA)
1476 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1477 "Prefix #%d", link_prefix_number);
1479 for (o6_p1 = (struct ospf6_prefix *) (link_body + 1);
1480 link_prefix_number; link_prefix_number --)
1482 ospf6_prefix_in6_addr (o6_p1, &in6);
1483 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
1485 if (IS_OSPF6_DUMP_LSA)
1486 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1487 "Prefix %s", buf);
1489 /* filter linklocal prefix */
1490 if (IN6_IS_ADDR_LINKLOCAL (&in6))
1492 if (IS_OSPF6_DUMP_LSA)
1493 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1494 "%s is Linklocal", buf);
1495 o6_p1 = OSPF6_NEXT_PREFIX (o6_p1);
1496 continue;
1499 /* filter unspecified(default) prefix */
1500 if (IN6_IS_ADDR_UNSPECIFIED (&in6))
1502 if (IS_OSPF6_DUMP_LSA)
1503 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1504 "%s is Unspecified", buf);
1505 o6_p1 = OSPF6_NEXT_PREFIX (o6_p1);
1506 continue;
1509 /* filter loopback prefix */
1510 if (IN6_IS_ADDR_LOOPBACK (&in6))
1512 if (IS_OSPF6_DUMP_LSA)
1513 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1514 "%s is Loopback", buf);
1515 o6_p1 = OSPF6_NEXT_PREFIX (o6_p1);
1516 continue;
1519 /* filter IPv4 compatible prefix */
1520 if (IN6_IS_ADDR_V4COMPAT (&in6))
1522 if (IS_OSPF6_DUMP_LSA)
1523 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1524 "%s is v4-Compatible", buf);
1525 o6_p1 = OSPF6_NEXT_PREFIX (o6_p1);
1526 continue;
1529 /* filter IPv4 Mapped prefix */
1530 if (IN6_IS_ADDR_V4MAPPED (&in6))
1532 if (IS_OSPF6_DUMP_LSA)
1533 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1534 "%s is v4-Mapped", buf);
1535 o6_p1 = OSPF6_NEXT_PREFIX (o6_p1);
1536 continue;
1539 /* Check duplicate prefix */
1540 duplicate = 0;
1541 for (o6_p2 = o6_pstart; o6_p2 < o6_pcurrent;
1542 o6_p2 = OSPF6_NEXT_PREFIX (o6_p2))
1544 if (! ospf6_prefix_issame (o6_p1, o6_p2))
1545 continue;
1547 duplicate = 1;
1548 o6_p2->prefix_options |= o6_p1->prefix_options;
1550 if (duplicate)
1552 if (IS_OSPF6_DUMP_LSA)
1553 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1554 "Duplicate %s", buf);
1555 o6_p1 = OSPF6_NEXT_PREFIX (o6_p1);
1556 continue;
1559 /* copy prefix to new LSA */
1560 if (IS_OSPF6_DUMP_LSA)
1561 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1562 "including %s", buf);
1563 o6_pcurrent->prefix_length = o6_p1->prefix_length;
1564 o6_pcurrent->prefix_options = o6_p1->prefix_options;
1565 memcpy (o6_pcurrent + 1, o6_p1 + 1,
1566 OSPF6_PREFIX_SPACE (o6_p1->prefix_length));
1568 size += OSPF6_PREFIX_SIZE (o6_pcurrent);
1569 o6_pcurrent = OSPF6_NEXT_PREFIX (o6_pcurrent);
1570 o6_p1 = OSPF6_NEXT_PREFIX (o6_p1);
1571 prefix_number ++;
1575 /* if no prefix to advertise, return */
1576 if (prefix_number == 0)
1578 if (IS_OSPF6_DUMP_LSA)
1579 zlog_info ("LSA Update Intra-Area-Prefix(Transit): "
1580 "No Prefix to advertise");
1581 return;
1584 intra_prefix_lsa->prefix_number = htons (prefix_number);
1586 /* Fill LSA Header */
1587 ospf6_lsa_header_set (htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
1588 htonl (o6i->if_id),
1589 o6i->area->ospf6->router_id,
1590 (struct ospf6_lsa_header *) buffer, size);
1592 /* create LSA */
1593 lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
1594 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
1595 OSPF6_LS_REFRESH_TIME);
1596 lsa->scope = (void *) o6i->area;
1598 if (ospf6_lsa_is_really_reoriginate (lsa))
1600 ospf6_dbex_remove_from_all_retrans_list (lsa);
1601 ospf6_dbex_flood (lsa, NULL);
1602 ospf6_lsdb_install (lsa);
1604 else
1605 ospf6_lsa_delete (lsa);
1608 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
1609 void
1610 ospf6_lsa_update_intra_prefix_stub (u_int32_t area_id)
1612 char buffer [MAXLSASIZE];
1613 u_int16_t size;
1614 struct ospf6_lsa *lsa, *prev_lsa;
1615 struct ospf6_area *o6a;
1616 int count;
1618 struct ospf6_intra_area_prefix_lsa *intra_prefix_lsa;
1619 listnode i,j;
1620 struct ospf6_interface *o6i = NULL;
1621 struct ospf6_prefix *prefix_dst;
1622 struct connected *c;
1623 struct prefix_ipv6 prefix_ipv6;
1624 char buf[128];
1625 u_int16_t prefix_number;
1627 o6a = ospf6_area_lookup (area_id, ospf6);
1628 if (! o6a)
1630 inet_ntop (AF_INET, &area_id, buffer, sizeof (buffer));
1631 zlog_warn ("LSA: Update Intra-Area-Prefix-LSA(Stub): "
1632 "No such area: %s", buffer);
1633 return;
1636 /* find previous LSA */
1637 prev_lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
1638 htonl (0), /* xxx */
1639 o6a->ospf6->router_id);
1641 /* prepare buffer */
1642 size = sizeof (struct ospf6_intra_area_prefix_lsa);
1643 memset (buffer, 0, sizeof (buffer));
1644 intra_prefix_lsa = (struct ospf6_intra_area_prefix_lsa *)
1645 (buffer + sizeof (struct ospf6_lsa_header));
1646 prefix_dst = (struct ospf6_prefix *)(intra_prefix_lsa + 1);
1647 prefix_number = 0;
1649 /* Examin for each interface */
1650 for (i = listhead (o6a->if_list); i; nextnode (i))
1652 o6i = (struct ospf6_interface *) getdata (i);
1654 if (IS_OSPF6_DUMP_LSA)
1655 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1656 "Checking Interface %s", o6i->interface->name);
1658 if (o6i->state == IFS_DOWN)
1660 if (IS_OSPF6_DUMP_LSA)
1661 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1662 "Interface %s down", o6i->interface->name);
1663 continue;
1666 count = 0;
1667 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
1668 if (o6i->state != IFS_LOOPBACK && o6i->state != IFS_PTOP &&
1669 count != 0)
1671 /* This interface's prefix will be included in DR's */
1672 if (IS_OSPF6_DUMP_LSA)
1673 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1674 "Interface %s is not stub", o6i->interface->name);
1675 continue;
1678 /* copy foreach site-local or global prefix */
1679 for (j = listhead (o6i->interface->connected); j; nextnode (j))
1681 c = (struct connected *) getdata (j);
1683 /* filter prefix not IPv6 */
1684 if (c->address->family != AF_INET6)
1685 continue;
1687 inet_ntop (AF_INET6, &c->address->u.prefix6, buf, sizeof (buf));
1689 if (IS_OSPF6_DUMP_LSA)
1690 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1691 "Checking %s", buf);
1693 /* filter linklocal prefix */
1694 if (IN6_IS_ADDR_LINKLOCAL (&c->address->u.prefix6))
1696 if (IS_OSPF6_DUMP_LSA)
1697 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1698 "%s is Linklocal", buf);
1699 continue;
1702 /* filter unspecified(default) prefix */
1703 if (IN6_IS_ADDR_UNSPECIFIED (&c->address->u.prefix6))
1705 if (IS_OSPF6_DUMP_LSA)
1706 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1707 "%s is Unspecified", buf);
1708 continue;
1711 /* filter loopback prefix */
1712 if (IN6_IS_ADDR_LOOPBACK (&c->address->u.prefix6))
1714 if (IS_OSPF6_DUMP_LSA)
1715 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1716 "%s is Loopback", buf);
1717 continue;
1720 /* filter IPv4 compatible prefix */
1721 if (IN6_IS_ADDR_V4COMPAT (&c->address->u.prefix6))
1723 if (IS_OSPF6_DUMP_LSA)
1724 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1725 "%s is v4-Compatible", buf);
1726 continue;
1729 /* filter IPv4 Mapped prefix */
1730 if (IN6_IS_ADDR_V4MAPPED (&c->address->u.prefix6))
1732 if (IS_OSPF6_DUMP_LSA)
1733 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1734 "%s is v4-Mapped", buf);
1735 continue;
1738 /* set ospf6 prefix according to its state */
1739 /* xxx, virtual links */
1740 prefix_copy ((struct prefix *) &prefix_ipv6, c->address);
1741 if (o6i->state == IFS_LOOPBACK || o6i->state == IFS_PTOP
1742 /* xxx, PoinToMultiPoint I/F type */ )
1744 prefix_dst->prefix_length = 128;
1745 prefix_dst->prefix_options = OSPF6_PREFIX_OPTION_LA;
1746 prefix_dst->prefix_metric = htons (0);
1747 memcpy (prefix_dst + 1, &prefix_ipv6.prefix,
1748 OSPF6_PREFIX_SPACE (prefix_dst->prefix_length));
1750 else
1752 /* apply mask */
1753 apply_mask_ipv6 (&prefix_ipv6);
1754 inet_ntop (AF_INET6, &c->address->u.prefix6, buf, sizeof (buf));
1756 prefix_dst->prefix_length = prefix_ipv6.prefixlen;
1757 prefix_dst->prefix_options = 0; /* xxx, no options yet */
1758 prefix_dst->prefix_metric = htons (o6i->cost);
1759 memcpy (prefix_dst + 1, &prefix_ipv6.prefix,
1760 OSPF6_PREFIX_SPACE (prefix_dst->prefix_length));
1763 if (IS_OSPF6_DUMP_LSA)
1764 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1765 "include %s", buf);
1767 /* forward current buffer pointer */
1768 prefix_number ++;
1769 size += OSPF6_PREFIX_SIZE (prefix_dst);
1770 prefix_dst = OSPF6_NEXT_PREFIX (prefix_dst);
1774 /* If no prefix to advertise */
1775 if (prefix_number == 0)
1777 if (IS_OSPF6_DUMP_LSA)
1778 zlog_info ("LSA Update Intra-Area-Prefix(Stub): "
1779 "No prefix to advertise for area %s", o6a->str);
1780 if (prev_lsa)
1781 ospf6_lsa_premature_aging (prev_lsa);
1782 return;
1785 if (IS_OSPF6_DUMP_LSA)
1786 zlog_info ("LSA Update Intra-Area-Prefix(Stub): Area %s", o6a->str);
1788 /* Set Referenced LSA field */
1789 intra_prefix_lsa->refer_lstype = htons (OSPF6_LSA_TYPE_ROUTER);
1790 intra_prefix_lsa->refer_lsid = htonl (0);
1791 intra_prefix_lsa->refer_advrtr = o6a->ospf6->router_id;
1793 intra_prefix_lsa->prefix_number = htons (prefix_number);
1795 /* Fill LSA Header */
1796 ospf6_lsa_header_set (htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
1797 htonl (0), /* xxx */
1798 o6i->area->ospf6->router_id,
1799 (struct ospf6_lsa_header *) buffer, size);
1801 /* create LSA */
1802 lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
1803 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
1804 OSPF6_LS_REFRESH_TIME);
1805 lsa->scope = (void *) o6a;
1807 if (ospf6_lsa_is_really_reoriginate (lsa))
1809 ospf6_dbex_remove_from_all_retrans_list (lsa);
1810 ospf6_dbex_flood (lsa, NULL);
1811 ospf6_lsdb_install (lsa);
1813 else
1814 ospf6_lsa_delete (lsa);
1817 void
1818 ospf6_lsa_update_link (char *ifname)
1820 char *cp, buffer [MAXLSASIZE];
1821 u_int16_t size;
1822 struct ospf6_lsa *lsa, *prev_lsa;
1823 struct interface *ifp;
1824 struct ospf6_interface *o6i;
1826 struct ospf6_link_lsa *llsa;
1827 struct ospf6_prefix *p;
1828 list prefix_connected;
1829 listnode n;
1830 struct connected *c;
1832 ifp = if_lookup_by_name (ifname);
1833 if (! ifp)
1835 if (IS_OSPF6_DUMP_LSA)
1836 zlog_info ("LSA: Update Link-LSA: No such Interface: %s", ifname);
1837 return;
1839 o6i = (struct ospf6_interface *) ifp->info;
1840 if (! o6i)
1842 if (IS_OSPF6_DUMP_LSA)
1843 zlog_info ("LSA: Update Link-LSA: Interface not enabled: %s", ifname);
1844 return;
1847 /* find previous LSA */
1848 prev_lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_LINK),
1849 htonl (o6i->if_id),
1850 ospf6->router_id);
1852 /* can't make Link-LSA if linklocal address not set */
1853 if (! o6i->lladdr)
1855 zlog_err ("LSA Update Link: No Linklocal Address: %s",
1856 o6i->interface->name);
1857 if (prev_lsa)
1858 ospf6_lsa_premature_aging (prev_lsa);
1859 return;
1862 if (IS_OSPF6_DUMP_LSA)
1863 zlog_info ("LSA Update Link: Interface %s", o6i->interface->name);
1865 /* check connected prefix */
1866 prefix_connected = list_new ();
1867 for (n = listhead (o6i->interface->connected); n; nextnode (n))
1869 c = (struct connected *) getdata (n);
1871 /* filter prefix not IPv6 */
1872 if (c->address->family != AF_INET6)
1873 continue;
1875 /* filter linklocal prefix */
1876 if (IN6_IS_ADDR_LINKLOCAL (&c->address->u.prefix6))
1877 continue;
1879 /* filter unspecified(default) prefix */
1880 if (IN6_IS_ADDR_UNSPECIFIED (&c->address->u.prefix6))
1881 continue;
1883 /* filter loopback prefix */
1884 if (IN6_IS_ADDR_LOOPBACK (&c->address->u.prefix6))
1885 continue;
1887 /* filter IPv4 compatible prefix */
1888 if (IN6_IS_ADDR_V4COMPAT (&c->address->u.prefix6))
1889 continue;
1891 /* filter IPv4 Mapped prefix */
1892 if (IN6_IS_ADDR_V4MAPPED (&c->address->u.prefix6))
1893 continue;
1895 /* hold prefix in list. duplicate is filtered in ospf6_prefix_add() */
1896 p = ospf6_prefix_make (0, 0, (struct prefix_ipv6 *) c->address);
1897 ospf6_prefix_add (prefix_connected, p);
1900 /* Note: if no prefix configured, still we have to create Link-LSA
1901 for next-hop resolution */
1903 /* fill Link LSA and calculate size */
1904 size = sizeof (struct ospf6_link_lsa);
1905 memset (buffer, 0, sizeof (buffer));
1906 llsa = (struct ospf6_link_lsa *)
1907 (buffer + sizeof (struct ospf6_lsa_header));
1908 llsa->llsa_rtr_pri = o6i->priority;
1909 llsa->llsa_options[0] = o6i->area->options[0];
1910 llsa->llsa_options[1] = o6i->area->options[1];
1911 llsa->llsa_options[2] = o6i->area->options[2];
1913 /* linklocal address */
1914 memcpy (&llsa->llsa_linklocal, o6i->lladdr, sizeof (struct in6_addr));
1915 #ifdef KAME /* clear ifindex */
1916 if (llsa->llsa_linklocal.s6_addr[3] & 0x0f)
1917 llsa->llsa_linklocal.s6_addr[3] &= ~((char)0x0f);
1918 #endif /* KAME */
1920 llsa->llsa_prefix_num = htonl (listcount (prefix_connected));
1921 cp = (char *)(llsa + 1);
1922 for (n = listhead (prefix_connected); n; nextnode (n))
1924 p = (struct ospf6_prefix *) getdata (n);
1925 size += OSPF6_PREFIX_SIZE (p);
1926 memcpy (cp, p, OSPF6_PREFIX_SIZE (p));
1927 cp += OSPF6_PREFIX_SIZE (p);
1930 for (n = listhead (prefix_connected); n; nextnode (n))
1932 p = (struct ospf6_prefix *) getdata (n);
1933 ospf6_prefix_free (p);
1935 list_delete (prefix_connected);
1937 /* Fill LSA Header */
1938 ospf6_lsa_header_set (htons (OSPF6_LSA_TYPE_LINK), htonl (o6i->if_id),
1939 o6i->area->ospf6->router_id,
1940 (struct ospf6_lsa_header *) buffer, size);
1942 /* create LSA */
1943 lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
1944 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
1945 OSPF6_LS_REFRESH_TIME);
1946 lsa->scope = (void *) o6i;
1948 if (ospf6_lsa_is_really_reoriginate (lsa))
1950 ospf6_dbex_remove_from_all_retrans_list (lsa);
1951 ospf6_dbex_flood (lsa, NULL);
1952 ospf6_lsdb_install (lsa);
1954 else
1955 ospf6_lsa_delete (lsa);
1958 #if 0
1959 void
1960 ospf6_lsa_update_inter_prefix (struct ospf6_area *o6a)
1962 char *cp, buffer [MAXLSASIZE];
1963 u_int16_t size;
1964 struct ospf6_lsa *lsa, *prev_lsa;
1966 struct ospf6_lsa_inter_prefix *inter_prefix;
1967 struct ospf6_prefix *o6p;
1969 /* find previous LSA */
1970 prev_lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTER_PREFIX),
1971 htonl (0), /* xxx */
1972 ospf6->router_id);
1974 if (o6a->area_range.prefixlen == 0)
1976 zlog_err ("LSA Update Inter-Area-Prefix: No Area range Configured for %s",
1977 o6a->str);
1978 if (prev_lsa)
1979 ospf6_lsa_premature_aging (prev_lsa);
1980 return;
1983 if (IS_OSPF6_DUMP_LSA)
1984 zlog_info ("LSA Update Inter-Area-Prefix: Area %s", o6a->str);
1986 size = sizeof (struct ospf6_lsa_inter_prefix_lsa);
1987 memset (buffer, 0, sizeof (buffer));
1988 inter_prefix = (struct ospf6_lsa_inter_prefix_lsa *)
1989 (buffer + sizeof (struct ospf6_lsa_header));
1991 /* linklocal address */
1992 memcpy (&llsa->llsa_linklocal, o6i->lladdr, sizeof (struct in6_addr));
1993 #ifdef KAME /* clear ifindex */
1994 if (llsa->llsa_linklocal.s6_addr[3] & 0x0f)
1995 llsa->llsa_linklocal.s6_addr[3] &= ~((char)0x0f);
1996 #endif /* KAME */
1998 llsa->llsa_prefix_num = htonl (listcount (prefix_connected));
1999 cp = (char *)(llsa + 1);
2000 for (n = listhead (prefix_connected); n; nextnode (n))
2002 p = (struct ospf6_prefix *) getdata (n);
2003 size += OSPF6_PREFIX_SIZE (p);
2004 memcpy (cp, p, OSPF6_PREFIX_SIZE (p));
2005 cp += OSPF6_PREFIX_SIZE (p);
2008 /* Fill LSA Header */
2009 ospf6_lsa_header_set (htons (OSPF6_LSA_TYPE_LINK), htonl (o6i->if_id),
2010 o6i->area->ospf6->router_id,
2011 (struct ospf6_lsa_header *) buffer, size);
2013 /* create LSA */
2014 lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
2015 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
2016 OSPF6_LS_REFRESH_TIME);
2017 lsa->scope = (void *) o6i;
2019 if (ospf6_lsa_is_really_reoriginate (lsa))
2021 ospf6_dbex_remove_from_all_retrans_list (lsa);
2022 ospf6_dbex_flood (lsa, NULL);
2023 ospf6_lsdb_install (lsa);
2025 else
2026 ospf6_lsa_delete (lsa);
2029 #endif
2031 void
2032 ospf6_lsa_reoriginate (struct ospf6_lsa *lsa)
2034 struct ospf6_lsa_header *lsa_header;
2036 struct ospf6 *o6;
2037 struct ospf6_area *o6a;
2038 struct ospf6_interface *o6i;
2040 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
2042 if (IS_OSPF6_DUMP_LSA)
2043 zlog_info ("Re-originate %s", lsa->str);
2045 switch (ntohs (lsa_header->type))
2047 case OSPF6_LSA_TYPE_ROUTER:
2048 o6a = (struct ospf6_area *) lsa->scope;
2049 assert (o6a);
2050 ospf6_lsa_update_router (o6a->area_id);
2051 break;
2053 case OSPF6_LSA_TYPE_NETWORK:
2054 o6a = (struct ospf6_area *) lsa->scope;
2055 assert (o6a);
2056 o6i = ospf6_interface_lookup_by_index (ntohl (lsa_header->ls_id));
2057 if (o6i)
2058 ospf6_lsa_update_network (o6i->interface->name);
2059 else
2060 ospf6_lsa_premature_aging (lsa);
2061 break;
2063 case OSPF6_LSA_TYPE_INTRA_PREFIX:
2064 /* xxx, assume LS-ID has addressing semantics */
2065 o6a = (struct ospf6_area *) lsa->scope;
2066 o6i = NULL;
2067 assert (o6a);
2068 if (ntohl (lsa_header->ls_id) != 0)
2069 o6i = ospf6_interface_lookup_by_index (ntohl (lsa_header->ls_id));
2071 if (o6i)
2072 ospf6_lsa_update_intra_prefix_transit (o6i->interface->name);
2073 else if (ntohl (lsa_header->ls_id) == 0)
2074 ospf6_lsa_update_intra_prefix_stub (o6a->area_id);
2075 else
2076 ospf6_lsa_premature_aging (lsa);
2077 break;
2079 case OSPF6_LSA_TYPE_LINK:
2080 o6i = (struct ospf6_interface *) lsa->scope;
2081 assert (o6i);
2082 ospf6_lsa_update_link (o6i->interface->name);
2083 break;
2085 case OSPF6_LSA_TYPE_AS_EXTERNAL:
2086 o6 = (struct ospf6 *) lsa->scope;
2087 assert (o6);
2088 ospf6_lsa_update_as_external (ntohl (lsa_header->ls_id));
2089 break;
2091 default:
2092 break;
2097 /* ospf6_lsa expired */
2099 ospf6_lsa_expire (struct thread *thread)
2101 struct ospf6_lsa *lsa;
2103 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
2104 assert (lsa && lsa->lsa_hdr);
2106 /* assertion */
2107 assert (ospf6_lsa_is_maxage (lsa));
2108 assert (!lsa->refresh);
2110 lsa->expire = (struct thread *) NULL;
2112 /* log */
2113 if (IS_OSPF6_DUMP_LSA)
2114 zlog_info ("LSA: Expire: %s", lsa->str);
2116 if (!lsa->summary)
2118 /* reflood lsa */
2119 ospf6_dbex_flood (lsa, NULL);
2121 /* do not free LSA, and do nothing about lslists.
2122 wait event (ospf6_lsdb_check_maxage) */
2125 return 0;
2129 ospf6_lsa_refresh (struct thread *thread)
2131 struct ospf6_lsa *lsa;
2133 assert (thread);
2134 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
2135 assert (lsa && lsa->lsa_hdr);
2137 /* this will be used later as flag to decide really originate */
2138 lsa->refresh = (struct thread *)NULL;
2140 /* log */
2141 if (IS_OSPF6_DUMP_LSA)
2143 zlog_info ("LSA Refresh: %s", lsa->str);
2146 ospf6_lsa_reoriginate (lsa);
2148 return 0;
2153 /* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
2154 #define MODX 4102
2155 #define LSA_CHECKSUM_OFFSET 15
2157 unsigned short
2158 ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
2160 u_char *sp, *ep, *p, *q;
2161 int c0 = 0, c1 = 0;
2162 int x, y;
2163 u_int16_t length;
2165 lsa_header->checksum = 0;
2166 length = ntohs (lsa_header->length) - 2;
2167 sp = (char *) &lsa_header->type;
2169 for (ep = sp + length; sp < ep; sp = q)
2171 q = sp + MODX;
2172 if (q > ep)
2173 q = ep;
2174 for (p = sp; p < q; p++)
2176 c0 += *p;
2177 c1 += c0;
2179 c0 %= 255;
2180 c1 %= 255;
2183 /* r = (c1 << 8) + c0; */
2184 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
2185 if (x <= 0)
2186 x += 255;
2187 y = 510 - c0 - x;
2188 if (y > 255)
2189 y -= 255;
2191 lsa_header->checksum = htons ((x << 8) + y);
2193 return (lsa_header->checksum);
2196 u_int16_t
2197 ospf6_lsa_get_scope_type (u_int16_t type)
2199 return (ntohs (type) & OSPF6_LSA_SCOPE_MASK);
2203 ospf6_lsa_is_known_type (struct ospf6_lsa_header *lsa_header)
2205 if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER))
2206 return 1;
2207 if (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK))
2208 return 1;
2209 #if 0
2210 if (lsa_header->type == htons (OSPF6_LSA_TYPE_INTER_PREFIX))
2211 return 1;
2212 if (lsa_header->type == htons (OSPF6_LSA_TYPE_INTER_ROUTER))
2213 return 1;
2214 #endif
2215 if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL))
2216 return 1;
2217 if (lsa_header->type == htons (OSPF6_LSA_TYPE_LINK))
2218 return 1;
2219 if (lsa_header->type == htons (OSPF6_LSA_TYPE_INTRA_PREFIX))
2220 return 1;
2221 return 0;