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