bgpd: tighten bounds checking in RR ORF msg reader
[jleu-quagga.git] / ospf6d / ospf6_intra.c
blob05b11ba36f9e73a2386a5056e1ed6d9718677d2d
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #include <zebra.h>
24 #include "log.h"
25 #include "linklist.h"
26 #include "thread.h"
27 #include "memory.h"
28 #include "if.h"
29 #include "prefix.h"
30 #include "table.h"
31 #include "vty.h"
32 #include "command.h"
34 #include "ospf6_proto.h"
35 #include "ospf6_message.h"
36 #include "ospf6_route.h"
37 #include "ospf6_lsa.h"
38 #include "ospf6_lsdb.h"
40 #include "ospf6_top.h"
41 #include "ospf6_area.h"
42 #include "ospf6_interface.h"
43 #include "ospf6_neighbor.h"
44 #include "ospf6_intra.h"
45 #include "ospf6_asbr.h"
46 #include "ospf6_abr.h"
47 #include "ospf6_flood.h"
48 #include "ospf6d.h"
51 unsigned char conf_debug_ospf6_brouter = 0;
52 u_int32_t conf_debug_ospf6_brouter_specific_router_id;
53 u_int32_t conf_debug_ospf6_brouter_specific_area_id;
55 /******************************/
56 /* RFC2740 3.4.3.1 Router-LSA */
57 /******************************/
59 static int
60 ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
62 char *start, *end, *current;
63 char buf[32], name[32], bits[16], options[32];
64 struct ospf6_router_lsa *router_lsa;
65 struct ospf6_router_lsdesc *lsdesc;
67 router_lsa = (struct ospf6_router_lsa *)
68 ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
70 ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
71 ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
72 vty_out (vty, " Bits: %s Options: %s%s", bits, options, VNL);
74 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
75 end = (char *) lsa->header + ntohs (lsa->header->length);
76 for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
77 current += sizeof (struct ospf6_router_lsdesc))
79 lsdesc = (struct ospf6_router_lsdesc *) current;
81 if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
82 snprintf (name, sizeof (name), "Point-To-Point");
83 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
84 snprintf (name, sizeof (name), "Transit-Network");
85 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
86 snprintf (name, sizeof (name), "Stub-Network");
87 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
88 snprintf (name, sizeof (name), "Virtual-Link");
89 else
90 snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
92 vty_out (vty, " Type: %s Metric: %d%s",
93 name, ntohs (lsdesc->metric), VNL);
94 vty_out (vty, " Interface ID: %s%s",
95 inet_ntop (AF_INET, &lsdesc->interface_id,
96 buf, sizeof (buf)), VNL);
97 vty_out (vty, " Neighbor Interface ID: %s%s",
98 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
99 buf, sizeof (buf)), VNL);
100 vty_out (vty, " Neighbor Router ID: %s%s",
101 inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
102 buf, sizeof (buf)), VNL);
104 return 0;
108 ospf6_router_lsa_originate (struct thread *thread)
110 struct ospf6_area *oa;
112 char buffer [OSPF6_MAX_LSASIZE];
113 struct ospf6_lsa_header *lsa_header;
114 struct ospf6_lsa *lsa;
116 u_int32_t link_state_id = 0;
117 struct listnode *node, *nnode;
118 struct listnode *j;
119 struct ospf6_interface *oi;
120 struct ospf6_neighbor *on, *drouter = NULL;
121 struct ospf6_router_lsa *router_lsa;
122 struct ospf6_router_lsdesc *lsdesc;
123 u_int16_t type;
124 u_int32_t router;
125 int count;
127 oa = (struct ospf6_area *) THREAD_ARG (thread);
128 oa->thread_router_lsa = NULL;
130 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
131 zlog_debug ("Originate Router-LSA for Area %s", oa->name);
133 memset (buffer, 0, sizeof (buffer));
134 lsa_header = (struct ospf6_lsa_header *) buffer;
135 router_lsa = (struct ospf6_router_lsa *)
136 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
138 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
139 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
140 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
141 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
142 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
143 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
145 if (ospf6_is_router_abr (ospf6))
146 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
147 else
148 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
149 if (ospf6_asbr_is_asbr (ospf6))
150 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
151 else
152 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
153 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
154 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
156 /* describe links for each interfaces */
157 lsdesc = (struct ospf6_router_lsdesc *)
158 ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
160 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
162 /* Interfaces in state Down or Loopback are not described */
163 if (oi->state == OSPF6_INTERFACE_DOWN ||
164 oi->state == OSPF6_INTERFACE_LOOPBACK)
165 continue;
167 /* Nor are interfaces without any full adjacencies described */
168 count = 0;
169 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
170 if (on->state == OSPF6_NEIGHBOR_FULL)
171 count++;
173 if (count == 0)
174 continue;
176 /* Multiple Router-LSA instance according to size limit setting */
177 if ( (oa->router_lsa_size_limit != 0)
178 && ((caddr_t) lsdesc + sizeof (struct ospf6_router_lsdesc) -
179 /* XXX warning: comparison between signed and unsigned */
180 (caddr_t) buffer > oa->router_lsa_size_limit))
182 if ((caddr_t) lsdesc == (caddr_t) router_lsa +
183 sizeof (struct ospf6_router_lsa))
185 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
186 zlog_debug ("Size limit setting for Router-LSA too short");
187 return 0;
190 /* Fill LSA Header */
191 lsa_header->age = 0;
192 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
193 lsa_header->id = htonl (link_state_id);
194 lsa_header->adv_router = oa->ospf6->router_id;
195 lsa_header->seqnum =
196 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
197 lsa_header->adv_router, oa->lsdb);
198 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
200 /* LSA checksum */
201 ospf6_lsa_checksum (lsa_header);
203 /* create LSA */
204 lsa = ospf6_lsa_create (lsa_header);
206 /* Originate */
207 ospf6_lsa_originate_area (lsa, oa);
209 /* Reset setting for consecutive origination */
210 memset ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa),
211 0, (caddr_t) lsdesc - (caddr_t) router_lsa);
212 lsdesc = (struct ospf6_router_lsdesc *)
213 ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
214 link_state_id ++;
217 /* Point-to-Point interfaces */
218 if (if_is_pointopoint (oi->interface))
220 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
222 if (on->state != OSPF6_NEIGHBOR_FULL)
223 continue;
225 lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
226 lsdesc->metric = htons (oi->cost);
227 lsdesc->interface_id = htonl (oi->interface->ifindex);
228 lsdesc->neighbor_interface_id = htonl (on->ifindex);
229 lsdesc->neighbor_router_id = on->router_id;
231 lsdesc++;
235 /* Broadcast and NBMA interfaces */
236 if (if_is_broadcast (oi->interface))
238 /* If this router is not DR,
239 and If this router not fully adjacent with DR,
240 this interface is not transit yet: ignore. */
241 if (oi->state != OSPF6_INTERFACE_DR)
243 drouter = ospf6_neighbor_lookup (oi->drouter, oi);
244 if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL)
245 continue;
248 lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
249 lsdesc->metric = htons (oi->cost);
250 lsdesc->interface_id = htonl (oi->interface->ifindex);
251 if (oi->state != OSPF6_INTERFACE_DR)
253 lsdesc->neighbor_interface_id = htonl (drouter->ifindex);
254 lsdesc->neighbor_router_id = drouter->router_id;
256 else
258 lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex);
259 lsdesc->neighbor_router_id = oi->area->ospf6->router_id;
262 lsdesc++;
265 /* Virtual links */
266 /* xxx */
267 /* Point-to-Multipoint interfaces */
268 /* xxx */
271 if ((caddr_t) lsdesc != (caddr_t) router_lsa +
272 sizeof (struct ospf6_router_lsa))
274 /* Fill LSA Header */
275 lsa_header->age = 0;
276 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
277 lsa_header->id = htonl (link_state_id);
278 lsa_header->adv_router = oa->ospf6->router_id;
279 lsa_header->seqnum =
280 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
281 lsa_header->adv_router, oa->lsdb);
282 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
284 /* LSA checksum */
285 ospf6_lsa_checksum (lsa_header);
287 /* create LSA */
288 lsa = ospf6_lsa_create (lsa_header);
290 /* Originate */
291 ospf6_lsa_originate_area (lsa, oa);
293 link_state_id ++;
295 else
297 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
298 zlog_debug ("Nothing to describe in Router-LSA, suppress");
301 /* Do premature-aging of rest, undesired Router-LSAs */
302 type = ntohs (OSPF6_LSTYPE_ROUTER);
303 router = oa->ospf6->router_id;
304 for (lsa = ospf6_lsdb_type_router_head (type, router, oa->lsdb); lsa;
305 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
307 if (ntohl (lsa->header->id) < link_state_id)
308 continue;
309 ospf6_lsa_purge (lsa);
312 return 0;
315 /*******************************/
316 /* RFC2740 3.4.3.2 Network-LSA */
317 /*******************************/
319 static int
320 ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
322 char *start, *end, *current;
323 struct ospf6_network_lsa *network_lsa;
324 struct ospf6_network_lsdesc *lsdesc;
325 char buf[128], options[32];
327 network_lsa = (struct ospf6_network_lsa *)
328 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
330 ospf6_options_printbuf (network_lsa->options, options, sizeof (options));
331 vty_out (vty, " Options: %s%s", options, VNL);
333 start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
334 end = (char *) lsa->header + ntohs (lsa->header->length);
335 for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end;
336 current += sizeof (struct ospf6_network_lsdesc))
338 lsdesc = (struct ospf6_network_lsdesc *) current;
339 inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
340 vty_out (vty, " Attached Router: %s%s", buf, VNL);
342 return 0;
346 ospf6_network_lsa_originate (struct thread *thread)
348 struct ospf6_interface *oi;
350 char buffer [OSPF6_MAX_LSASIZE];
351 struct ospf6_lsa_header *lsa_header;
353 int count;
354 struct ospf6_lsa *old, *lsa;
355 struct ospf6_network_lsa *network_lsa;
356 struct ospf6_network_lsdesc *lsdesc;
357 struct ospf6_neighbor *on;
358 struct ospf6_link_lsa *link_lsa;
359 struct listnode *i;
360 u_int16_t type;
362 oi = (struct ospf6_interface *) THREAD_ARG (thread);
363 oi->thread_network_lsa = NULL;
365 /* The interface must be enabled until here. A Network-LSA of a
366 disabled interface (but was once enabled) should be flushed
367 by ospf6_lsa_refresh (), and does not come here. */
368 assert (oi->area);
370 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
371 htonl (oi->interface->ifindex),
372 oi->area->ospf6->router_id, oi->area->lsdb);
374 /* Do not originate Network-LSA if not DR */
375 if (oi->state != OSPF6_INTERFACE_DR)
377 if (old)
378 ospf6_lsa_purge (old);
379 return 0;
382 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
383 zlog_debug ("Originate Network-LSA for Interface %s", oi->interface->name);
385 /* If none of neighbor is adjacent to us */
386 count = 0;
388 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
389 if (on->state == OSPF6_NEIGHBOR_FULL)
390 count++;
392 if (count == 0)
394 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
395 zlog_debug ("Interface stub, ignore");
396 if (old)
397 ospf6_lsa_purge (old);
398 return 0;
401 /* prepare buffer */
402 memset (buffer, 0, sizeof (buffer));
403 lsa_header = (struct ospf6_lsa_header *) buffer;
404 network_lsa = (struct ospf6_network_lsa *)
405 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
407 /* Collect the interface's Link-LSAs to describe
408 network's optional capabilities */
409 type = htons (OSPF6_LSTYPE_LINK);
410 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
411 lsa = ospf6_lsdb_type_next (type, lsa))
413 link_lsa = (struct ospf6_link_lsa *)
414 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
415 network_lsa->options[0] |= link_lsa->options[0];
416 network_lsa->options[1] |= link_lsa->options[1];
417 network_lsa->options[2] |= link_lsa->options[2];
420 lsdesc = (struct ospf6_network_lsdesc *)
421 ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
423 /* set Link Description to the router itself */
424 lsdesc->router_id = oi->area->ospf6->router_id;
425 lsdesc++;
427 /* Walk through the neighbors */
428 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
430 if (on->state != OSPF6_NEIGHBOR_FULL)
431 continue;
433 /* set this neighbor's Router-ID to LSA */
434 lsdesc->router_id = on->router_id;
435 lsdesc++;
438 /* Fill LSA Header */
439 lsa_header->age = 0;
440 lsa_header->type = htons (OSPF6_LSTYPE_NETWORK);
441 lsa_header->id = htonl (oi->interface->ifindex);
442 lsa_header->adv_router = oi->area->ospf6->router_id;
443 lsa_header->seqnum =
444 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
445 lsa_header->adv_router, oi->area->lsdb);
446 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
448 /* LSA checksum */
449 ospf6_lsa_checksum (lsa_header);
451 /* create LSA */
452 lsa = ospf6_lsa_create (lsa_header);
454 /* Originate */
455 ospf6_lsa_originate_area (lsa, oi->area);
457 return 0;
461 /****************************/
462 /* RFC2740 3.4.3.6 Link-LSA */
463 /****************************/
465 static int
466 ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
468 char *start, *end, *current;
469 struct ospf6_link_lsa *link_lsa;
470 int prefixnum;
471 char buf[128], options[32];
472 struct ospf6_prefix *prefix;
473 const char *p, *mc, *la, *nu;
474 struct in6_addr in6;
476 link_lsa = (struct ospf6_link_lsa *)
477 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
479 ospf6_options_printbuf (link_lsa->options, options, sizeof (options));
480 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
481 prefixnum = ntohl (link_lsa->prefix_num);
483 vty_out (vty, " Priority: %d Options: %s%s",
484 link_lsa->priority, options, VNL);
485 vty_out (vty, " LinkLocal Address: %s%s", buf, VNL);
486 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
488 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
489 end = (char *) lsa->header + ntohs (lsa->header->length);
490 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
492 prefix = (struct ospf6_prefix *) current;
493 if (prefix->prefix_length == 0 ||
494 current + OSPF6_PREFIX_SIZE (prefix) > end)
495 break;
497 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
498 "P" : "--");
499 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
500 "MC" : "--");
501 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
502 "LA" : "--");
503 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
504 "NU" : "--");
505 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
506 p, mc, la, nu, VNL);
508 memset (&in6, 0, sizeof (in6));
509 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
510 OSPF6_PREFIX_SPACE (prefix->prefix_length));
511 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
512 vty_out (vty, " Prefix: %s/%d%s",
513 buf, prefix->prefix_length, VNL);
516 return 0;
520 ospf6_link_lsa_originate (struct thread *thread)
522 struct ospf6_interface *oi;
524 char buffer[OSPF6_MAX_LSASIZE];
525 struct ospf6_lsa_header *lsa_header;
526 struct ospf6_lsa *old, *lsa;
528 struct ospf6_link_lsa *link_lsa;
529 struct ospf6_route *route;
530 struct ospf6_prefix *op;
532 oi = (struct ospf6_interface *) THREAD_ARG (thread);
533 oi->thread_link_lsa = NULL;
535 assert (oi->area);
537 /* find previous LSA */
538 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
539 htonl (oi->interface->ifindex),
540 oi->area->ospf6->router_id, oi->lsdb);
542 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
544 if (old)
545 ospf6_lsa_purge (old);
546 return 0;
549 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
550 zlog_debug ("Originate Link-LSA for Interface %s", oi->interface->name);
552 /* can't make Link-LSA if linklocal address not set */
553 if (oi->linklocal_addr == NULL)
555 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
556 zlog_debug ("No Linklocal address on %s, defer originating",
557 oi->interface->name);
558 if (old)
559 ospf6_lsa_purge (old);
560 return 0;
563 /* prepare buffer */
564 memset (buffer, 0, sizeof (buffer));
565 lsa_header = (struct ospf6_lsa_header *) buffer;
566 link_lsa = (struct ospf6_link_lsa *)
567 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
569 /* Fill Link-LSA */
570 link_lsa->priority = oi->priority;
571 memcpy (link_lsa->options, oi->area->options, 3);
572 memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr,
573 sizeof (struct in6_addr));
574 link_lsa->prefix_num = htonl (oi->route_connected->count);
576 op = (struct ospf6_prefix *)
577 ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa));
579 /* connected prefix to advertise */
580 for (route = ospf6_route_head (oi->route_connected); route;
581 route = ospf6_route_next (route))
583 op->prefix_length = route->prefix.prefixlen;
584 op->prefix_options = route->path.prefix_options;
585 op->prefix_metric = htons (0);
586 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
587 OSPF6_PREFIX_SPACE (op->prefix_length));
588 op = OSPF6_PREFIX_NEXT (op);
591 /* Fill LSA Header */
592 lsa_header->age = 0;
593 lsa_header->type = htons (OSPF6_LSTYPE_LINK);
594 lsa_header->id = htonl (oi->interface->ifindex);
595 lsa_header->adv_router = oi->area->ospf6->router_id;
596 lsa_header->seqnum =
597 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
598 lsa_header->adv_router, oi->lsdb);
599 lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer);
601 /* LSA checksum */
602 ospf6_lsa_checksum (lsa_header);
604 /* create LSA */
605 lsa = ospf6_lsa_create (lsa_header);
607 /* Originate */
608 ospf6_lsa_originate_interface (lsa, oi);
610 return 0;
614 /*****************************************/
615 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
616 /*****************************************/
618 static int
619 ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
621 char *start, *end, *current;
622 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
623 int prefixnum;
624 char buf[128];
625 struct ospf6_prefix *prefix;
626 char id[16], adv_router[16];
627 const char *p, *mc, *la, *nu;
628 struct in6_addr in6;
630 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
631 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
633 prefixnum = ntohs (intra_prefix_lsa->prefix_num);
635 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
637 inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id));
638 inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router,
639 adv_router, sizeof (adv_router));
640 vty_out (vty, " Reference: %s Id: %s Adv: %s%s",
641 ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router,
642 VNL);
644 start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
645 end = (char *) lsa->header + ntohs (lsa->header->length);
646 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
648 prefix = (struct ospf6_prefix *) current;
649 if (prefix->prefix_length == 0 ||
650 current + OSPF6_PREFIX_SIZE (prefix) > end)
651 break;
653 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
654 "P" : "--");
655 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
656 "MC" : "--");
657 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
658 "LA" : "--");
659 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
660 "NU" : "--");
661 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
662 p, mc, la, nu, VNL);
664 memset (&in6, 0, sizeof (in6));
665 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
666 OSPF6_PREFIX_SPACE (prefix->prefix_length));
667 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
668 vty_out (vty, " Prefix: %s/%d%s",
669 buf, prefix->prefix_length, VNL);
672 return 0;
676 ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
678 struct ospf6_area *oa;
680 char buffer[OSPF6_MAX_LSASIZE];
681 struct ospf6_lsa_header *lsa_header;
682 struct ospf6_lsa *old, *lsa;
684 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
685 struct ospf6_interface *oi;
686 struct ospf6_neighbor *on;
687 struct ospf6_route *route;
688 struct ospf6_prefix *op;
689 struct listnode *i, *j;
690 int full_count = 0;
691 unsigned short prefix_num = 0;
692 char buf[BUFSIZ];
693 struct ospf6_route_table *route_advertise;
695 oa = (struct ospf6_area *) THREAD_ARG (thread);
696 oa->thread_intra_prefix_lsa = NULL;
698 /* find previous LSA */
699 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
700 htonl (0), oa->ospf6->router_id, oa->lsdb);
702 if (! IS_AREA_ENABLED (oa))
704 if (old)
705 ospf6_lsa_purge (old);
706 return 0;
709 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
710 zlog_debug ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
711 oa->name);
713 /* prepare buffer */
714 memset (buffer, 0, sizeof (buffer));
715 lsa_header = (struct ospf6_lsa_header *) buffer;
716 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
717 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
719 /* Fill Intra-Area-Prefix-LSA */
720 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER);
721 intra_prefix_lsa->ref_id = htonl (0);
722 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
724 route_advertise = ospf6_route_table_create (0, 0);
726 for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
728 if (oi->state == OSPF6_INTERFACE_DOWN)
730 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
731 zlog_debug (" Interface %s is down, ignore", oi->interface->name);
732 continue;
735 full_count = 0;
737 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
738 if (on->state == OSPF6_NEIGHBOR_FULL)
739 full_count++;
741 if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
742 oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
743 full_count != 0)
745 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
746 zlog_debug (" Interface %s is not stub, ignore",
747 oi->interface->name);
748 continue;
751 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
752 zlog_debug (" Interface %s:", oi->interface->name);
754 /* connected prefix to advertise */
755 for (route = ospf6_route_head (oi->route_connected); route;
756 route = ospf6_route_best_next (route))
758 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
760 prefix2str (&route->prefix, buf, sizeof (buf));
761 zlog_debug (" include %s", buf);
763 ospf6_route_add (ospf6_route_copy (route), route_advertise);
767 if (route_advertise->count == 0)
769 if (old)
770 ospf6_lsa_purge (old);
771 ospf6_route_table_delete (route_advertise);
772 return 0;
775 /* put prefixes to advertise */
776 prefix_num = 0;
777 op = (struct ospf6_prefix *)
778 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
779 for (route = ospf6_route_head (route_advertise); route;
780 route = ospf6_route_best_next (route))
782 op->prefix_length = route->prefix.prefixlen;
783 op->prefix_options = route->path.prefix_options;
784 op->prefix_metric = htons (route->path.cost);
785 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
786 OSPF6_PREFIX_SPACE (op->prefix_length));
787 op = OSPF6_PREFIX_NEXT (op);
788 prefix_num++;
791 ospf6_route_table_delete (route_advertise);
793 if (prefix_num == 0)
795 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
796 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
797 return 0;
800 intra_prefix_lsa->prefix_num = htons (prefix_num);
802 /* Fill LSA Header */
803 lsa_header->age = 0;
804 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
805 lsa_header->id = htonl (0);
806 lsa_header->adv_router = oa->ospf6->router_id;
807 lsa_header->seqnum =
808 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
809 lsa_header->adv_router, oa->lsdb);
810 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
812 /* LSA checksum */
813 ospf6_lsa_checksum (lsa_header);
815 /* create LSA */
816 lsa = ospf6_lsa_create (lsa_header);
818 /* Originate */
819 ospf6_lsa_originate_area (lsa, oa);
821 return 0;
826 ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
828 struct ospf6_interface *oi;
830 char buffer[OSPF6_MAX_LSASIZE];
831 struct ospf6_lsa_header *lsa_header;
832 struct ospf6_lsa *old, *lsa;
834 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
835 struct ospf6_neighbor *on;
836 struct ospf6_route *route;
837 struct ospf6_prefix *op;
838 struct listnode *i;
839 int full_count = 0;
840 unsigned short prefix_num = 0;
841 struct ospf6_route_table *route_advertise;
842 struct ospf6_link_lsa *link_lsa;
843 char *start, *end, *current;
844 u_int16_t type;
845 char buf[BUFSIZ];
847 oi = (struct ospf6_interface *) THREAD_ARG (thread);
848 oi->thread_intra_prefix_lsa = NULL;
850 assert (oi->area);
852 /* find previous LSA */
853 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
854 htonl (oi->interface->ifindex),
855 oi->area->ospf6->router_id, oi->area->lsdb);
857 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
859 if (old)
860 ospf6_lsa_purge (old);
861 return 0;
864 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
865 zlog_debug ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
866 oi->interface->name);
868 /* prepare buffer */
869 memset (buffer, 0, sizeof (buffer));
870 lsa_header = (struct ospf6_lsa_header *) buffer;
871 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
872 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
874 /* Fill Intra-Area-Prefix-LSA */
875 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK);
876 intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex);
877 intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
879 if (oi->state != OSPF6_INTERFACE_DR)
881 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
882 zlog_debug (" Interface is not DR");
883 if (old)
884 ospf6_lsa_purge (old);
885 return 0;
888 full_count = 0;
889 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
890 if (on->state == OSPF6_NEIGHBOR_FULL)
891 full_count++;
893 if (full_count == 0)
895 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
896 zlog_debug (" Interface is stub");
897 if (old)
898 ospf6_lsa_purge (old);
899 return 0;
902 /* connected prefix to advertise */
903 route_advertise = ospf6_route_table_create (0, 0);
905 type = ntohs (OSPF6_LSTYPE_LINK);
906 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
907 lsa = ospf6_lsdb_type_next (type, lsa))
909 if (OSPF6_LSA_IS_MAXAGE (lsa))
910 continue;
912 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
913 zlog_debug (" include prefix from %s", lsa->name);
915 if (lsa->header->adv_router != oi->area->ospf6->router_id)
917 on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
918 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
920 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
921 zlog_debug (" Neighbor not found or not Full, ignore");
922 continue;
926 link_lsa = (struct ospf6_link_lsa *)
927 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
929 prefix_num = (unsigned short) ntohl (link_lsa->prefix_num);
930 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
931 end = (char *) lsa->header + ntohs (lsa->header->length);
932 for (current = start; current < end && prefix_num;
933 current += OSPF6_PREFIX_SIZE (op))
935 op = (struct ospf6_prefix *) current;
936 if (op->prefix_length == 0 ||
937 current + OSPF6_PREFIX_SIZE (op) > end)
938 break;
940 route = ospf6_route_create ();
942 route->type = OSPF6_DEST_TYPE_NETWORK;
943 route->prefix.family = AF_INET6;
944 route->prefix.prefixlen = op->prefix_length;
945 memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr));
946 memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
947 OSPF6_PREFIX_SPACE (op->prefix_length));
949 route->path.origin.type = lsa->header->type;
950 route->path.origin.id = lsa->header->id;
951 route->path.origin.adv_router = lsa->header->adv_router;
952 route->path.options[0] = link_lsa->options[0];
953 route->path.options[1] = link_lsa->options[1];
954 route->path.options[2] = link_lsa->options[2];
955 route->path.prefix_options = op->prefix_options;
956 route->path.area_id = oi->area->area_id;
957 route->path.type = OSPF6_PATH_TYPE_INTRA;
959 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
961 prefix2str (&route->prefix, buf, sizeof (buf));
962 zlog_debug (" include %s", buf);
965 ospf6_route_add (route, route_advertise);
966 prefix_num--;
968 if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
969 zlog_debug ("Trailing garbage in %s", lsa->name);
972 op = (struct ospf6_prefix *)
973 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
975 prefix_num = 0;
976 for (route = ospf6_route_head (route_advertise); route;
977 route = ospf6_route_best_next (route))
979 op->prefix_length = route->prefix.prefixlen;
980 op->prefix_options = route->path.prefix_options;
981 op->prefix_metric = htons (0);
982 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
983 OSPF6_PREFIX_SPACE (op->prefix_length));
984 op = OSPF6_PREFIX_NEXT (op);
985 prefix_num++;
988 ospf6_route_table_delete (route_advertise);
990 if (prefix_num == 0)
992 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
993 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
994 return 0;
997 intra_prefix_lsa->prefix_num = htons (prefix_num);
999 /* Fill LSA Header */
1000 lsa_header->age = 0;
1001 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1002 lsa_header->id = htonl (oi->interface->ifindex);
1003 lsa_header->adv_router = oi->area->ospf6->router_id;
1004 lsa_header->seqnum =
1005 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
1006 lsa_header->adv_router, oi->area->lsdb);
1007 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
1009 /* LSA checksum */
1010 ospf6_lsa_checksum (lsa_header);
1012 /* create LSA */
1013 lsa = ospf6_lsa_create (lsa_header);
1015 /* Originate */
1016 ospf6_lsa_originate_area (lsa, oi->area);
1018 return 0;
1021 void
1022 ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
1024 struct ospf6_area *oa;
1025 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1026 struct prefix ls_prefix;
1027 struct ospf6_route *route, *ls_entry;
1028 int i, prefix_num;
1029 struct ospf6_prefix *op;
1030 char *start, *current, *end;
1031 char buf[64];
1033 if (OSPF6_LSA_IS_MAXAGE (lsa))
1034 return;
1036 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1037 zlog_debug ("%s found", lsa->name);
1039 oa = OSPF6_AREA (lsa->lsdb->data);
1041 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1042 OSPF6_LSA_HEADER_END (lsa->header);
1043 if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
1044 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1045 htonl (0), &ls_prefix);
1046 else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
1047 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1048 intra_prefix_lsa->ref_id, &ls_prefix);
1049 else
1051 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1052 zlog_debug ("Unknown reference LS-type: %#hx",
1053 ntohs (intra_prefix_lsa->ref_type));
1054 return;
1057 ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
1058 if (ls_entry == NULL)
1060 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1062 ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
1063 zlog_debug ("LS entry does not exist: %s", buf);
1065 return;
1068 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1069 start = (caddr_t) intra_prefix_lsa +
1070 sizeof (struct ospf6_intra_prefix_lsa);
1071 end = OSPF6_LSA_END (lsa->header);
1072 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1074 op = (struct ospf6_prefix *) current;
1075 if (prefix_num == 0)
1076 break;
1077 if (end < current + OSPF6_PREFIX_SIZE (op))
1078 break;
1080 route = ospf6_route_create ();
1082 memset (&route->prefix, 0, sizeof (struct prefix));
1083 route->prefix.family = AF_INET6;
1084 route->prefix.prefixlen = op->prefix_length;
1085 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op);
1087 route->type = OSPF6_DEST_TYPE_NETWORK;
1088 route->path.origin.type = lsa->header->type;
1089 route->path.origin.id = lsa->header->id;
1090 route->path.origin.adv_router = lsa->header->adv_router;
1091 route->path.prefix_options = op->prefix_options;
1092 route->path.area_id = oa->area_id;
1093 route->path.type = OSPF6_PATH_TYPE_INTRA;
1094 route->path.metric_type = 1;
1095 route->path.cost = ls_entry->path.cost +
1096 ntohs (op->prefix_metric);
1098 for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
1099 i < OSPF6_MULTI_PATH_LIMIT; i++)
1100 ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
1102 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1104 prefix2str (&route->prefix, buf, sizeof (buf));
1105 zlog_debug (" add %s", buf);
1108 ospf6_route_add (route, oa->route_table);
1109 prefix_num--;
1112 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1113 zlog_debug ("Trailing garbage ignored");
1116 void
1117 ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
1119 struct ospf6_area *oa;
1120 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1121 struct prefix prefix;
1122 struct ospf6_route *route;
1123 int prefix_num;
1124 struct ospf6_prefix *op;
1125 char *start, *current, *end;
1126 char buf[64];
1128 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1129 zlog_debug ("%s disappearing", lsa->name);
1131 oa = OSPF6_AREA (lsa->lsdb->data);
1133 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1134 OSPF6_LSA_HEADER_END (lsa->header);
1136 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1137 start = (caddr_t) intra_prefix_lsa +
1138 sizeof (struct ospf6_intra_prefix_lsa);
1139 end = OSPF6_LSA_END (lsa->header);
1140 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1142 op = (struct ospf6_prefix *) current;
1143 if (prefix_num == 0)
1144 break;
1145 if (end < current + OSPF6_PREFIX_SIZE (op))
1146 break;
1147 prefix_num--;
1149 memset (&prefix, 0, sizeof (struct prefix));
1150 prefix.family = AF_INET6;
1151 prefix.prefixlen = op->prefix_length;
1152 ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
1154 route = ospf6_route_lookup (&prefix, oa->route_table);
1155 if (route == NULL)
1156 continue;
1158 for (ospf6_route_lock (route);
1159 route && ospf6_route_is_prefix (&prefix, route);
1160 route = ospf6_route_next (route))
1162 if (route->type != OSPF6_DEST_TYPE_NETWORK)
1163 continue;
1164 if (route->path.area_id != oa->area_id)
1165 continue;
1166 if (route->path.type != OSPF6_PATH_TYPE_INTRA)
1167 continue;
1168 if (route->path.origin.type != lsa->header->type ||
1169 route->path.origin.id != lsa->header->id ||
1170 route->path.origin.adv_router != lsa->header->adv_router)
1171 continue;
1173 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1175 prefix2str (&route->prefix, buf, sizeof (buf));
1176 zlog_debug ("remove %s", buf);
1178 ospf6_route_remove (route, oa->route_table);
1182 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1183 zlog_debug ("Trailing garbage ignored");
1186 void
1187 ospf6_intra_route_calculation (struct ospf6_area *oa)
1189 struct ospf6_route *route;
1190 u_int16_t type;
1191 struct ospf6_lsa *lsa;
1192 void (*hook_add) (struct ospf6_route *) = NULL;
1193 void (*hook_remove) (struct ospf6_route *) = NULL;
1195 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1196 zlog_debug ("Re-examin intra-routes for area %s", oa->name);
1198 hook_add = oa->route_table->hook_add;
1199 hook_remove = oa->route_table->hook_remove;
1200 oa->route_table->hook_add = NULL;
1201 oa->route_table->hook_remove = NULL;
1203 for (route = ospf6_route_head (oa->route_table); route;
1204 route = ospf6_route_next (route))
1205 route->flag = OSPF6_ROUTE_REMOVE;
1207 type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1208 for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
1209 lsa = ospf6_lsdb_type_next (type, lsa))
1210 ospf6_intra_prefix_lsa_add (lsa);
1212 oa->route_table->hook_add = hook_add;
1213 oa->route_table->hook_remove = hook_remove;
1215 for (route = ospf6_route_head (oa->route_table); route;
1216 route = ospf6_route_next (route))
1218 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
1219 CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
1221 UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
1222 UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
1225 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
1226 ospf6_route_remove (route, oa->route_table);
1227 else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
1228 CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
1230 if (hook_add)
1231 (*hook_add) (route);
1234 route->flag = 0;
1237 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1238 zlog_debug ("Re-examin intra-routes for area %s: Done", oa->name);
1241 static void
1242 ospf6_brouter_debug_print (struct ospf6_route *brouter)
1244 u_int32_t brouter_id;
1245 char brouter_name[16];
1246 char area_name[16];
1247 char destination[64];
1248 char installed[16], changed[16];
1249 struct timeval now, res;
1250 char id[16], adv_router[16];
1251 char capa[16], options[16];
1253 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1254 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1255 inet_ntop (AF_INET, &brouter->path.area_id, area_name, sizeof (area_name));
1256 ospf6_linkstate_prefix2str (&brouter->prefix, destination,
1257 sizeof (destination));
1259 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
1260 timersub (&now, &brouter->installed, &res);
1261 timerstring (&res, installed, sizeof (installed));
1263 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
1264 timersub (&now, &brouter->changed, &res);
1265 timerstring (&res, changed, sizeof (changed));
1267 inet_ntop (AF_INET, &brouter->path.origin.id, id, sizeof (id));
1268 inet_ntop (AF_INET, &brouter->path.origin.adv_router, adv_router,
1269 sizeof (adv_router));
1271 ospf6_options_printbuf (brouter->path.options, options, sizeof (options));
1272 ospf6_capability_printbuf (brouter->path.router_bits, capa, sizeof (capa));
1274 zlog_info ("Brouter: %s via area %s", brouter_name, area_name);
1275 zlog_info (" memory: prev: %p this: %p next: %p parent rnode: %p",
1276 brouter->prev, brouter, brouter->next, brouter->rnode);
1277 zlog_info (" type: %d prefix: %s installed: %s changed: %s",
1278 brouter->type, destination, installed, changed);
1279 zlog_info (" lock: %d flags: %s%s%s%s", brouter->lock,
1280 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
1281 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
1282 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
1283 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
1284 zlog_info (" path type: %s ls-origin %s id: %s adv-router %s",
1285 OSPF6_PATH_TYPE_NAME (brouter->path.type),
1286 ospf6_lstype_name (brouter->path.origin.type),
1287 id, adv_router);
1288 zlog_info (" options: %s router-bits: %s metric-type: %d metric: %d/%d",
1289 options, capa, brouter->path.metric_type,
1290 brouter->path.cost, brouter->path.cost_e2);
1293 void
1294 ospf6_intra_brouter_calculation (struct ospf6_area *oa)
1296 struct ospf6_route *brouter, *copy;
1297 void (*hook_add) (struct ospf6_route *) = NULL;
1298 void (*hook_remove) (struct ospf6_route *) = NULL;
1299 u_int32_t brouter_id;
1300 char brouter_name[16];
1302 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1303 zlog_info ("border-router calculation for area %s", oa->name);
1305 hook_add = oa->ospf6->brouter_table->hook_add;
1306 hook_remove = oa->ospf6->brouter_table->hook_remove;
1307 oa->ospf6->brouter_table->hook_add = NULL;
1308 oa->ospf6->brouter_table->hook_remove = NULL;
1310 /* withdraw the previous router entries for the area */
1311 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1312 brouter = ospf6_route_next (brouter))
1314 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1315 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1316 if (brouter->path.area_id != oa->area_id)
1317 continue;
1318 brouter->flag = OSPF6_ROUTE_REMOVE;
1320 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1321 IS_OSPF6_DEBUG_ROUTE (MEMORY))
1323 zlog_info ("%p: mark as removing: area %s brouter %s",
1324 brouter, oa->name, brouter_name);
1325 ospf6_brouter_debug_print (brouter);
1329 for (brouter = ospf6_route_head (oa->spf_table); brouter;
1330 brouter = ospf6_route_next (brouter))
1332 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1333 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1335 if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
1336 continue;
1337 if (ospf6_linkstate_prefix_id (&brouter->prefix) != htonl (0))
1338 continue;
1339 if (! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_E) &&
1340 ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
1341 continue;
1343 copy = ospf6_route_copy (brouter);
1344 copy->type = OSPF6_DEST_TYPE_ROUTER;
1345 copy->path.area_id = oa->area_id;
1346 ospf6_route_add (copy, oa->ospf6->brouter_table);
1348 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1349 IS_OSPF6_DEBUG_ROUTE (MEMORY))
1351 zlog_info ("%p: transfer: area %s brouter %s",
1352 brouter, oa->name, brouter_name);
1353 ospf6_brouter_debug_print (brouter);
1357 oa->ospf6->brouter_table->hook_add = hook_add;
1358 oa->ospf6->brouter_table->hook_remove = hook_remove;
1360 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1361 brouter = ospf6_route_next (brouter))
1363 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1364 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1366 if (brouter->path.area_id != oa->area_id)
1367 continue;
1369 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
1370 continue;
1372 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) &&
1373 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD))
1375 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
1376 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
1379 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE))
1381 if (IS_OSPF6_DEBUG_BROUTER ||
1382 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1383 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1384 zlog_info ("brouter %s disappears via area %s",
1385 brouter_name, oa->name);
1386 ospf6_route_remove (brouter, oa->ospf6->brouter_table);
1388 else if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ||
1389 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE))
1391 if (IS_OSPF6_DEBUG_BROUTER ||
1392 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1393 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1394 zlog_info ("brouter %s appears via area %s",
1395 brouter_name, oa->name);
1397 /* newly added */
1398 if (hook_add)
1399 (*hook_add) (brouter);
1401 else
1403 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1404 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1405 zlog_info ("brouter %s still exists via area %s",
1406 brouter_name, oa->name);
1409 brouter->flag = 0;
1412 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1413 zlog_info ("border-router calculation for area %s: done", oa->name);
1416 struct ospf6_lsa_handler router_handler =
1418 OSPF6_LSTYPE_ROUTER,
1419 "Router",
1420 ospf6_router_lsa_show
1423 struct ospf6_lsa_handler network_handler =
1425 OSPF6_LSTYPE_NETWORK,
1426 "Network",
1427 ospf6_network_lsa_show
1430 struct ospf6_lsa_handler link_handler =
1432 OSPF6_LSTYPE_LINK,
1433 "Link",
1434 ospf6_link_lsa_show
1437 struct ospf6_lsa_handler intra_prefix_handler =
1439 OSPF6_LSTYPE_INTRA_PREFIX,
1440 "Intra-Prefix",
1441 ospf6_intra_prefix_lsa_show
1444 void
1445 ospf6_intra_init (void)
1447 ospf6_install_lsa_handler (&router_handler);
1448 ospf6_install_lsa_handler (&network_handler);
1449 ospf6_install_lsa_handler (&link_handler);
1450 ospf6_install_lsa_handler (&intra_prefix_handler);
1453 DEFUN (debug_ospf6_brouter,
1454 debug_ospf6_brouter_cmd,
1455 "debug ospf6 border-routers",
1456 DEBUG_STR
1457 OSPF6_STR
1458 "Debug border router\n"
1461 OSPF6_DEBUG_BROUTER_ON ();
1462 return CMD_SUCCESS;
1465 DEFUN (no_debug_ospf6_brouter,
1466 no_debug_ospf6_brouter_cmd,
1467 "no debug ospf6 border-routers",
1468 NO_STR
1469 DEBUG_STR
1470 OSPF6_STR
1471 "Debug border router\n"
1474 OSPF6_DEBUG_BROUTER_OFF ();
1475 return CMD_SUCCESS;
1478 DEFUN (debug_ospf6_brouter_router,
1479 debug_ospf6_brouter_router_cmd,
1480 "debug ospf6 border-routers router-id A.B.C.D",
1481 DEBUG_STR
1482 OSPF6_STR
1483 "Debug border router\n"
1484 "Debug specific border router\n"
1485 "Specify border-router's router-id\n"
1488 u_int32_t router_id;
1489 inet_pton (AF_INET, argv[0], &router_id);
1490 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON (router_id);
1491 return CMD_SUCCESS;
1494 DEFUN (no_debug_ospf6_brouter_router,
1495 no_debug_ospf6_brouter_router_cmd,
1496 "no debug ospf6 border-routers router-id",
1497 NO_STR
1498 DEBUG_STR
1499 OSPF6_STR
1500 "Debug border router\n"
1501 "Debug specific border router\n"
1504 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF ();
1505 return CMD_SUCCESS;
1508 DEFUN (debug_ospf6_brouter_area,
1509 debug_ospf6_brouter_area_cmd,
1510 "debug ospf6 border-routers area-id A.B.C.D",
1511 DEBUG_STR
1512 OSPF6_STR
1513 "Debug border router\n"
1514 "Debug border routers in specific Area\n"
1515 "Specify Area-ID\n"
1518 u_int32_t area_id;
1519 inet_pton (AF_INET, argv[0], &area_id);
1520 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON (area_id);
1521 return CMD_SUCCESS;
1524 DEFUN (no_debug_ospf6_brouter_area,
1525 no_debug_ospf6_brouter_area_cmd,
1526 "no debug ospf6 border-routers area-id",
1527 NO_STR
1528 DEBUG_STR
1529 OSPF6_STR
1530 "Debug border router\n"
1531 "Debug border routers in specific Area\n"
1534 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF ();
1535 return CMD_SUCCESS;
1539 config_write_ospf6_debug_brouter (struct vty *vty)
1541 char buf[16];
1542 if (IS_OSPF6_DEBUG_BROUTER)
1543 vty_out (vty, "debug ospf6 border-routers%s", VNL);
1544 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER)
1546 inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
1547 buf, sizeof (buf));
1548 vty_out (vty, "debug ospf6 border-routers router-id %s%s", buf, VNL);
1550 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA)
1552 inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
1553 buf, sizeof (buf));
1554 vty_out (vty, "debug ospf6 border-routers area-id %s%s", buf, VNL);
1556 return 0;
1559 void
1560 install_element_ospf6_debug_brouter (void)
1562 install_element (ENABLE_NODE, &debug_ospf6_brouter_cmd);
1563 install_element (ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
1564 install_element (ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
1565 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
1566 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
1567 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
1568 install_element (CONFIG_NODE, &debug_ospf6_brouter_cmd);
1569 install_element (CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
1570 install_element (CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
1571 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
1572 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
1573 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);