]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_intra.c
bgpd: Function to encode Encapsulation type extended community
[mirror_frr.git] / ospf6d / ospf6_intra.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
3 *
4 * This file is part of GNU Zebra.
5 *
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.
10 *
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.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "log.h"
24 #include "linklist.h"
25 #include "thread.h"
26 #include "memory.h"
27 #include "if.h"
28 #include "prefix.h"
29 #include "table.h"
30 #include "vty.h"
31 #include "command.h"
32 #include "vrf.h"
33
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"
39
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"
49 #include "ospf6_spf.h"
50
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;
54
55 /******************************/
56 /* RFC2740 3.4.3.1 Router-LSA */
57 /******************************/
58
59 static char *
60 ospf6_router_lsa_get_nbr_id (struct ospf6_lsa *lsa, char *buf, int buflen,
61 int pos)
62 {
63 struct ospf6_router_lsa *router_lsa;
64 struct ospf6_router_lsdesc *lsdesc;
65 char *start, *end;
66 char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
67
68 if (lsa)
69 {
70 router_lsa = (struct ospf6_router_lsa *)
71 ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
72 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
73 end = (char *) lsa->header + ntohs (lsa->header->length);
74
75 lsdesc = (struct ospf6_router_lsdesc *)
76 (start + pos*(sizeof (struct ospf6_router_lsdesc)));
77 if ((char *)lsdesc < end)
78 {
79 if (buf && (buflen > INET_ADDRSTRLEN*2))
80 {
81 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
82 buf1, sizeof(buf1));
83 inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
84 buf2, sizeof(buf2));
85 sprintf (buf, "%s/%s", buf2, buf1);
86 }
87 }
88 else
89 return NULL;
90 }
91
92 return buf;
93 }
94
95 static int
96 ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
97 {
98 char *start, *end, *current;
99 char buf[32], name[32], bits[16], options[32];
100 struct ospf6_router_lsa *router_lsa;
101 struct ospf6_router_lsdesc *lsdesc;
102
103 router_lsa = (struct ospf6_router_lsa *)
104 ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
105
106 ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
107 ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
108 vty_out (vty, " Bits: %s Options: %s%s", bits, options, VNL);
109
110 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
111 end = (char *) lsa->header + ntohs (lsa->header->length);
112 for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
113 current += sizeof (struct ospf6_router_lsdesc))
114 {
115 lsdesc = (struct ospf6_router_lsdesc *) current;
116
117 if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
118 snprintf (name, sizeof (name), "Point-To-Point");
119 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
120 snprintf (name, sizeof (name), "Transit-Network");
121 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
122 snprintf (name, sizeof (name), "Stub-Network");
123 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
124 snprintf (name, sizeof (name), "Virtual-Link");
125 else
126 snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
127
128 vty_out (vty, " Type: %s Metric: %d%s",
129 name, ntohs (lsdesc->metric), VNL);
130 vty_out (vty, " Interface ID: %s%s",
131 inet_ntop (AF_INET, &lsdesc->interface_id,
132 buf, sizeof (buf)), VNL);
133 vty_out (vty, " Neighbor Interface ID: %s%s",
134 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
135 buf, sizeof (buf)), VNL);
136 vty_out (vty, " Neighbor Router ID: %s%s",
137 inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
138 buf, sizeof (buf)), VNL);
139 }
140 return 0;
141 }
142
143 static void
144 ospf6_router_lsa_options_set (struct ospf6_area *oa,
145 struct ospf6_router_lsa *router_lsa)
146 {
147 OSPF6_OPT_CLEAR_ALL (router_lsa->options);
148 memcpy (router_lsa->options, oa->options, 3);
149
150 if (ospf6_is_router_abr (ospf6))
151 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
152 else
153 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
154
155 if (!IS_AREA_STUB (oa) && ospf6_asbr_is_asbr (oa->ospf6))
156 {
157 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
158 }
159 else
160 {
161 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
162 }
163
164 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
165 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
166 }
167
168 int
169 ospf6_router_is_stub_router (struct ospf6_lsa *lsa)
170 {
171 struct ospf6_router_lsa *rtr_lsa;
172
173 if (lsa != NULL && OSPF6_LSA_IS_TYPE (ROUTER, lsa))
174 {
175 rtr_lsa = (struct ospf6_router_lsa *)
176 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
177
178 if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_R))
179 {
180 return (OSPF6_IS_STUB_ROUTER);
181 }
182 else if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_V6))
183 {
184 return (OSPF6_IS_STUB_ROUTER_V6);
185 }
186 }
187
188 return (OSPF6_NOT_STUB_ROUTER);
189 }
190
191 int
192 ospf6_router_lsa_originate (struct thread *thread)
193 {
194 struct ospf6_area *oa;
195
196 char buffer [OSPF6_MAX_LSASIZE];
197 struct ospf6_lsa_header *lsa_header;
198 struct ospf6_lsa *lsa;
199
200 u_int32_t link_state_id = 0;
201 struct listnode *node, *nnode;
202 struct listnode *j;
203 struct ospf6_interface *oi;
204 struct ospf6_neighbor *on, *drouter = NULL;
205 struct ospf6_router_lsa *router_lsa;
206 struct ospf6_router_lsdesc *lsdesc;
207 u_int16_t type;
208 u_int32_t router;
209 int count;
210
211 oa = (struct ospf6_area *) THREAD_ARG (thread);
212 oa->thread_router_lsa = NULL;
213
214 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
215 zlog_debug ("Originate Router-LSA for Area %s", oa->name);
216
217 memset (buffer, 0, sizeof (buffer));
218 lsa_header = (struct ospf6_lsa_header *) buffer;
219 router_lsa = (struct ospf6_router_lsa *)
220 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
221
222 ospf6_router_lsa_options_set (oa, router_lsa);
223
224 /* describe links for each interfaces */
225 lsdesc = (struct ospf6_router_lsdesc *)
226 ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
227
228 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
229 {
230 /* Interfaces in state Down or Loopback are not described */
231 if (oi->state == OSPF6_INTERFACE_DOWN ||
232 oi->state == OSPF6_INTERFACE_LOOPBACK)
233 continue;
234
235 /* Nor are interfaces without any full adjacencies described */
236 count = 0;
237 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
238 if (on->state == OSPF6_NEIGHBOR_FULL)
239 count++;
240
241 if (count == 0)
242 continue;
243
244 /* Multiple Router-LSA instance according to size limit setting */
245 if ( (oa->router_lsa_size_limit != 0)
246 && ((size_t)((char *)lsdesc - buffer)
247 + sizeof (struct ospf6_router_lsdesc)
248 > oa->router_lsa_size_limit))
249 {
250 if ((caddr_t) lsdesc == (caddr_t) router_lsa +
251 sizeof (struct ospf6_router_lsa))
252 {
253 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
254 zlog_debug ("Size limit setting for Router-LSA too short");
255 return 0;
256 }
257
258 link_state_id ++;
259 }
260
261 /* Point-to-Point interfaces */
262 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
263 {
264 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
265 {
266 if (on->state != OSPF6_NEIGHBOR_FULL)
267 continue;
268
269 lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
270 lsdesc->metric = htons (oi->cost);
271 lsdesc->interface_id = htonl (oi->interface->ifindex);
272 lsdesc->neighbor_interface_id = htonl (on->ifindex);
273 lsdesc->neighbor_router_id = on->router_id;
274
275 lsdesc++;
276 }
277 }
278
279 /* Broadcast and NBMA interfaces */
280 else if (oi->type == OSPF_IFTYPE_BROADCAST)
281 {
282 /* If this router is not DR,
283 and If this router not fully adjacent with DR,
284 this interface is not transit yet: ignore. */
285 if (oi->state != OSPF6_INTERFACE_DR)
286 {
287 drouter = ospf6_neighbor_lookup (oi->drouter, oi);
288 if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL)
289 continue;
290 }
291
292 lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
293 lsdesc->metric = htons (oi->cost);
294 lsdesc->interface_id = htonl (oi->interface->ifindex);
295 if (oi->state != OSPF6_INTERFACE_DR)
296 {
297 lsdesc->neighbor_interface_id = htonl (drouter->ifindex);
298 lsdesc->neighbor_router_id = drouter->router_id;
299 }
300 else
301 {
302 lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex);
303 lsdesc->neighbor_router_id = oi->area->ospf6->router_id;
304 }
305
306 lsdesc++;
307 }
308 else
309 {
310 assert (0); /* Unknown interface type */
311 }
312
313 /* Virtual links */
314 /* xxx */
315 /* Point-to-Multipoint interfaces */
316 /* xxx */
317 }
318
319 /* Fill LSA Header */
320 lsa_header->age = 0;
321 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
322 lsa_header->id = htonl (link_state_id);
323 lsa_header->adv_router = oa->ospf6->router_id;
324 lsa_header->seqnum =
325 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
326 lsa_header->adv_router, oa->lsdb);
327 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
328
329 /* LSA checksum */
330 ospf6_lsa_checksum (lsa_header);
331
332 /* create LSA */
333 lsa = ospf6_lsa_create (lsa_header);
334
335 /* Originate */
336 ospf6_lsa_originate_area (lsa, oa);
337
338 link_state_id ++;
339
340 /* Do premature-aging of rest, undesired Router-LSAs */
341 type = ntohs (OSPF6_LSTYPE_ROUTER);
342 router = oa->ospf6->router_id;
343 count = 0;
344 for (lsa = ospf6_lsdb_type_router_head (type, router, oa->lsdb); lsa;
345 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
346 {
347 if (ntohl (lsa->header->id) < link_state_id)
348 continue;
349 ospf6_lsa_purge (lsa);
350 count++;
351 }
352
353 /*
354 * Waiting till the LSA is actually removed from the database to trigger
355 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
356 * interfaces associated with an area are gone, triggering an SPF right away
357 * helps convergence with inter-area routes.
358 */
359 if (count && !link_state_id)
360 ospf6_spf_schedule (oa->ospf6, OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED);
361
362 return 0;
363 }
364
365 /*******************************/
366 /* RFC2740 3.4.3.2 Network-LSA */
367 /*******************************/
368
369 static char *
370 ospf6_network_lsa_get_ar_id (struct ospf6_lsa *lsa, char *buf, int buflen,
371 int pos)
372 {
373 char *start, *end, *current;
374 struct ospf6_network_lsa *network_lsa;
375 struct ospf6_network_lsdesc *lsdesc;
376
377 if (lsa)
378 {
379 network_lsa = (struct ospf6_network_lsa *)
380 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
381
382 start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
383 end = (char *) lsa->header + ntohs (lsa->header->length);
384 current = start + pos*(sizeof (struct ospf6_network_lsdesc));
385
386 if ((current + sizeof(struct ospf6_network_lsdesc)) <= end)
387 {
388 lsdesc = (struct ospf6_network_lsdesc *)current;
389 if (buf)
390 inet_ntop (AF_INET, &lsdesc->router_id, buf, buflen);
391 }
392 else
393 return NULL;
394 }
395
396 return (buf);
397 }
398
399 static int
400 ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
401 {
402 char *start, *end, *current;
403 struct ospf6_network_lsa *network_lsa;
404 struct ospf6_network_lsdesc *lsdesc;
405 char buf[128], options[32];
406
407 network_lsa = (struct ospf6_network_lsa *)
408 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
409
410 ospf6_options_printbuf (network_lsa->options, options, sizeof (options));
411 vty_out (vty, " Options: %s%s", options, VNL);
412
413 start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
414 end = (char *) lsa->header + ntohs (lsa->header->length);
415 for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end;
416 current += sizeof (struct ospf6_network_lsdesc))
417 {
418 lsdesc = (struct ospf6_network_lsdesc *) current;
419 inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
420 vty_out (vty, " Attached Router: %s%s", buf, VNL);
421 }
422 return 0;
423 }
424
425 int
426 ospf6_network_lsa_originate (struct thread *thread)
427 {
428 struct ospf6_interface *oi;
429
430 char buffer [OSPF6_MAX_LSASIZE];
431 struct ospf6_lsa_header *lsa_header;
432
433 int count;
434 struct ospf6_lsa *old, *lsa;
435 struct ospf6_network_lsa *network_lsa;
436 struct ospf6_network_lsdesc *lsdesc;
437 struct ospf6_neighbor *on;
438 struct ospf6_link_lsa *link_lsa;
439 struct listnode *i;
440 u_int16_t type;
441
442 oi = (struct ospf6_interface *) THREAD_ARG (thread);
443 oi->thread_network_lsa = NULL;
444
445 /* The interface must be enabled until here. A Network-LSA of a
446 disabled interface (but was once enabled) should be flushed
447 by ospf6_lsa_refresh (), and does not come here. */
448 assert (oi->area);
449
450 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
451 htonl (oi->interface->ifindex),
452 oi->area->ospf6->router_id, oi->area->lsdb);
453
454 /* Do not originate Network-LSA if not DR */
455 if (oi->state != OSPF6_INTERFACE_DR)
456 {
457 if (old)
458 {
459 ospf6_lsa_purge (old);
460 /*
461 * Waiting till the LSA is actually removed from the database to
462 * trigger SPF delays network convergence.
463 */
464 ospf6_spf_schedule (oi->area->ospf6,
465 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED);
466 }
467 return 0;
468 }
469
470 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
471 zlog_debug ("Originate Network-LSA for Interface %s", oi->interface->name);
472
473 /* If none of neighbor is adjacent to us */
474 count = 0;
475
476 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
477 if (on->state == OSPF6_NEIGHBOR_FULL)
478 count++;
479
480 if (count == 0)
481 {
482 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
483 zlog_debug ("Interface stub, ignore");
484 if (old)
485 ospf6_lsa_purge (old);
486 return 0;
487 }
488
489 /* prepare buffer */
490 memset (buffer, 0, sizeof (buffer));
491 lsa_header = (struct ospf6_lsa_header *) buffer;
492 network_lsa = (struct ospf6_network_lsa *)
493 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
494
495 /* Collect the interface's Link-LSAs to describe
496 network's optional capabilities */
497 type = htons (OSPF6_LSTYPE_LINK);
498 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
499 lsa = ospf6_lsdb_type_next (type, lsa))
500 {
501 link_lsa = (struct ospf6_link_lsa *)
502 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
503 network_lsa->options[0] |= link_lsa->options[0];
504 network_lsa->options[1] |= link_lsa->options[1];
505 network_lsa->options[2] |= link_lsa->options[2];
506 }
507
508 lsdesc = (struct ospf6_network_lsdesc *)
509 ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
510
511 /* set Link Description to the router itself */
512 lsdesc->router_id = oi->area->ospf6->router_id;
513 lsdesc++;
514
515 /* Walk through the neighbors */
516 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
517 {
518 if (on->state != OSPF6_NEIGHBOR_FULL)
519 continue;
520
521 /* set this neighbor's Router-ID to LSA */
522 lsdesc->router_id = on->router_id;
523 lsdesc++;
524 }
525
526 /* Fill LSA Header */
527 lsa_header->age = 0;
528 lsa_header->type = htons (OSPF6_LSTYPE_NETWORK);
529 lsa_header->id = htonl (oi->interface->ifindex);
530 lsa_header->adv_router = oi->area->ospf6->router_id;
531 lsa_header->seqnum =
532 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
533 lsa_header->adv_router, oi->area->lsdb);
534 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
535
536 /* LSA checksum */
537 ospf6_lsa_checksum (lsa_header);
538
539 /* create LSA */
540 lsa = ospf6_lsa_create (lsa_header);
541
542 /* Originate */
543 ospf6_lsa_originate_area (lsa, oi->area);
544
545 return 0;
546 }
547
548
549 /****************************/
550 /* RFC2740 3.4.3.6 Link-LSA */
551 /****************************/
552
553 static char *
554 ospf6_link_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, int buflen,
555 int pos)
556 {
557 char *start, *end, *current;
558 struct ospf6_link_lsa *link_lsa;
559 struct in6_addr in6;
560 struct ospf6_prefix *prefix;
561 int cnt = 0, prefixnum;
562
563 if (lsa)
564 {
565 link_lsa = (struct ospf6_link_lsa *)
566 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
567
568 if (pos == 0) {
569 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, buflen);
570 return (buf);
571 }
572
573 prefixnum = ntohl (link_lsa->prefix_num);
574 if (pos > prefixnum)
575 return (NULL);
576
577 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
578 end = (char *) lsa->header + ntohs (lsa->header->length);
579 current = start;
580
581 do
582 {
583 prefix = (struct ospf6_prefix *) current;
584 if (prefix->prefix_length == 0 ||
585 current + OSPF6_PREFIX_SIZE (prefix) > end)
586 {
587 return (NULL);
588 }
589
590 if (cnt < pos)
591 {
592 current = start + pos*OSPF6_PREFIX_SIZE(prefix);
593 cnt++;
594 }
595 else
596 {
597 memset (&in6, 0, sizeof (in6));
598 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
599 OSPF6_PREFIX_SPACE (prefix->prefix_length));
600 inet_ntop (AF_INET6, &in6, buf, buflen);
601 return (buf);
602 }
603 } while (current <= end);
604 }
605 return (NULL);
606 }
607
608 static int
609 ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
610 {
611 char *start, *end, *current;
612 struct ospf6_link_lsa *link_lsa;
613 int prefixnum;
614 char buf[128], options[32];
615 struct ospf6_prefix *prefix;
616 const char *p, *mc, *la, *nu;
617 struct in6_addr in6;
618
619 link_lsa = (struct ospf6_link_lsa *)
620 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
621
622 ospf6_options_printbuf (link_lsa->options, options, sizeof (options));
623 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
624 prefixnum = ntohl (link_lsa->prefix_num);
625
626 vty_out (vty, " Priority: %d Options: %s%s",
627 link_lsa->priority, options, VNL);
628 vty_out (vty, " LinkLocal Address: %s%s", buf, VNL);
629 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
630
631 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
632 end = (char *) lsa->header + ntohs (lsa->header->length);
633 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
634 {
635 prefix = (struct ospf6_prefix *) current;
636 if (prefix->prefix_length == 0 ||
637 current + OSPF6_PREFIX_SIZE (prefix) > end)
638 break;
639
640 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
641 "P" : "--");
642 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
643 "MC" : "--");
644 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
645 "LA" : "--");
646 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
647 "NU" : "--");
648 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
649 p, mc, la, nu, VNL);
650
651 memset (&in6, 0, sizeof (in6));
652 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
653 OSPF6_PREFIX_SPACE (prefix->prefix_length));
654 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
655 vty_out (vty, " Prefix: %s/%d%s",
656 buf, prefix->prefix_length, VNL);
657 }
658
659 return 0;
660 }
661
662 int
663 ospf6_link_lsa_originate (struct thread *thread)
664 {
665 struct ospf6_interface *oi;
666
667 char buffer[OSPF6_MAX_LSASIZE];
668 struct ospf6_lsa_header *lsa_header;
669 struct ospf6_lsa *old, *lsa;
670
671 struct ospf6_link_lsa *link_lsa;
672 struct ospf6_route *route;
673 struct ospf6_prefix *op;
674
675 oi = (struct ospf6_interface *) THREAD_ARG (thread);
676 oi->thread_link_lsa = NULL;
677
678 assert (oi->area);
679
680 /* find previous LSA */
681 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
682 htonl (oi->interface->ifindex),
683 oi->area->ospf6->router_id, oi->lsdb);
684
685 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
686 {
687 if (old)
688 ospf6_lsa_purge (old);
689 return 0;
690 }
691
692 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
693 zlog_debug ("Originate Link-LSA for Interface %s", oi->interface->name);
694
695 /* can't make Link-LSA if linklocal address not set */
696 if (oi->linklocal_addr == NULL)
697 {
698 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
699 zlog_debug ("No Linklocal address on %s, defer originating",
700 oi->interface->name);
701 if (old)
702 ospf6_lsa_purge (old);
703 return 0;
704 }
705
706 /* prepare buffer */
707 memset (buffer, 0, sizeof (buffer));
708 lsa_header = (struct ospf6_lsa_header *) buffer;
709 link_lsa = (struct ospf6_link_lsa *)
710 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
711
712 /* Fill Link-LSA */
713 link_lsa->priority = oi->priority;
714 memcpy (link_lsa->options, oi->area->options, 3);
715 memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr,
716 sizeof (struct in6_addr));
717 link_lsa->prefix_num = htonl (oi->route_connected->count);
718
719 op = (struct ospf6_prefix *)
720 ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa));
721
722 /* connected prefix to advertise */
723 for (route = ospf6_route_head (oi->route_connected); route;
724 route = ospf6_route_next (route))
725 {
726 op->prefix_length = route->prefix.prefixlen;
727 op->prefix_options = route->path.prefix_options;
728 op->prefix_metric = htons (0);
729 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
730 OSPF6_PREFIX_SPACE (op->prefix_length));
731 op = OSPF6_PREFIX_NEXT (op);
732 }
733
734 /* Fill LSA Header */
735 lsa_header->age = 0;
736 lsa_header->type = htons (OSPF6_LSTYPE_LINK);
737 lsa_header->id = htonl (oi->interface->ifindex);
738 lsa_header->adv_router = oi->area->ospf6->router_id;
739 lsa_header->seqnum =
740 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
741 lsa_header->adv_router, oi->lsdb);
742 lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer);
743
744 /* LSA checksum */
745 ospf6_lsa_checksum (lsa_header);
746
747 /* create LSA */
748 lsa = ospf6_lsa_create (lsa_header);
749
750 /* Originate */
751 ospf6_lsa_originate_interface (lsa, oi);
752
753 return 0;
754 }
755
756
757 /*****************************************/
758 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
759 /*****************************************/
760 static char *
761 ospf6_intra_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
762 int buflen, int pos)
763 {
764 char *start, *end, *current;
765 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
766 struct in6_addr in6;
767 int prefixnum, cnt = 0;
768 struct ospf6_prefix *prefix;
769
770 if (lsa)
771 {
772 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
773 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
774
775 prefixnum = ntohs (intra_prefix_lsa->prefix_num);
776 if (pos > prefixnum)
777 return (NULL);
778
779 start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
780 end = (char *) lsa->header + ntohs (lsa->header->length);
781 current = start;
782
783 do
784 {
785 prefix = (struct ospf6_prefix *) current;
786 if (prefix->prefix_length == 0 ||
787 current + OSPF6_PREFIX_SIZE (prefix) > end)
788 {
789 return NULL;
790 }
791
792 if (cnt < pos)
793 {
794 current = start + pos*OSPF6_PREFIX_SIZE(prefix);
795 cnt++;
796 }
797 else
798 {
799 memset (&in6, 0, sizeof (in6));
800 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
801 OSPF6_PREFIX_SPACE (prefix->prefix_length));
802 inet_ntop (AF_INET6, &in6, buf, buflen);
803 sprintf(&buf[strlen(buf)], "/%d", prefix->prefix_length);
804 return (buf);
805 }
806 } while (current <= end);
807 }
808 return (buf);
809 }
810
811 static int
812 ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
813 {
814 char *start, *end, *current;
815 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
816 int prefixnum;
817 char buf[128];
818 struct ospf6_prefix *prefix;
819 char id[16], adv_router[16];
820 const char *p, *mc, *la, *nu;
821 struct in6_addr in6;
822
823 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
824 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
825
826 prefixnum = ntohs (intra_prefix_lsa->prefix_num);
827
828 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
829
830 inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id));
831 inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router,
832 adv_router, sizeof (adv_router));
833 vty_out (vty, " Reference: %s Id: %s Adv: %s%s",
834 ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router,
835 VNL);
836
837 start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
838 end = (char *) lsa->header + ntohs (lsa->header->length);
839 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
840 {
841 prefix = (struct ospf6_prefix *) current;
842 if (prefix->prefix_length == 0 ||
843 current + OSPF6_PREFIX_SIZE (prefix) > end)
844 break;
845
846 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
847 "P" : "--");
848 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
849 "MC" : "--");
850 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
851 "LA" : "--");
852 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
853 "NU" : "--");
854 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
855 p, mc, la, nu, VNL);
856
857 memset (&in6, 0, sizeof (in6));
858 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
859 OSPF6_PREFIX_SPACE (prefix->prefix_length));
860 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
861 vty_out (vty, " Prefix: %s/%d%s",
862 buf, prefix->prefix_length, VNL);
863 }
864
865 return 0;
866 }
867
868 int
869 ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
870 {
871 struct ospf6_area *oa;
872
873 char buffer[OSPF6_MAX_LSASIZE];
874 struct ospf6_lsa_header *lsa_header;
875 struct ospf6_lsa *old, *lsa;
876
877 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
878 struct ospf6_interface *oi;
879 struct ospf6_neighbor *on;
880 struct ospf6_route *route;
881 struct ospf6_prefix *op;
882 struct listnode *i, *j;
883 int full_count = 0;
884 unsigned short prefix_num = 0;
885 char buf[PREFIX2STR_BUFFER];
886 struct ospf6_route_table *route_advertise;
887
888 oa = (struct ospf6_area *) THREAD_ARG (thread);
889 oa->thread_intra_prefix_lsa = NULL;
890
891 /* find previous LSA */
892 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
893 htonl (0), oa->ospf6->router_id, oa->lsdb);
894
895 if (! IS_AREA_ENABLED (oa))
896 {
897 if (old)
898 ospf6_lsa_purge (old);
899 return 0;
900 }
901
902 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
903 zlog_debug ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
904 oa->name);
905
906 /* prepare buffer */
907 memset (buffer, 0, sizeof (buffer));
908 lsa_header = (struct ospf6_lsa_header *) buffer;
909 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
910 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
911
912 /* Fill Intra-Area-Prefix-LSA */
913 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER);
914 intra_prefix_lsa->ref_id = htonl (0);
915 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
916
917 route_advertise = ospf6_route_table_create (0, 0);
918
919 for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
920 {
921 if (oi->state == OSPF6_INTERFACE_DOWN)
922 {
923 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
924 zlog_debug (" Interface %s is down, ignore", oi->interface->name);
925 continue;
926 }
927
928 full_count = 0;
929
930 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
931 if (on->state == OSPF6_NEIGHBOR_FULL)
932 full_count++;
933
934 if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
935 oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
936 full_count != 0)
937 {
938 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
939 zlog_debug (" Interface %s is not stub, ignore",
940 oi->interface->name);
941 continue;
942 }
943
944 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
945 zlog_debug (" Interface %s:", oi->interface->name);
946
947 /* connected prefix to advertise */
948 for (route = ospf6_route_head (oi->route_connected); route;
949 route = ospf6_route_best_next (route))
950 {
951 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
952 {
953 prefix2str (&route->prefix, buf, sizeof (buf));
954 zlog_debug (" include %s", buf);
955 }
956 ospf6_route_add (ospf6_route_copy (route), route_advertise);
957 }
958 }
959
960 if (route_advertise->count == 0)
961 {
962 if (old)
963 ospf6_lsa_purge (old);
964 ospf6_route_table_delete (route_advertise);
965 return 0;
966 }
967
968 /* put prefixes to advertise */
969 prefix_num = 0;
970 op = (struct ospf6_prefix *)
971 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
972 for (route = ospf6_route_head (route_advertise); route;
973 route = ospf6_route_best_next (route))
974 {
975 op->prefix_length = route->prefix.prefixlen;
976 op->prefix_options = route->path.prefix_options;
977 op->prefix_metric = htons (route->path.cost);
978 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
979 OSPF6_PREFIX_SPACE (op->prefix_length));
980 op = OSPF6_PREFIX_NEXT (op);
981 prefix_num++;
982 }
983
984 ospf6_route_table_delete (route_advertise);
985
986 if (prefix_num == 0)
987 {
988 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
989 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
990 return 0;
991 }
992
993 intra_prefix_lsa->prefix_num = htons (prefix_num);
994
995 /* Fill LSA Header */
996 lsa_header->age = 0;
997 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
998 lsa_header->id = htonl (0);
999 lsa_header->adv_router = oa->ospf6->router_id;
1000 lsa_header->seqnum =
1001 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
1002 lsa_header->adv_router, oa->lsdb);
1003 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
1004
1005 /* LSA checksum */
1006 ospf6_lsa_checksum (lsa_header);
1007
1008 /* create LSA */
1009 lsa = ospf6_lsa_create (lsa_header);
1010
1011 /* Originate */
1012 ospf6_lsa_originate_area (lsa, oa);
1013
1014 return 0;
1015 }
1016
1017
1018 int
1019 ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
1020 {
1021 struct ospf6_interface *oi;
1022
1023 char buffer[OSPF6_MAX_LSASIZE];
1024 struct ospf6_lsa_header *lsa_header;
1025 struct ospf6_lsa *old, *lsa;
1026
1027 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1028 struct ospf6_neighbor *on;
1029 struct ospf6_route *route;
1030 struct ospf6_prefix *op;
1031 struct listnode *i;
1032 int full_count = 0;
1033 unsigned short prefix_num = 0;
1034 struct ospf6_route_table *route_advertise;
1035 struct ospf6_link_lsa *link_lsa;
1036 char *start, *end, *current;
1037 u_int16_t type;
1038 char buf[PREFIX2STR_BUFFER];
1039
1040 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1041 oi->thread_intra_prefix_lsa = NULL;
1042
1043 assert (oi->area);
1044
1045 /* find previous LSA */
1046 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
1047 htonl (oi->interface->ifindex),
1048 oi->area->ospf6->router_id, oi->area->lsdb);
1049
1050 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
1051 {
1052 if (old)
1053 ospf6_lsa_purge (old);
1054 return 0;
1055 }
1056
1057 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
1058 zlog_debug ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1059 oi->interface->name);
1060
1061 /* prepare buffer */
1062 memset (buffer, 0, sizeof (buffer));
1063 lsa_header = (struct ospf6_lsa_header *) buffer;
1064 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1065 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
1066
1067 /* Fill Intra-Area-Prefix-LSA */
1068 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK);
1069 intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex);
1070 intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
1071
1072 if (oi->state != OSPF6_INTERFACE_DR)
1073 {
1074 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
1075 zlog_debug (" Interface is not DR");
1076 if (old)
1077 ospf6_lsa_purge (old);
1078 return 0;
1079 }
1080
1081 full_count = 0;
1082 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
1083 if (on->state == OSPF6_NEIGHBOR_FULL)
1084 full_count++;
1085
1086 if (full_count == 0)
1087 {
1088 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
1089 zlog_debug (" Interface is stub");
1090 if (old)
1091 ospf6_lsa_purge (old);
1092 return 0;
1093 }
1094
1095 /* connected prefix to advertise */
1096 route_advertise = ospf6_route_table_create (0, 0);
1097
1098 type = ntohs (OSPF6_LSTYPE_LINK);
1099 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
1100 lsa = ospf6_lsdb_type_next (type, lsa))
1101 {
1102 if (OSPF6_LSA_IS_MAXAGE (lsa))
1103 continue;
1104
1105 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
1106 zlog_debug (" include prefix from %s", lsa->name);
1107
1108 if (lsa->header->adv_router != oi->area->ospf6->router_id)
1109 {
1110 on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
1111 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
1112 {
1113 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
1114 zlog_debug (" Neighbor not found or not Full, ignore");
1115 continue;
1116 }
1117 }
1118
1119 link_lsa = (struct ospf6_link_lsa *)
1120 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
1121
1122 prefix_num = (unsigned short) ntohl (link_lsa->prefix_num);
1123 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
1124 end = (char *) lsa->header + ntohs (lsa->header->length);
1125 for (current = start; current < end && prefix_num;
1126 current += OSPF6_PREFIX_SIZE (op))
1127 {
1128 op = (struct ospf6_prefix *) current;
1129 if (op->prefix_length == 0 ||
1130 current + OSPF6_PREFIX_SIZE (op) > end)
1131 break;
1132
1133 route = ospf6_route_create ();
1134
1135 route->type = OSPF6_DEST_TYPE_NETWORK;
1136 route->prefix.family = AF_INET6;
1137 route->prefix.prefixlen = op->prefix_length;
1138 memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr));
1139 memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
1140 OSPF6_PREFIX_SPACE (op->prefix_length));
1141
1142 route->path.origin.type = lsa->header->type;
1143 route->path.origin.id = lsa->header->id;
1144 route->path.origin.adv_router = lsa->header->adv_router;
1145 route->path.options[0] = link_lsa->options[0];
1146 route->path.options[1] = link_lsa->options[1];
1147 route->path.options[2] = link_lsa->options[2];
1148 route->path.prefix_options = op->prefix_options;
1149 route->path.area_id = oi->area->area_id;
1150 route->path.type = OSPF6_PATH_TYPE_INTRA;
1151
1152 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
1153 {
1154 prefix2str (&route->prefix, buf, sizeof (buf));
1155 zlog_debug (" include %s", buf);
1156 }
1157
1158 ospf6_route_add (route, route_advertise);
1159 prefix_num--;
1160 }
1161 if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
1162 zlog_debug ("Trailing garbage in %s", lsa->name);
1163 }
1164
1165 op = (struct ospf6_prefix *)
1166 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
1167
1168 prefix_num = 0;
1169 for (route = ospf6_route_head (route_advertise); route;
1170 route = ospf6_route_best_next (route))
1171 {
1172 op->prefix_length = route->prefix.prefixlen;
1173 op->prefix_options = route->path.prefix_options;
1174 op->prefix_metric = htons (0);
1175 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
1176 OSPF6_PREFIX_SPACE (op->prefix_length));
1177 op = OSPF6_PREFIX_NEXT (op);
1178 prefix_num++;
1179 }
1180
1181 ospf6_route_table_delete (route_advertise);
1182
1183 if (prefix_num == 0)
1184 {
1185 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
1186 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
1187 return 0;
1188 }
1189
1190 intra_prefix_lsa->prefix_num = htons (prefix_num);
1191
1192 /* Fill LSA Header */
1193 lsa_header->age = 0;
1194 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1195 lsa_header->id = htonl (oi->interface->ifindex);
1196 lsa_header->adv_router = oi->area->ospf6->router_id;
1197 lsa_header->seqnum =
1198 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
1199 lsa_header->adv_router, oi->area->lsdb);
1200 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
1201
1202 /* LSA checksum */
1203 ospf6_lsa_checksum (lsa_header);
1204
1205 /* create LSA */
1206 lsa = ospf6_lsa_create (lsa_header);
1207
1208 /* Originate */
1209 ospf6_lsa_originate_area (lsa, oi->area);
1210
1211 return 0;
1212 }
1213
1214 void
1215 ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
1216 {
1217 struct ospf6_area *oa;
1218 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1219 struct prefix ls_prefix;
1220 struct ospf6_route *route, *ls_entry;
1221 int prefix_num;
1222 struct ospf6_prefix *op;
1223 char *start, *current, *end;
1224 char buf[PREFIX2STR_BUFFER];
1225 struct interface *ifp;
1226 int direct_connect = 0;
1227
1228 if (OSPF6_LSA_IS_MAXAGE (lsa))
1229 return;
1230
1231 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1232 zlog_debug ("%s found", lsa->name);
1233
1234 oa = OSPF6_AREA (lsa->lsdb->data);
1235
1236 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1237 OSPF6_LSA_HEADER_END (lsa->header);
1238 if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
1239 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1240 htonl (0), &ls_prefix);
1241 else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
1242 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1243 intra_prefix_lsa->ref_id, &ls_prefix);
1244 else
1245 {
1246 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1247 zlog_debug ("Unknown reference LS-type: %#hx",
1248 ntohs (intra_prefix_lsa->ref_type));
1249 return;
1250 }
1251
1252 ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
1253 if (ls_entry == NULL)
1254 {
1255 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1256 {
1257 ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
1258 zlog_debug ("LS entry does not exist: %s", buf);
1259 }
1260 return;
1261 }
1262
1263 if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id)
1264 {
1265 /* the intra-prefix are directly connected */
1266 direct_connect = 1;
1267 }
1268
1269 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1270 start = (caddr_t) intra_prefix_lsa +
1271 sizeof (struct ospf6_intra_prefix_lsa);
1272 end = OSPF6_LSA_END (lsa->header);
1273 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1274 {
1275 op = (struct ospf6_prefix *) current;
1276 if (prefix_num == 0)
1277 break;
1278 if (end < current + OSPF6_PREFIX_SIZE (op))
1279 break;
1280
1281 /* Appendix A.4.1.1 */
1282 if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU))
1283 {
1284 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1285 {
1286 ospf6_linkstate_prefix2str ((struct prefix *)OSPF6_PREFIX_BODY(op),
1287 buf, sizeof (buf));
1288 zlog_debug ("%s: Skipping Prefix %s has NU option set",
1289 __func__, buf);
1290 }
1291 continue;
1292 }
1293
1294 route = ospf6_route_create ();
1295
1296 memset (&route->prefix, 0, sizeof (struct prefix));
1297 route->prefix.family = AF_INET6;
1298 route->prefix.prefixlen = op->prefix_length;
1299 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op);
1300
1301 route->type = OSPF6_DEST_TYPE_NETWORK;
1302 route->path.origin.type = lsa->header->type;
1303 route->path.origin.id = lsa->header->id;
1304 route->path.origin.adv_router = lsa->header->adv_router;
1305 route->path.prefix_options = op->prefix_options;
1306 route->path.area_id = oa->area_id;
1307 route->path.type = OSPF6_PATH_TYPE_INTRA;
1308 route->path.metric_type = 1;
1309 route->path.cost = ls_entry->path.cost +
1310 ntohs (op->prefix_metric);
1311
1312 if (direct_connect)
1313 {
1314 ifp = if_lookup_prefix(&route->prefix, VRF_DEFAULT);
1315 if (ifp)
1316 ospf6_route_add_nexthop (route, ifp->ifindex, NULL);
1317 }
1318 else
1319 {
1320 ospf6_route_copy_nexthops (route, ls_entry);
1321 }
1322
1323 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1324 {
1325 prefix2str (&route->prefix, buf, sizeof (buf));
1326 zlog_debug (" add %s", buf);
1327 }
1328
1329 ospf6_route_add (route, oa->route_table);
1330 prefix_num--;
1331 }
1332
1333 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1334 zlog_debug ("Trailing garbage ignored");
1335 }
1336
1337 void
1338 ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
1339 {
1340 struct ospf6_area *oa;
1341 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1342 struct prefix prefix;
1343 struct ospf6_route *route, *nroute;
1344 int prefix_num;
1345 struct ospf6_prefix *op;
1346 char *start, *current, *end;
1347 char buf[PREFIX2STR_BUFFER];
1348
1349 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1350 zlog_debug ("%s disappearing", lsa->name);
1351
1352 oa = OSPF6_AREA (lsa->lsdb->data);
1353
1354 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1355 OSPF6_LSA_HEADER_END (lsa->header);
1356
1357 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1358 start = (caddr_t) intra_prefix_lsa +
1359 sizeof (struct ospf6_intra_prefix_lsa);
1360 end = OSPF6_LSA_END (lsa->header);
1361 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1362 {
1363 op = (struct ospf6_prefix *) current;
1364 if (prefix_num == 0)
1365 break;
1366 if (end < current + OSPF6_PREFIX_SIZE (op))
1367 break;
1368 prefix_num--;
1369
1370 memset (&prefix, 0, sizeof (struct prefix));
1371 prefix.family = AF_INET6;
1372 prefix.prefixlen = op->prefix_length;
1373 ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
1374
1375 route = ospf6_route_lookup (&prefix, oa->route_table);
1376 if (route == NULL)
1377 continue;
1378
1379 for (ospf6_route_lock (route);
1380 route && ospf6_route_is_prefix (&prefix, route);
1381 route = nroute)
1382 {
1383 nroute = ospf6_route_next (route);
1384 if (route->type != OSPF6_DEST_TYPE_NETWORK)
1385 continue;
1386 if (route->path.area_id != oa->area_id)
1387 continue;
1388 if (route->path.type != OSPF6_PATH_TYPE_INTRA)
1389 continue;
1390 if (route->path.origin.type != lsa->header->type ||
1391 route->path.origin.id != lsa->header->id ||
1392 route->path.origin.adv_router != lsa->header->adv_router)
1393 continue;
1394
1395 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1396 {
1397 prefix2str (&route->prefix, buf, sizeof (buf));
1398 zlog_debug ("remove %s", buf);
1399 }
1400 ospf6_route_remove (route, oa->route_table);
1401 }
1402 if (route)
1403 ospf6_route_unlock (route);
1404 }
1405
1406 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1407 zlog_debug ("Trailing garbage ignored");
1408 }
1409
1410 void
1411 ospf6_intra_route_calculation (struct ospf6_area *oa)
1412 {
1413 struct ospf6_route *route, *nroute;
1414 u_int16_t type;
1415 struct ospf6_lsa *lsa;
1416 void (*hook_add) (struct ospf6_route *) = NULL;
1417 void (*hook_remove) (struct ospf6_route *) = NULL;
1418
1419 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1420 zlog_debug ("Re-examin intra-routes for area %s", oa->name);
1421
1422 hook_add = oa->route_table->hook_add;
1423 hook_remove = oa->route_table->hook_remove;
1424 oa->route_table->hook_add = NULL;
1425 oa->route_table->hook_remove = NULL;
1426
1427 for (route = ospf6_route_head (oa->route_table); route;
1428 route = ospf6_route_next (route))
1429 route->flag = OSPF6_ROUTE_REMOVE;
1430
1431 type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1432 for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
1433 lsa = ospf6_lsdb_type_next (type, lsa))
1434 ospf6_intra_prefix_lsa_add (lsa);
1435
1436 oa->route_table->hook_add = hook_add;
1437 oa->route_table->hook_remove = hook_remove;
1438
1439 for (route = ospf6_route_head (oa->route_table); route;
1440 route = nroute)
1441 {
1442 nroute = ospf6_route_next (route);
1443 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
1444 CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
1445 {
1446 UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
1447 UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
1448 }
1449
1450 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
1451 ospf6_route_remove (route, oa->route_table);
1452 else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
1453 CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
1454 {
1455 if (hook_add)
1456 (*hook_add) (route);
1457 route->flag = 0;
1458 }
1459 else
1460 {
1461 /* Redo the summaries as things might have changed */
1462 ospf6_abr_originate_summary (route);
1463 route->flag = 0;
1464 }
1465 }
1466
1467 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1468 zlog_debug ("Re-examin intra-routes for area %s: Done", oa->name);
1469 }
1470
1471 static void
1472 ospf6_brouter_debug_print (struct ospf6_route *brouter)
1473 {
1474 u_int32_t brouter_id;
1475 char brouter_name[16];
1476 char area_name[16];
1477 char destination[64];
1478 char installed[16], changed[16];
1479 struct timeval now, res;
1480 char id[16], adv_router[16];
1481 char capa[16], options[16];
1482
1483 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1484 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1485 inet_ntop (AF_INET, &brouter->path.area_id, area_name, sizeof (area_name));
1486 ospf6_linkstate_prefix2str (&brouter->prefix, destination,
1487 sizeof (destination));
1488
1489 monotime(&now);
1490 timersub (&now, &brouter->installed, &res);
1491 timerstring (&res, installed, sizeof (installed));
1492
1493 monotime(&now);
1494 timersub (&now, &brouter->changed, &res);
1495 timerstring (&res, changed, sizeof (changed));
1496
1497 inet_ntop (AF_INET, &brouter->path.origin.id, id, sizeof (id));
1498 inet_ntop (AF_INET, &brouter->path.origin.adv_router, adv_router,
1499 sizeof (adv_router));
1500
1501 ospf6_options_printbuf (brouter->path.options, options, sizeof (options));
1502 ospf6_capability_printbuf (brouter->path.router_bits, capa, sizeof (capa));
1503
1504 zlog_info ("Brouter: %s via area %s", brouter_name, area_name);
1505 zlog_info (" memory: prev: %p this: %p next: %p parent rnode: %p",
1506 (void *)brouter->prev, (void *)brouter, (void *)brouter->next,
1507 (void *)brouter->rnode);
1508 zlog_info (" type: %d prefix: %s installed: %s changed: %s",
1509 brouter->type, destination, installed, changed);
1510 zlog_info (" lock: %d flags: %s%s%s%s", brouter->lock,
1511 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
1512 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
1513 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
1514 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
1515 zlog_info (" path type: %s ls-origin %s id: %s adv-router %s",
1516 OSPF6_PATH_TYPE_NAME (brouter->path.type),
1517 ospf6_lstype_name (brouter->path.origin.type),
1518 id, adv_router);
1519 zlog_info (" options: %s router-bits: %s metric-type: %d metric: %d/%d",
1520 options, capa, brouter->path.metric_type,
1521 brouter->path.cost, brouter->path.u.cost_e2);
1522 }
1523
1524 void
1525 ospf6_intra_brouter_calculation (struct ospf6_area *oa)
1526 {
1527 struct ospf6_route *brouter, *nbrouter, *copy;
1528 void (*hook_add) (struct ospf6_route *) = NULL;
1529 void (*hook_remove) (struct ospf6_route *) = NULL;
1530 u_int32_t brouter_id;
1531 char brouter_name[16];
1532
1533 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1534 zlog_info ("border-router calculation for area %s", oa->name);
1535
1536 hook_add = oa->ospf6->brouter_table->hook_add;
1537 hook_remove = oa->ospf6->brouter_table->hook_remove;
1538 oa->ospf6->brouter_table->hook_add = NULL;
1539 oa->ospf6->brouter_table->hook_remove = NULL;
1540
1541 /* withdraw the previous router entries for the area */
1542 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1543 brouter = ospf6_route_next (brouter))
1544 {
1545 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1546 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1547 if (brouter->path.area_id != oa->area_id)
1548 continue;
1549 SET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
1550
1551 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1552 IS_OSPF6_DEBUG_ROUTE (MEMORY))
1553 {
1554 zlog_info ("%p: mark as removing: area %s brouter %s",
1555 (void *)brouter, oa->name, brouter_name);
1556 ospf6_brouter_debug_print (brouter);
1557 }
1558 }
1559
1560 for (brouter = ospf6_route_head (oa->spf_table); brouter;
1561 brouter = ospf6_route_next (brouter))
1562 {
1563 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1564 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1565
1566 if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
1567 continue;
1568 if (ospf6_linkstate_prefix_id (&brouter->prefix) != htonl (0))
1569 continue;
1570 if (! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_E) &&
1571 ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
1572 continue;
1573
1574 if (! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_V6) ||
1575 ! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_R))
1576 continue;
1577
1578 copy = ospf6_route_copy (brouter);
1579 copy->type = OSPF6_DEST_TYPE_ROUTER;
1580 copy->path.area_id = oa->area_id;
1581 ospf6_route_add (copy, oa->ospf6->brouter_table);
1582
1583 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1584 IS_OSPF6_DEBUG_ROUTE (MEMORY))
1585 {
1586 zlog_info ("%p: transfer: area %s brouter %s",
1587 (void *)brouter, oa->name, brouter_name);
1588 ospf6_brouter_debug_print (brouter);
1589 }
1590 }
1591
1592 oa->ospf6->brouter_table->hook_add = hook_add;
1593 oa->ospf6->brouter_table->hook_remove = hook_remove;
1594
1595 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1596 brouter = nbrouter)
1597 {
1598 nbrouter = ospf6_route_next (brouter);
1599 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1600 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1601
1602 if (brouter->path.area_id != oa->area_id)
1603 continue;
1604
1605 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
1606 continue;
1607
1608 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) &&
1609 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD))
1610 {
1611 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
1612 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
1613 }
1614
1615 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE))
1616 {
1617 if (IS_OSPF6_DEBUG_BROUTER ||
1618 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1619 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1620 zlog_info ("brouter %s disappears via area %s",
1621 brouter_name, oa->name);
1622 ospf6_route_remove (brouter, oa->ospf6->brouter_table);
1623 brouter = NULL;
1624 }
1625 else if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ||
1626 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE))
1627 {
1628 if (IS_OSPF6_DEBUG_BROUTER ||
1629 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1630 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1631 zlog_info ("brouter %s appears via area %s",
1632 brouter_name, oa->name);
1633
1634 /* newly added */
1635 if (hook_add)
1636 (*hook_add) (brouter);
1637 }
1638 else
1639 {
1640 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1641 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1642 zlog_info ("brouter %s still exists via area %s",
1643 brouter_name, oa->name);
1644 /* But re-originate summaries */
1645 ospf6_abr_originate_summary (brouter);
1646 }
1647
1648 if (brouter)
1649 {
1650 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
1651 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE);
1652 }
1653 }
1654
1655 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1656 zlog_info ("border-router calculation for area %s: done", oa->name);
1657 }
1658
1659 struct ospf6_lsa_handler router_handler =
1660 {
1661 OSPF6_LSTYPE_ROUTER,
1662 "Router",
1663 "Rtr",
1664 ospf6_router_lsa_show,
1665 ospf6_router_lsa_get_nbr_id
1666 };
1667
1668 struct ospf6_lsa_handler network_handler =
1669 {
1670 OSPF6_LSTYPE_NETWORK,
1671 "Network",
1672 "Net",
1673 ospf6_network_lsa_show,
1674 ospf6_network_lsa_get_ar_id
1675 };
1676
1677 struct ospf6_lsa_handler link_handler =
1678 {
1679 OSPF6_LSTYPE_LINK,
1680 "Link",
1681 "Lnk",
1682 ospf6_link_lsa_show,
1683 ospf6_link_lsa_get_prefix_str
1684 };
1685
1686 struct ospf6_lsa_handler intra_prefix_handler =
1687 {
1688 OSPF6_LSTYPE_INTRA_PREFIX,
1689 "Intra-Prefix",
1690 "INP",
1691 ospf6_intra_prefix_lsa_show,
1692 ospf6_intra_prefix_lsa_get_prefix_str
1693 };
1694
1695 void
1696 ospf6_intra_init (void)
1697 {
1698 ospf6_install_lsa_handler (&router_handler);
1699 ospf6_install_lsa_handler (&network_handler);
1700 ospf6_install_lsa_handler (&link_handler);
1701 ospf6_install_lsa_handler (&intra_prefix_handler);
1702 }
1703
1704 DEFUN (debug_ospf6_brouter,
1705 debug_ospf6_brouter_cmd,
1706 "debug ospf6 border-routers",
1707 DEBUG_STR
1708 OSPF6_STR
1709 "Debug border router\n"
1710 )
1711 {
1712 OSPF6_DEBUG_BROUTER_ON ();
1713 return CMD_SUCCESS;
1714 }
1715
1716 DEFUN (no_debug_ospf6_brouter,
1717 no_debug_ospf6_brouter_cmd,
1718 "no debug ospf6 border-routers",
1719 NO_STR
1720 DEBUG_STR
1721 OSPF6_STR
1722 "Debug border router\n"
1723 )
1724 {
1725 OSPF6_DEBUG_BROUTER_OFF ();
1726 return CMD_SUCCESS;
1727 }
1728
1729 DEFUN (debug_ospf6_brouter_router,
1730 debug_ospf6_brouter_router_cmd,
1731 "debug ospf6 border-routers router-id A.B.C.D",
1732 DEBUG_STR
1733 OSPF6_STR
1734 "Debug border router\n"
1735 "Debug specific border router\n"
1736 "Specify border-router's router-id\n"
1737 )
1738 {
1739 int idx_ipv4 = 4;
1740 u_int32_t router_id;
1741 inet_pton (AF_INET, argv[idx_ipv4]->arg, &router_id);
1742 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON (router_id);
1743 return CMD_SUCCESS;
1744 }
1745
1746 DEFUN (no_debug_ospf6_brouter_router,
1747 no_debug_ospf6_brouter_router_cmd,
1748 "no debug ospf6 border-routers router-id",
1749 NO_STR
1750 DEBUG_STR
1751 OSPF6_STR
1752 "Debug border router\n"
1753 "Debug specific border router\n"
1754 )
1755 {
1756 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF ();
1757 return CMD_SUCCESS;
1758 }
1759
1760 DEFUN (debug_ospf6_brouter_area,
1761 debug_ospf6_brouter_area_cmd,
1762 "debug ospf6 border-routers area-id A.B.C.D",
1763 DEBUG_STR
1764 OSPF6_STR
1765 "Debug border router\n"
1766 "Debug border routers in specific Area\n"
1767 "Specify Area-ID\n"
1768 )
1769 {
1770 int idx_ipv4 = 4;
1771 u_int32_t area_id;
1772 inet_pton (AF_INET, argv[idx_ipv4]->arg, &area_id);
1773 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON (area_id);
1774 return CMD_SUCCESS;
1775 }
1776
1777 DEFUN (no_debug_ospf6_brouter_area,
1778 no_debug_ospf6_brouter_area_cmd,
1779 "no debug ospf6 border-routers area-id",
1780 NO_STR
1781 DEBUG_STR
1782 OSPF6_STR
1783 "Debug border router\n"
1784 "Debug border routers in specific Area\n"
1785 )
1786 {
1787 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF ();
1788 return CMD_SUCCESS;
1789 }
1790
1791 int
1792 config_write_ospf6_debug_brouter (struct vty *vty)
1793 {
1794 char buf[16];
1795 if (IS_OSPF6_DEBUG_BROUTER)
1796 vty_out (vty, "debug ospf6 border-routers%s", VNL);
1797 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER)
1798 {
1799 inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
1800 buf, sizeof (buf));
1801 vty_out (vty, "debug ospf6 border-routers router-id %s%s", buf, VNL);
1802 }
1803 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA)
1804 {
1805 inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
1806 buf, sizeof (buf));
1807 vty_out (vty, "debug ospf6 border-routers area-id %s%s", buf, VNL);
1808 }
1809 return 0;
1810 }
1811
1812 void
1813 install_element_ospf6_debug_brouter (void)
1814 {
1815 install_element (ENABLE_NODE, &debug_ospf6_brouter_cmd);
1816 install_element (ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
1817 install_element (ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
1818 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
1819 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
1820 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
1821 install_element (CONFIG_NODE, &debug_ospf6_brouter_cmd);
1822 install_element (CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
1823 install_element (CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
1824 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
1825 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
1826 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);
1827 }
1828
1829