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