]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_intra.c
ospf6d: Support for nssa in ospfv3
[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 uint32_t conf_debug_ospf6_brouter_specific_router_id;
53 uint32_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 + sizeof(struct ospf6_router_lsdesc)
80 <= end) {
81 if (buf && (buflen > INET_ADDRSTRLEN * 2)) {
82 inet_ntop(AF_INET,
83 &lsdesc->neighbor_interface_id, buf1,
84 sizeof(buf1));
85 inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
86 buf2, sizeof(buf2));
87 snprintf(buf, buflen, "%s/%s", buf2, buf1);
88
89 return buf;
90 }
91 }
92 }
93
94 return NULL;
95 }
96
97 static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
98 json_object *json_obj, bool use_json)
99 {
100 char *start, *end, *current;
101 char buf[32], name[32], bits[16], options[32];
102 struct ospf6_router_lsa *router_lsa;
103 struct ospf6_router_lsdesc *lsdesc;
104 json_object *json_arr;
105 json_object *json_loop;
106
107 router_lsa =
108 (struct ospf6_router_lsa *)((char *)lsa->header
109 + sizeof(struct ospf6_lsa_header));
110
111 ospf6_capability_printbuf(router_lsa->bits, bits, sizeof(bits));
112 ospf6_options_printbuf(router_lsa->options, options, sizeof(options));
113 if (use_json) {
114 json_object_string_add(json_obj, "bits", bits);
115 json_object_string_add(json_obj, "options", options);
116 json_arr = json_object_new_array();
117 } else
118 vty_out(vty, " Bits: %s Options: %s\n", bits, options);
119
120 start = (char *)router_lsa + sizeof(struct ospf6_router_lsa);
121 end = (char *)lsa->header + ntohs(lsa->header->length);
122 for (current = start;
123 current + sizeof(struct ospf6_router_lsdesc) <= end;
124 current += sizeof(struct ospf6_router_lsdesc)) {
125 lsdesc = (struct ospf6_router_lsdesc *)current;
126
127 if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
128 snprintf(name, sizeof(name), "Point-To-Point");
129 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
130 snprintf(name, sizeof(name), "Transit-Network");
131 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
132 snprintf(name, sizeof(name), "Stub-Network");
133 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
134 snprintf(name, sizeof(name), "Virtual-Link");
135 else
136 snprintf(name, sizeof(name), "Unknown (%#x)",
137 lsdesc->type);
138
139 if (use_json) {
140 json_loop = json_object_new_object();
141 json_object_string_add(json_loop, "type", name);
142 json_object_int_add(json_loop, "metric",
143 ntohs(lsdesc->metric));
144 json_object_string_add(json_loop, "interfaceId",
145 inet_ntop(AF_INET,
146 &lsdesc->interface_id,
147 buf, sizeof(buf)));
148 json_object_string_add(
149 json_loop, "neighborInterfaceId",
150 inet_ntop(AF_INET,
151 &lsdesc->neighbor_interface_id, buf,
152 sizeof(buf)));
153 json_object_string_add(
154 json_loop, "neighborRouterId",
155 inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
156 buf, sizeof(buf)));
157 json_object_array_add(json_arr, json_loop);
158 } else {
159 vty_out(vty, " Type: %s Metric: %d\n", name,
160 ntohs(lsdesc->metric));
161 vty_out(vty, " Interface ID: %s\n",
162 inet_ntop(AF_INET, &lsdesc->interface_id, buf,
163 sizeof(buf)));
164 vty_out(vty, " Neighbor Interface ID: %s\n",
165 inet_ntop(AF_INET,
166 &lsdesc->neighbor_interface_id, buf,
167 sizeof(buf)));
168 vty_out(vty, " Neighbor Router ID: %s\n",
169 inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
170 buf, sizeof(buf)));
171 }
172 }
173 if (use_json)
174 json_object_object_add(json_obj, "lsaDescription", json_arr);
175
176 return 0;
177 }
178
179 static void ospf6_router_lsa_options_set(struct ospf6_area *oa,
180 struct ospf6_router_lsa *router_lsa)
181 {
182 OSPF6_OPT_CLEAR_ALL(router_lsa->options);
183 memcpy(router_lsa->options, oa->options, 3);
184
185 if (ospf6_is_router_abr(oa->ospf6))
186 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B);
187 else
188 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B);
189
190 if (!IS_AREA_STUB(oa) && ospf6_asbr_is_asbr(oa->ospf6)) {
191 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E);
192 } else {
193 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E);
194 }
195
196 /* If the router is ASBR and the area-type is NSSA set the
197 * translate bit in router LSA.
198 */
199 if (IS_AREA_NSSA(oa)
200 && (ospf6_asbr_is_asbr(oa->ospf6) || IS_OSPF6_ABR(oa->ospf6))) {
201 if (oa->NSSATranslatorRole == OSPF6_NSSA_ROLE_ALWAYS)
202 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_NT);
203 } else {
204 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_NT);
205 }
206
207 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_V);
208 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_W);
209 }
210
211 int ospf6_router_is_stub_router(struct ospf6_lsa *lsa)
212 {
213 struct ospf6_router_lsa *rtr_lsa;
214
215 if (lsa != NULL && OSPF6_LSA_IS_TYPE(ROUTER, lsa)) {
216 rtr_lsa = (struct ospf6_router_lsa
217 *)((caddr_t)lsa->header
218 + sizeof(struct ospf6_lsa_header));
219
220 if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_R)) {
221 return OSPF6_IS_STUB_ROUTER;
222 } else if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_V6)) {
223 return OSPF6_IS_STUB_ROUTER_V6;
224 }
225 }
226
227 return OSPF6_NOT_STUB_ROUTER;
228 }
229
230 int ospf6_router_lsa_originate(struct thread *thread)
231 {
232 struct ospf6_area *oa;
233
234 char buffer[OSPF6_MAX_LSASIZE];
235 struct ospf6_lsa_header *lsa_header;
236 struct ospf6_lsa *lsa;
237
238 uint32_t link_state_id = 0;
239 struct listnode *node, *nnode;
240 struct listnode *j;
241 struct ospf6_interface *oi;
242 struct ospf6_neighbor *on, *drouter = NULL;
243 struct ospf6_router_lsa *router_lsa;
244 struct ospf6_router_lsdesc *lsdesc;
245 uint16_t type;
246 uint32_t router;
247 int count;
248
249 oa = (struct ospf6_area *)THREAD_ARG(thread);
250 oa->thread_router_lsa = NULL;
251
252 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
253 zlog_debug("Originate Router-LSA for Area %s", oa->name);
254
255 memset(buffer, 0, sizeof(buffer));
256 lsa_header = (struct ospf6_lsa_header *)buffer;
257 router_lsa =
258 (struct ospf6_router_lsa *)((caddr_t)lsa_header
259 + sizeof(struct ospf6_lsa_header));
260
261 ospf6_router_lsa_options_set(oa, router_lsa);
262
263 /* describe links for each interfaces */
264 lsdesc = (struct ospf6_router_lsdesc
265 *)((caddr_t)router_lsa
266 + sizeof(struct ospf6_router_lsa));
267
268 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
269 /* Interfaces in state Down or Loopback are not described */
270 if (oi->state == OSPF6_INTERFACE_DOWN
271 || oi->state == OSPF6_INTERFACE_LOOPBACK)
272 continue;
273
274 /* Nor are interfaces without any full adjacencies described */
275 count = 0;
276 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on))
277 if (on->state == OSPF6_NEIGHBOR_FULL)
278 count++;
279
280 if (count == 0)
281 continue;
282
283 /* Multiple Router-LSA instance according to size limit setting
284 */
285 if ((oa->router_lsa_size_limit != 0)
286 && ((size_t)((char *)lsdesc - buffer)
287 + sizeof(struct ospf6_router_lsdesc)
288 > oa->router_lsa_size_limit)) {
289 if ((caddr_t)lsdesc
290 == (caddr_t)router_lsa
291 + sizeof(struct ospf6_router_lsa)) {
292 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
293 zlog_debug(
294 "Size limit setting for Router-LSA too short");
295 return 0;
296 }
297
298 /* Fill LSA Header */
299 lsa_header->age = 0;
300 lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
301 lsa_header->id = htonl(link_state_id);
302 lsa_header->adv_router = oa->ospf6->router_id;
303 lsa_header->seqnum = ospf6_new_ls_seqnum(
304 lsa_header->type, lsa_header->id,
305 lsa_header->adv_router, oa->lsdb);
306 lsa_header->length =
307 htons((caddr_t)lsdesc - (caddr_t)buffer);
308
309 /* LSA checksum */
310 ospf6_lsa_checksum(lsa_header);
311
312 /* create LSA */
313 lsa = ospf6_lsa_create(lsa_header);
314
315 /* Originate */
316 ospf6_lsa_originate_area(lsa, oa);
317
318 /* Reset Buffer to fill next Router LSA */
319 memset(buffer, 0, sizeof(buffer));
320 lsa_header = (struct ospf6_lsa_header *)buffer;
321 router_lsa =
322 (struct ospf6_router_lsa
323 *)((caddr_t)lsa_header
324 + sizeof(struct ospf6_lsa_header));
325
326 ospf6_router_lsa_options_set(oa, router_lsa);
327
328 /* describe links for each interfaces */
329 lsdesc = (struct ospf6_router_lsdesc
330 *)((caddr_t)router_lsa
331 + sizeof(struct ospf6_router_lsa));
332
333 link_state_id++;
334 }
335
336 /* Point-to-Point interfaces */
337 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
338 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) {
339 if (on->state != OSPF6_NEIGHBOR_FULL)
340 continue;
341
342 lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
343 lsdesc->metric = htons(oi->cost);
344 lsdesc->interface_id =
345 htonl(oi->interface->ifindex);
346 lsdesc->neighbor_interface_id =
347 htonl(on->ifindex);
348 lsdesc->neighbor_router_id = on->router_id;
349
350 lsdesc++;
351 }
352 }
353
354 /* Broadcast and NBMA interfaces */
355 else if (oi->type == OSPF_IFTYPE_BROADCAST) {
356 /* If this router is not DR,
357 and If this router not fully adjacent with DR,
358 this interface is not transit yet: ignore. */
359 if (oi->state != OSPF6_INTERFACE_DR) {
360 drouter =
361 ospf6_neighbor_lookup(oi->drouter, oi);
362 if (drouter == NULL
363 || drouter->state != OSPF6_NEIGHBOR_FULL)
364 continue;
365 }
366
367 lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
368 lsdesc->metric = htons(oi->cost);
369 lsdesc->interface_id = htonl(oi->interface->ifindex);
370 if (oi->state != OSPF6_INTERFACE_DR) {
371 lsdesc->neighbor_interface_id =
372 htonl(drouter->ifindex);
373 lsdesc->neighbor_router_id = drouter->router_id;
374 } else {
375 lsdesc->neighbor_interface_id =
376 htonl(oi->interface->ifindex);
377 lsdesc->neighbor_router_id =
378 oi->area->ospf6->router_id;
379 }
380
381 lsdesc++;
382 } else {
383 assert(0); /* Unknown interface type */
384 }
385
386 /* Virtual links */
387 /* xxx */
388 /* Point-to-Multipoint interfaces */
389 /* xxx */
390 }
391
392 /* Fill LSA Header */
393 lsa_header->age = 0;
394 lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
395 lsa_header->id = htonl(link_state_id);
396 lsa_header->adv_router = oa->ospf6->router_id;
397 lsa_header->seqnum =
398 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
399 lsa_header->adv_router, oa->lsdb);
400 lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer);
401
402 /* LSA checksum */
403 ospf6_lsa_checksum(lsa_header);
404
405 /* create LSA */
406 lsa = ospf6_lsa_create(lsa_header);
407
408 /* Originate */
409 ospf6_lsa_originate_area(lsa, oa);
410
411 link_state_id++;
412
413 /* Do premature-aging of rest, undesired Router-LSAs */
414 type = ntohs(OSPF6_LSTYPE_ROUTER);
415 router = oa->ospf6->router_id;
416 count = 0;
417 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router, lsa)) {
418 if (ntohl(lsa->header->id) < link_state_id)
419 continue;
420 ospf6_lsa_purge(lsa);
421 count++;
422 }
423
424 /*
425 * Waiting till the LSA is actually removed from the database to trigger
426 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
427 * interfaces associated with an area are gone, triggering an SPF right
428 * away
429 * helps convergence with inter-area routes.
430 */
431 if (count && !link_state_id)
432 ospf6_spf_schedule(oa->ospf6,
433 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED);
434
435 return 0;
436 }
437
438 /*******************************/
439 /* RFC2740 3.4.3.2 Network-LSA */
440 /*******************************/
441
442 static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa *lsa, char *buf,
443 int buflen, int pos)
444 {
445 char *start, *end, *current;
446 struct ospf6_network_lsa *network_lsa;
447 struct ospf6_network_lsdesc *lsdesc;
448
449 if (lsa) {
450 network_lsa = (struct ospf6_network_lsa
451 *)((caddr_t)lsa->header
452 + sizeof(struct ospf6_lsa_header));
453
454 start = (char *)network_lsa + sizeof(struct ospf6_network_lsa);
455 end = (char *)lsa->header + ntohs(lsa->header->length);
456 current = start + pos * (sizeof(struct ospf6_network_lsdesc));
457
458 if ((current + sizeof(struct ospf6_network_lsdesc)) <= end) {
459 lsdesc = (struct ospf6_network_lsdesc *)current;
460 if (buf) {
461 inet_ntop(AF_INET, &lsdesc->router_id, buf,
462 buflen);
463 return buf;
464 }
465 }
466 }
467
468 return NULL;
469 }
470
471 static int ospf6_network_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
472 json_object *json_obj, bool use_json)
473 {
474 char *start, *end, *current;
475 struct ospf6_network_lsa *network_lsa;
476 struct ospf6_network_lsdesc *lsdesc;
477 char buf[128], options[32];
478 json_object *json_arr;
479
480 network_lsa =
481 (struct ospf6_network_lsa *)((caddr_t)lsa->header
482 + sizeof(struct ospf6_lsa_header));
483
484 ospf6_options_printbuf(network_lsa->options, options, sizeof(options));
485 if (use_json)
486 json_object_string_add(json_obj, "options", options);
487 else
488 vty_out(vty, " Options: %s\n", options);
489
490 start = (char *)network_lsa + sizeof(struct ospf6_network_lsa);
491 end = (char *)lsa->header + ntohs(lsa->header->length);
492 if (use_json)
493 json_arr = json_object_new_array();
494
495 for (current = start;
496 current + sizeof(struct ospf6_network_lsdesc) <= end;
497 current += sizeof(struct ospf6_network_lsdesc)) {
498 lsdesc = (struct ospf6_network_lsdesc *)current;
499 inet_ntop(AF_INET, &lsdesc->router_id, buf, sizeof(buf));
500 if (use_json)
501 json_object_array_add(json_arr,
502 json_object_new_string(buf));
503 else
504 vty_out(vty, " Attached Router: %s\n", buf);
505 }
506 if (use_json)
507 json_object_object_add(json_obj, "attachedRouter", json_arr);
508
509 return 0;
510 }
511
512 int ospf6_network_lsa_originate(struct thread *thread)
513 {
514 struct ospf6_interface *oi;
515
516 char buffer[OSPF6_MAX_LSASIZE];
517 struct ospf6_lsa_header *lsa_header;
518
519 int count;
520 struct ospf6_lsa *old, *lsa;
521 struct ospf6_network_lsa *network_lsa;
522 struct ospf6_network_lsdesc *lsdesc;
523 struct ospf6_neighbor *on;
524 struct ospf6_link_lsa *link_lsa;
525 struct listnode *i;
526 uint16_t type;
527
528 oi = (struct ospf6_interface *)THREAD_ARG(thread);
529 oi->thread_network_lsa = NULL;
530
531 /* The interface must be enabled until here. A Network-LSA of a
532 disabled interface (but was once enabled) should be flushed
533 by ospf6_lsa_refresh (), and does not come here. */
534 assert(oi->area);
535
536 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK),
537 htonl(oi->interface->ifindex),
538 oi->area->ospf6->router_id, oi->area->lsdb);
539
540 /* Do not originate Network-LSA if not DR */
541 if (oi->state != OSPF6_INTERFACE_DR) {
542 if (old) {
543 ospf6_lsa_purge(old);
544 /*
545 * Waiting till the LSA is actually removed from the
546 * database to
547 * trigger SPF delays network convergence.
548 */
549 ospf6_spf_schedule(
550 oi->area->ospf6,
551 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED);
552 }
553 return 0;
554 }
555
556 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK))
557 zlog_debug("Originate Network-LSA for Interface %s",
558 oi->interface->name);
559
560 /* If none of neighbor is adjacent to us */
561 count = 0;
562
563 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on))
564 if (on->state == OSPF6_NEIGHBOR_FULL)
565 count++;
566
567 if (count == 0) {
568 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK))
569 zlog_debug("Interface stub, ignore");
570 if (old)
571 ospf6_lsa_purge(old);
572 return 0;
573 }
574
575 /* prepare buffer */
576 memset(buffer, 0, sizeof(buffer));
577 lsa_header = (struct ospf6_lsa_header *)buffer;
578 network_lsa =
579 (struct ospf6_network_lsa *)((caddr_t)lsa_header
580 + sizeof(struct ospf6_lsa_header));
581
582 /* Collect the interface's Link-LSAs to describe
583 network's optional capabilities */
584 type = htons(OSPF6_LSTYPE_LINK);
585 for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
586 link_lsa = (struct ospf6_link_lsa
587 *)((caddr_t)lsa->header
588 + sizeof(struct ospf6_lsa_header));
589 network_lsa->options[0] |= link_lsa->options[0];
590 network_lsa->options[1] |= link_lsa->options[1];
591 network_lsa->options[2] |= link_lsa->options[2];
592 }
593
594 lsdesc = (struct ospf6_network_lsdesc
595 *)((caddr_t)network_lsa
596 + sizeof(struct ospf6_network_lsa));
597
598 /* set Link Description to the router itself */
599 lsdesc->router_id = oi->area->ospf6->router_id;
600 lsdesc++;
601
602 /* Walk through the neighbors */
603 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on)) {
604 if (on->state != OSPF6_NEIGHBOR_FULL)
605 continue;
606
607 /* set this neighbor's Router-ID to LSA */
608 lsdesc->router_id = on->router_id;
609 lsdesc++;
610 }
611
612 /* Fill LSA Header */
613 lsa_header->age = 0;
614 lsa_header->type = htons(OSPF6_LSTYPE_NETWORK);
615 lsa_header->id = htonl(oi->interface->ifindex);
616 lsa_header->adv_router = oi->area->ospf6->router_id;
617 lsa_header->seqnum =
618 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
619 lsa_header->adv_router, oi->area->lsdb);
620 lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer);
621
622 /* LSA checksum */
623 ospf6_lsa_checksum(lsa_header);
624
625 /* create LSA */
626 lsa = ospf6_lsa_create(lsa_header);
627
628 /* Originate */
629 ospf6_lsa_originate_area(lsa, oi->area);
630
631 return 0;
632 }
633
634
635 /****************************/
636 /* RFC2740 3.4.3.6 Link-LSA */
637 /****************************/
638
639 static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf,
640 int buflen, int pos)
641 {
642 char *start, *end, *current;
643 struct ospf6_link_lsa *link_lsa;
644 struct in6_addr in6;
645 struct ospf6_prefix *prefix;
646 int cnt = 0, prefixnum;
647
648 if (lsa) {
649 link_lsa = (struct ospf6_link_lsa
650 *)((caddr_t)lsa->header
651 + sizeof(struct ospf6_lsa_header));
652
653 if (pos == 0) {
654 inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf,
655 buflen);
656 return (buf);
657 }
658
659 prefixnum = ntohl(link_lsa->prefix_num);
660 if (pos > prefixnum)
661 return NULL;
662
663 start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
664 end = (char *)lsa->header + ntohs(lsa->header->length);
665 current = start;
666
667 while (current + sizeof(struct ospf6_prefix) <= end) {
668 prefix = (struct ospf6_prefix *)current;
669 if (prefix->prefix_length == 0
670 || current + OSPF6_PREFIX_SIZE(prefix) > end) {
671 return NULL;
672 }
673
674 if (cnt < (pos - 1)) {
675 current += OSPF6_PREFIX_SIZE(prefix);
676 cnt++;
677 } else {
678 memset(&in6, 0, sizeof(in6));
679 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
680 OSPF6_PREFIX_SPACE(
681 prefix->prefix_length));
682 inet_ntop(AF_INET6, &in6, buf, buflen);
683 return (buf);
684 }
685 }
686 }
687 return NULL;
688 }
689
690 static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
691 json_object *json_obj, bool use_json)
692 {
693 char *start, *end, *current;
694 struct ospf6_link_lsa *link_lsa;
695 int prefixnum;
696 char buf[128], options[32];
697 struct ospf6_prefix *prefix;
698 struct in6_addr in6;
699 json_object *json_loop;
700 json_object *json_arr = NULL;
701 char prefix_string[133];
702
703 link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa->header
704 + sizeof(struct ospf6_lsa_header));
705
706 ospf6_options_printbuf(link_lsa->options, options, sizeof(options));
707 inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf, sizeof(buf));
708 prefixnum = ntohl(link_lsa->prefix_num);
709
710 if (use_json) {
711 json_arr = json_object_new_array();
712 json_object_int_add(json_obj, "priority", link_lsa->priority);
713 json_object_string_add(json_obj, "options", options);
714 json_object_string_add(json_obj, "linkLocalAddress", buf);
715 json_object_int_add(json_obj, "numberOfPrefix", prefixnum);
716 } else {
717 vty_out(vty, " Priority: %d Options: %s\n",
718 link_lsa->priority, options);
719 vty_out(vty, " LinkLocal Address: %s\n", buf);
720 vty_out(vty, " Number of Prefix: %d\n", prefixnum);
721 }
722
723 start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
724 end = (char *)lsa->header + ntohs(lsa->header->length);
725 for (current = start; current < end;
726 current += OSPF6_PREFIX_SIZE(prefix)) {
727 prefix = (struct ospf6_prefix *)current;
728 if (prefix->prefix_length == 0
729 || current + OSPF6_PREFIX_SIZE(prefix) > end)
730 break;
731
732 ospf6_prefix_options_printbuf(prefix->prefix_options, buf,
733 sizeof(buf));
734 if (use_json) {
735 json_loop = json_object_new_object();
736 json_object_string_add(json_loop, "prefixOption", buf);
737 } else
738 vty_out(vty, " Prefix Options: %s\n", buf);
739
740 memset(&in6, 0, sizeof(in6));
741 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
742 OSPF6_PREFIX_SPACE(prefix->prefix_length));
743 inet_ntop(AF_INET6, &in6, buf, sizeof(buf));
744 if (use_json) {
745 snprintf(prefix_string, sizeof(prefix_string), "%s/%d",
746 buf, prefix->prefix_length);
747 json_object_string_add(json_loop, "prefix",
748 prefix_string);
749 json_object_array_add(json_arr, json_loop);
750 } else
751 vty_out(vty, " Prefix: %s/%d\n", buf,
752 prefix->prefix_length);
753 }
754 if (use_json)
755 json_object_object_add(json_obj, "prefix", json_arr);
756
757 return 0;
758 }
759
760 int ospf6_link_lsa_originate(struct thread *thread)
761 {
762 struct ospf6_interface *oi;
763
764 char buffer[OSPF6_MAX_LSASIZE];
765 struct ospf6_lsa_header *lsa_header;
766 struct ospf6_lsa *old, *lsa;
767
768 struct ospf6_link_lsa *link_lsa;
769 struct ospf6_route *route;
770 struct ospf6_prefix *op;
771 int count, max_addr_count;
772
773 oi = (struct ospf6_interface *)THREAD_ARG(thread);
774 oi->thread_link_lsa = NULL;
775
776 assert(oi->area);
777
778 /* find previous LSA */
779 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK),
780 htonl(oi->interface->ifindex),
781 oi->area->ospf6->router_id, oi->lsdb);
782
783 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
784 if (old)
785 ospf6_lsa_purge(old);
786 return 0;
787 }
788
789 if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
790 zlog_debug("Originate Link-LSA for Interface %s",
791 oi->interface->name);
792
793 /* can't make Link-LSA if linklocal address not set */
794 if (oi->linklocal_addr == NULL) {
795 if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
796 zlog_debug(
797 "No Linklocal address on %s, defer originating",
798 oi->interface->name);
799 if (old)
800 ospf6_lsa_purge(old);
801 return 0;
802 }
803
804 /* prepare buffer */
805 memset(buffer, 0, sizeof(buffer));
806 lsa_header = (struct ospf6_lsa_header *)buffer;
807 link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa_header
808 + sizeof(struct ospf6_lsa_header));
809
810 /* Fill Link-LSA */
811 link_lsa->priority = oi->priority;
812 memcpy(link_lsa->options, oi->area->options, 3);
813 memcpy(&link_lsa->linklocal_addr, oi->linklocal_addr,
814 sizeof(struct in6_addr));
815
816 op = (struct ospf6_prefix *)((caddr_t)link_lsa
817 + sizeof(struct ospf6_link_lsa));
818
819 /* connected prefix to advertise, number of interface addresses
820 * supported is based on MTU size of OSPFv3 packets
821 */
822 if (oi->ifmtu >= OSPF6_JUMBO_MTU)
823 max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO;
824 else
825 max_addr_count = OSPF6_MAX_IF_ADDRS;
826 for (route = ospf6_route_head(oi->route_connected), count = 0;
827 route && count < max_addr_count;
828 route = ospf6_route_next(route), count++) {
829 op->prefix_length = route->prefix.prefixlen;
830 op->prefix_options = route->path.prefix_options;
831 op->prefix_metric = htons(0);
832 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
833 OSPF6_PREFIX_SPACE(op->prefix_length));
834 op = OSPF6_PREFIX_NEXT(op);
835 }
836
837 link_lsa->prefix_num = htonl(count);
838
839 /* Fill LSA Header */
840 lsa_header->age = 0;
841 lsa_header->type = htons(OSPF6_LSTYPE_LINK);
842 lsa_header->id = htonl(oi->interface->ifindex);
843 lsa_header->adv_router = oi->area->ospf6->router_id;
844 lsa_header->seqnum =
845 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
846 lsa_header->adv_router, oi->lsdb);
847 lsa_header->length = htons((caddr_t)op - (caddr_t)buffer);
848
849 /* LSA checksum */
850 ospf6_lsa_checksum(lsa_header);
851
852 /* create LSA */
853 lsa = ospf6_lsa_create(lsa_header);
854
855 /* Originate */
856 ospf6_lsa_originate_interface(lsa, oi);
857
858 return 0;
859 }
860
861
862 /*****************************************/
863 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
864 /*****************************************/
865 static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
866 char *buf, int buflen,
867 int pos)
868 {
869 char *start, *end, *current;
870 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
871 struct in6_addr in6;
872 int prefixnum, cnt = 0;
873 struct ospf6_prefix *prefix;
874 char tbuf[16];
875
876 if (lsa) {
877 intra_prefix_lsa =
878 (struct ospf6_intra_prefix_lsa
879 *)((caddr_t)lsa->header
880 + sizeof(struct ospf6_lsa_header));
881
882 prefixnum = ntohs(intra_prefix_lsa->prefix_num);
883 if ((pos + 1) > prefixnum)
884 return NULL;
885
886 start = (char *)intra_prefix_lsa
887 + sizeof(struct ospf6_intra_prefix_lsa);
888 end = (char *)lsa->header + ntohs(lsa->header->length);
889 current = start;
890
891 while (current + sizeof(struct ospf6_prefix) <= end) {
892 prefix = (struct ospf6_prefix *)current;
893 if (prefix->prefix_length == 0
894 || current + OSPF6_PREFIX_SIZE(prefix) > end) {
895 return NULL;
896 }
897
898 if (cnt < pos) {
899 current += OSPF6_PREFIX_SIZE(prefix);
900 cnt++;
901 } else {
902 memset(&in6, 0, sizeof(in6));
903 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
904 OSPF6_PREFIX_SPACE(
905 prefix->prefix_length));
906 inet_ntop(AF_INET6, &in6, buf, buflen);
907 snprintf(tbuf, sizeof(tbuf), "/%d",
908 prefix->prefix_length);
909 strlcat(buf, tbuf, buflen);
910 return (buf);
911 }
912 }
913 }
914 return NULL;
915 }
916
917 static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
918 json_object *json_obj, bool use_json)
919 {
920 char *start, *end, *current;
921 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
922 int prefixnum;
923 char buf[128];
924 struct ospf6_prefix *prefix;
925 char id[16], adv_router[16];
926 struct in6_addr in6;
927 json_object *json_loop;
928 json_object *json_arr = NULL;
929 char prefix_string[133];
930
931 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
932 *)((caddr_t)lsa->header
933 + sizeof(struct ospf6_lsa_header));
934
935 prefixnum = ntohs(intra_prefix_lsa->prefix_num);
936
937 if (use_json) {
938 json_arr = json_object_new_array();
939 json_object_int_add(json_obj, "numberOfPrefix", prefixnum);
940 } else
941 vty_out(vty, " Number of Prefix: %d\n", prefixnum);
942
943 inet_ntop(AF_INET, &intra_prefix_lsa->ref_id, id, sizeof(id));
944 inet_ntop(AF_INET, &intra_prefix_lsa->ref_adv_router, adv_router,
945 sizeof(adv_router));
946 if (use_json) {
947 json_object_string_add(
948 json_obj, "reference",
949 ospf6_lstype_name(intra_prefix_lsa->ref_type));
950 json_object_string_add(json_obj, "referenceId", id);
951 json_object_string_add(json_obj, "referenceAdv", adv_router);
952 } else
953 vty_out(vty, " Reference: %s Id: %s Adv: %s\n",
954 ospf6_lstype_name(intra_prefix_lsa->ref_type), id,
955 adv_router);
956
957 start = (char *)intra_prefix_lsa
958 + sizeof(struct ospf6_intra_prefix_lsa);
959 end = (char *)lsa->header + ntohs(lsa->header->length);
960 for (current = start; current < end;
961 current += OSPF6_PREFIX_SIZE(prefix)) {
962 prefix = (struct ospf6_prefix *)current;
963 if (prefix->prefix_length == 0
964 || current + OSPF6_PREFIX_SIZE(prefix) > end)
965 break;
966
967 ospf6_prefix_options_printbuf(prefix->prefix_options, buf,
968 sizeof(buf));
969 if (use_json) {
970 json_loop = json_object_new_object();
971 json_object_string_add(json_loop, "prefixOption", buf);
972 } else
973 vty_out(vty, " Prefix Options: %s\n", buf);
974
975 memset(&in6, 0, sizeof(in6));
976 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
977 OSPF6_PREFIX_SPACE(prefix->prefix_length));
978 inet_ntop(AF_INET6, &in6, buf, sizeof(buf));
979 if (use_json) {
980 snprintf(prefix_string, sizeof(prefix_string), "%s/%d",
981 buf, prefix->prefix_length);
982 json_object_string_add(json_loop, "prefix",
983 prefix_string);
984 json_object_int_add(json_loop, "metric",
985 ntohs(prefix->prefix_metric));
986 json_object_array_add(json_arr, json_loop);
987 } else {
988 vty_out(vty, " Prefix: %s/%d\n", buf,
989 prefix->prefix_length);
990 vty_out(vty, " Metric: %d\n",
991 ntohs(prefix->prefix_metric));
992 }
993 }
994 if (use_json)
995 json_object_object_add(json_obj, "prefix", json_arr);
996
997 return 0;
998 }
999
1000 int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
1001 {
1002 struct ospf6_area *oa;
1003
1004 char buffer[OSPF6_MAX_LSASIZE];
1005 struct ospf6_lsa_header *lsa_header;
1006 struct ospf6_lsa *old, *lsa, *old_next = NULL;
1007
1008 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1009 struct ospf6_interface *oi;
1010 struct ospf6_neighbor *on;
1011 struct ospf6_route *route;
1012 struct ospf6_prefix *op;
1013 struct listnode *i, *j;
1014 int full_count = 0;
1015 unsigned short prefix_num = 0;
1016 struct ospf6_route_table *route_advertise;
1017 int ls_id = 0;
1018 int count, max_addr_count;
1019
1020 oa = (struct ospf6_area *)THREAD_ARG(thread);
1021 oa->thread_intra_prefix_lsa = NULL;
1022
1023 /* find previous LSA */
1024 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX), htonl(0),
1025 oa->ospf6->router_id, oa->lsdb);
1026
1027 if (!IS_AREA_ENABLED(oa)) {
1028 if (old) {
1029 ospf6_lsa_purge(old);
1030 /* find previous LSA */
1031 old_next = ospf6_lsdb_lookup(
1032 htons(OSPF6_LSTYPE_INTRA_PREFIX),
1033 htonl(++ls_id), oa->ospf6->router_id, oa->lsdb);
1034
1035 while (old_next) {
1036 ospf6_lsa_purge(old_next);
1037 old_next = ospf6_lsdb_lookup(
1038 htons(OSPF6_LSTYPE_INTRA_PREFIX),
1039 htonl(++ls_id), oa->ospf6->router_id,
1040 oa->lsdb);
1041 }
1042 }
1043 return 0;
1044 }
1045
1046 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1047 zlog_debug(
1048 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
1049 oa->name);
1050
1051 /* prepare buffer */
1052 memset(buffer, 0, sizeof(buffer));
1053 lsa_header = (struct ospf6_lsa_header *)buffer;
1054 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
1055 *)((caddr_t)lsa_header
1056 + sizeof(struct ospf6_lsa_header));
1057
1058 /* Fill Intra-Area-Prefix-LSA */
1059 intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
1060 intra_prefix_lsa->ref_id = htonl(0);
1061 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
1062
1063 route_advertise = ospf6_route_table_create(0, 0);
1064 route_advertise->hook_add = NULL;
1065 route_advertise->hook_remove = NULL;
1066
1067 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) {
1068 if (oi->state == OSPF6_INTERFACE_DOWN) {
1069 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1070 zlog_debug(" Interface %s is down, ignore",
1071 oi->interface->name);
1072 continue;
1073 }
1074
1075 full_count = 0;
1076
1077 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on))
1078 if (on->state == OSPF6_NEIGHBOR_FULL)
1079 full_count++;
1080
1081 if (oi->state != OSPF6_INTERFACE_LOOPBACK
1082 && oi->state != OSPF6_INTERFACE_POINTTOPOINT
1083 && full_count != 0) {
1084 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1085 zlog_debug(" Interface %s is not stub, ignore",
1086 oi->interface->name);
1087 continue;
1088 }
1089
1090 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1091 zlog_debug(" Interface %s:", oi->interface->name);
1092
1093 /* connected prefix to advertise */
1094 if (oi->ifmtu >= OSPF6_JUMBO_MTU)
1095 max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO;
1096 else
1097 max_addr_count = OSPF6_MAX_IF_ADDRS;
1098
1099 for (route = ospf6_route_head(oi->route_connected), count = 0;
1100 route && count < max_addr_count;
1101 route = ospf6_route_best_next(route), count++) {
1102 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1103 zlog_debug(" include %pFX", &route->prefix);
1104 ospf6_route_add(ospf6_route_copy(route),
1105 route_advertise);
1106 }
1107 }
1108
1109 if (route_advertise->count == 0) {
1110 if (old) {
1111 ls_id = 0;
1112 ospf6_lsa_purge(old);
1113 /* find previous LSA */
1114 old_next = ospf6_lsdb_lookup(
1115 htons(OSPF6_LSTYPE_INTRA_PREFIX),
1116 htonl(++ls_id), oa->ospf6->router_id, oa->lsdb);
1117
1118 while (old_next) {
1119 ospf6_lsa_purge(old_next);
1120 old_next = ospf6_lsdb_lookup(
1121 htons(OSPF6_LSTYPE_INTRA_PREFIX),
1122 htonl(++ls_id), oa->ospf6->router_id,
1123 oa->lsdb);
1124 }
1125 }
1126 ospf6_route_table_delete(route_advertise);
1127 return 0;
1128 }
1129
1130 /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
1131 * has not change, Flush old LSA and Re-Originate INP,
1132 * as ospf6_flood() checks if LSA is same as DB,
1133 * it won't be updated to neighbor's DB.
1134 */
1135 if (oa->intra_prefix_originate) {
1136 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1137 zlog_debug(
1138 "%s: Re-originate intra prefix LSA, Current full nbrs %u",
1139 __func__, oa->full_nbrs);
1140 if (old)
1141 ospf6_lsa_purge_multi_ls_id(oa, old);
1142 oa->intra_prefix_originate = 0;
1143 }
1144
1145 /* put prefixes to advertise */
1146 prefix_num = 0;
1147 op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
1148 + sizeof(struct ospf6_intra_prefix_lsa));
1149 for (route = ospf6_route_head(route_advertise); route;
1150 route = ospf6_route_best_next(route)) {
1151 if (((caddr_t)op - (caddr_t)lsa_header) > MAX_LSA_PAYLOAD) {
1152
1153 intra_prefix_lsa->prefix_num = htons(prefix_num);
1154
1155 /* Fill LSA Header */
1156 lsa_header->age = 0;
1157 lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
1158 lsa_header->id = htonl(ls_id++);
1159 lsa_header->adv_router = oa->ospf6->router_id;
1160 lsa_header->seqnum = ospf6_new_ls_seqnum(
1161 lsa_header->type, lsa_header->id,
1162 lsa_header->adv_router, oa->lsdb);
1163 lsa_header->length =
1164 htons((caddr_t)op - (caddr_t)lsa_header);
1165
1166 /* LSA checksum */
1167 ospf6_lsa_checksum(lsa_header);
1168
1169 /* Create LSA */
1170 lsa = ospf6_lsa_create(lsa_header);
1171
1172 /* Originate */
1173 ospf6_lsa_originate_area(lsa, oa);
1174
1175 /* Prepare next buffer */
1176 memset(buffer, 0, sizeof(buffer));
1177 lsa_header = (struct ospf6_lsa_header *)buffer;
1178 intra_prefix_lsa =
1179 (struct ospf6_intra_prefix_lsa
1180 *)((caddr_t)lsa_header
1181 + sizeof(struct ospf6_lsa_header));
1182
1183 /* Fill Intra-Area-Prefix-LSA */
1184 intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
1185 intra_prefix_lsa->ref_id = htonl(0);
1186 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
1187
1188 /* Put next set of prefixes to advertise */
1189 prefix_num = 0;
1190 op = (struct ospf6_prefix
1191 *)((caddr_t)intra_prefix_lsa
1192 + sizeof(struct
1193 ospf6_intra_prefix_lsa));
1194 }
1195
1196 op->prefix_length = route->prefix.prefixlen;
1197 op->prefix_options = route->path.prefix_options;
1198 op->prefix_metric = htons(route->path.cost);
1199 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
1200 OSPF6_PREFIX_SPACE(op->prefix_length));
1201 prefix_num++;
1202
1203 op = OSPF6_PREFIX_NEXT(op);
1204 }
1205
1206 ospf6_route_table_delete(route_advertise);
1207
1208 if (prefix_num == 0) {
1209 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1210 zlog_debug(
1211 "Quit to Advertise Intra-Prefix: no route to advertise");
1212 return 0;
1213 }
1214
1215 intra_prefix_lsa->prefix_num = htons(prefix_num);
1216
1217 /* Fill LSA Header */
1218 lsa_header->age = 0;
1219 lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
1220 lsa_header->id = htonl(ls_id++);
1221 lsa_header->adv_router = oa->ospf6->router_id;
1222 lsa_header->seqnum =
1223 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
1224 lsa_header->adv_router, oa->lsdb);
1225 lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header);
1226
1227 /* LSA checksum */
1228 ospf6_lsa_checksum(lsa_header);
1229
1230 /* create LSA */
1231 lsa = ospf6_lsa_create(lsa_header);
1232
1233 /* Originate */
1234 ospf6_lsa_originate_area(lsa, oa);
1235
1236 return 0;
1237 }
1238
1239
1240 int ospf6_intra_prefix_lsa_originate_transit(struct thread *thread)
1241 {
1242 struct ospf6_interface *oi;
1243
1244 char buffer[OSPF6_MAX_LSASIZE];
1245 struct ospf6_lsa_header *lsa_header;
1246 struct ospf6_lsa *old, *lsa;
1247
1248 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1249 struct ospf6_neighbor *on;
1250 struct ospf6_route *route;
1251 struct ospf6_prefix *op;
1252 struct listnode *i;
1253 int full_count = 0;
1254 unsigned short prefix_num = 0;
1255 struct ospf6_route_table *route_advertise;
1256 struct ospf6_link_lsa *link_lsa;
1257 char *start, *end, *current;
1258 uint16_t type;
1259
1260 oi = (struct ospf6_interface *)THREAD_ARG(thread);
1261 oi->thread_intra_prefix_lsa = NULL;
1262
1263 assert(oi->area);
1264
1265 /* find previous LSA */
1266 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX),
1267 htonl(oi->interface->ifindex),
1268 oi->area->ospf6->router_id, oi->area->lsdb);
1269
1270 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
1271 if (old)
1272 ospf6_lsa_purge(old);
1273 return 0;
1274 }
1275
1276 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1277 zlog_debug(
1278 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1279 oi->interface->name);
1280
1281 /* prepare buffer */
1282 memset(buffer, 0, sizeof(buffer));
1283 lsa_header = (struct ospf6_lsa_header *)buffer;
1284 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
1285 *)((caddr_t)lsa_header
1286 + sizeof(struct ospf6_lsa_header));
1287
1288 /* Fill Intra-Area-Prefix-LSA */
1289 intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_NETWORK);
1290 intra_prefix_lsa->ref_id = htonl(oi->interface->ifindex);
1291 intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
1292
1293 if (oi->state != OSPF6_INTERFACE_DR) {
1294 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1295 zlog_debug(" Interface is not DR");
1296 if (old)
1297 ospf6_lsa_purge(old);
1298 return 0;
1299 }
1300
1301 full_count = 0;
1302 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on))
1303 if (on->state == OSPF6_NEIGHBOR_FULL)
1304 full_count++;
1305
1306 if (full_count == 0) {
1307 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1308 zlog_debug(" Interface is stub");
1309 if (old)
1310 ospf6_lsa_purge(old);
1311 return 0;
1312 }
1313
1314 /* connected prefix to advertise */
1315 route_advertise = ospf6_route_table_create(0, 0);
1316 route_advertise->hook_add = NULL;
1317 route_advertise->hook_remove = NULL;
1318
1319 type = ntohs(OSPF6_LSTYPE_LINK);
1320 for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
1321 if (OSPF6_LSA_IS_MAXAGE(lsa))
1322 continue;
1323
1324 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1325 zlog_debug(" include prefix from %s", lsa->name);
1326
1327 if (lsa->header->adv_router != oi->area->ospf6->router_id) {
1328 on = ospf6_neighbor_lookup(lsa->header->adv_router, oi);
1329 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL) {
1330 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1331 zlog_debug(
1332 " Neighbor not found or not Full, ignore");
1333 continue;
1334 }
1335 }
1336
1337 link_lsa = (struct ospf6_link_lsa
1338 *)((caddr_t)lsa->header
1339 + sizeof(struct ospf6_lsa_header));
1340
1341 prefix_num = (unsigned short)ntohl(link_lsa->prefix_num);
1342 start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
1343 end = (char *)lsa->header + ntohs(lsa->header->length);
1344 for (current = start; current < end && prefix_num;
1345 current += OSPF6_PREFIX_SIZE(op)) {
1346 op = (struct ospf6_prefix *)current;
1347 if (op->prefix_length == 0
1348 || current + OSPF6_PREFIX_SIZE(op) > end)
1349 break;
1350
1351 route = ospf6_route_create();
1352
1353 route->type = OSPF6_DEST_TYPE_NETWORK;
1354 route->prefix.family = AF_INET6;
1355 route->prefix.prefixlen = op->prefix_length;
1356 memset(&route->prefix.u.prefix6, 0,
1357 sizeof(struct in6_addr));
1358 memcpy(&route->prefix.u.prefix6, OSPF6_PREFIX_BODY(op),
1359 OSPF6_PREFIX_SPACE(op->prefix_length));
1360
1361 route->path.origin.type = lsa->header->type;
1362 route->path.origin.id = lsa->header->id;
1363 route->path.origin.adv_router = lsa->header->adv_router;
1364 route->path.options[0] = link_lsa->options[0];
1365 route->path.options[1] = link_lsa->options[1];
1366 route->path.options[2] = link_lsa->options[2];
1367 route->path.prefix_options = op->prefix_options;
1368 route->path.area_id = oi->area->area_id;
1369 route->path.type = OSPF6_PATH_TYPE_INTRA;
1370
1371 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1372 zlog_debug(" include %pFX", &route->prefix);
1373
1374 ospf6_route_add(route, route_advertise);
1375 prefix_num--;
1376 }
1377 if (current != end && IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1378 zlog_debug("Trailing garbage in %s", lsa->name);
1379 }
1380
1381 op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
1382 + sizeof(struct ospf6_intra_prefix_lsa));
1383
1384 prefix_num = 0;
1385 for (route = ospf6_route_head(route_advertise); route;
1386 route = ospf6_route_best_next(route)) {
1387 op->prefix_length = route->prefix.prefixlen;
1388 op->prefix_options = route->path.prefix_options;
1389 op->prefix_metric = htons(0);
1390 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
1391 OSPF6_PREFIX_SPACE(op->prefix_length));
1392 op = OSPF6_PREFIX_NEXT(op);
1393 prefix_num++;
1394 }
1395
1396 ospf6_route_table_delete(route_advertise);
1397
1398 if (prefix_num == 0) {
1399 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1400 zlog_debug(
1401 "Quit to Advertise Intra-Prefix: no route to advertise");
1402 return 0;
1403 }
1404
1405 intra_prefix_lsa->prefix_num = htons(prefix_num);
1406
1407 /* Fill LSA Header */
1408 lsa_header->age = 0;
1409 lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
1410 lsa_header->id = htonl(oi->interface->ifindex);
1411 lsa_header->adv_router = oi->area->ospf6->router_id;
1412 lsa_header->seqnum =
1413 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
1414 lsa_header->adv_router, oi->area->lsdb);
1415 lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header);
1416
1417 /* LSA checksum */
1418 ospf6_lsa_checksum(lsa_header);
1419
1420 /* create LSA */
1421 lsa = ospf6_lsa_create(lsa_header);
1422
1423 /* Originate */
1424 ospf6_lsa_originate_area(lsa, oi->area);
1425
1426 return 0;
1427 }
1428
1429 static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route,
1430 struct ospf6 *ospf6)
1431 {
1432 struct ospf6_path *h_path;
1433 struct ospf6_route *g_route, *nroute;
1434
1435 /* Update Global ospf6 route path */
1436 g_route = ospf6_route_lookup(&oa_route->prefix, ospf6->route_table);
1437
1438 assert(g_route);
1439
1440 for (ospf6_route_lock(g_route); g_route &&
1441 ospf6_route_is_prefix(&oa_route->prefix, g_route);
1442 g_route = nroute) {
1443 nroute = ospf6_route_next(g_route);
1444 if (g_route->type != oa_route->type)
1445 continue;
1446 if (g_route->path.area_id != oa_route->path.area_id)
1447 continue;
1448 if (g_route->path.type != OSPF6_PATH_TYPE_INTRA)
1449 continue;
1450 if (g_route->path.cost != oa_route->path.cost)
1451 continue;
1452
1453 if (ospf6_route_is_same_origin(g_route, oa_route)) {
1454 h_path = (struct ospf6_path *)listgetdata(
1455 listhead(g_route->paths));
1456 g_route->path.origin.type = h_path->origin.type;
1457 g_route->path.origin.id = h_path->origin.id;
1458 g_route->path.origin.adv_router =
1459 h_path->origin.adv_router;
1460 if (nroute)
1461 ospf6_route_unlock(nroute);
1462 break;
1463 }
1464 }
1465
1466 h_path = (struct ospf6_path *)listgetdata(
1467 listhead(oa_route->paths));
1468 oa_route->path.origin.type = h_path->origin.type;
1469 oa_route->path.origin.id = h_path->origin.id;
1470 oa_route->path.origin.adv_router = h_path->origin.adv_router;
1471 }
1472
1473 void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
1474 struct ospf6_route *old,
1475 struct ospf6_route *route)
1476 {
1477 struct ospf6_route *old_route, *ls_entry;
1478 struct ospf6_path *ecmp_path, *o_path = NULL;
1479 struct listnode *anode, *anext;
1480 struct listnode *nnode, *rnode, *rnext;
1481 struct ospf6_nexthop *nh, *rnh;
1482 char buf[PREFIX2STR_BUFFER];
1483 bool route_found = false;
1484 struct interface *ifp = NULL;
1485 struct ospf6_lsa *lsa;
1486 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1487
1488 /* check for old entry match with new route origin,
1489 * delete old entry.
1490 */
1491 for (old_route = old; old_route; old_route = old_route->next) {
1492 bool route_updated = false;
1493
1494 if (!ospf6_route_is_same(old_route, route) ||
1495 (old_route->path.type != route->path.type))
1496 continue;
1497
1498 /* Current and New route has same origin,
1499 * delete old entry.
1500 */
1501 for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext,
1502 o_path)) {
1503 /* Check old route path and route has same
1504 * origin.
1505 */
1506 if (o_path->area_id != route->path.area_id ||
1507 (memcmp(&(o_path)->origin, &(route)->path.origin,
1508 sizeof(struct ospf6_ls_origin)) != 0))
1509 continue;
1510
1511 /* Cost is not same then delete current path */
1512 if (o_path->cost == route->path.cost)
1513 continue;
1514
1515 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1516 zlog_debug(
1517 "%s: route %pFX cost old %u new %u is not same, replace route",
1518 __func__, &old_route->prefix, o_path->cost,
1519 route->path.cost);
1520 }
1521
1522 /* Remove selected current path's nh from
1523 * effective nh list.
1524 */
1525 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
1526 for (ALL_LIST_ELEMENTS(old_route->nh_list,
1527 rnode, rnext, rnh)) {
1528 if (!ospf6_nexthop_is_same(rnh, nh))
1529 continue;
1530 listnode_delete(old_route->nh_list,
1531 rnh);
1532 ospf6_nexthop_delete(rnh);
1533 route_updated = true;
1534 }
1535 }
1536
1537 listnode_delete(old_route->paths, o_path);
1538 ospf6_path_free(o_path);
1539
1540 /* Current route's path (adv_router info) is similar
1541 * to route being added.
1542 * Replace current route's path with paths list head.
1543 * Update FIB with effective NHs.
1544 */
1545 if (listcount(old_route->paths)) {
1546 if (route_updated) {
1547 for (ALL_LIST_ELEMENTS(old_route->paths,
1548 anode, anext, o_path)) {
1549 ospf6_merge_nexthops(
1550 old_route->nh_list,
1551 o_path->nh_list);
1552 }
1553 /* Update ospf6 route table and
1554 * RIB/FIB with effective
1555 * nh_list
1556 */
1557 if (oa->route_table->hook_add)
1558 (*oa->route_table->hook_add)(
1559 old_route);
1560
1561 if (old_route->path.origin.id ==
1562 route->path.origin.id &&
1563 old_route->path.origin.adv_router ==
1564 route->path.origin.adv_router) {
1565 ospf6_intra_prefix_update_route_origin(
1566 old_route, oa->ospf6);
1567 }
1568 break;
1569 }
1570 } else {
1571 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1572 zlog_debug(
1573 "%s: route %pFX old cost %u new cost %u, delete old entry.",
1574 __func__, &old_route->prefix,
1575 old_route->path.cost,
1576 route->path.cost);
1577 }
1578 if (oa->route_table->hook_remove)
1579 ospf6_route_remove(old_route,
1580 oa->route_table);
1581 else
1582 SET_FLAG(old_route->flag,
1583 OSPF6_ROUTE_REMOVE);
1584 break;
1585 }
1586 }
1587 if (route_updated)
1588 break;
1589 }
1590
1591 for (old_route = old; old_route; old_route = old_route->next) {
1592
1593 if (!ospf6_route_is_same(old_route, route) ||
1594 (old_route->path.type != route->path.type))
1595 continue;
1596
1597 /* Old Route and New Route have Equal Cost, Merge NHs */
1598 if (old_route->path.cost == route->path.cost) {
1599 route_found = true;
1600
1601 /* check if this path exists already in
1602 * route->paths list, if so, replace nh_list.
1603 */
1604 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1605 o_path)) {
1606 if (o_path->area_id == route->path.area_id &&
1607 (memcmp(&(o_path)->origin,
1608 &(route)->path.origin,
1609 sizeof(struct ospf6_ls_origin)) == 0))
1610 break;
1611 }
1612 /* If path is not found in old_route paths's list,
1613 * add a new path to route paths list and merge
1614 * nexthops in route->path->nh_list.
1615 * Otherwise replace existing path's nh_list.
1616 */
1617 if (o_path == NULL) {
1618 ecmp_path = ospf6_path_dup(&route->path);
1619
1620 /* Add a nh_list to new ecmp path */
1621 ospf6_copy_nexthops(ecmp_path->nh_list,
1622 route->nh_list);
1623 /* Add the new path to route's path list */
1624 listnode_add_sort(old_route->paths, ecmp_path);
1625
1626 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1627 zlog_debug(
1628 "%s: route %pFX %p another path added with nh %u, effective paths %u nh %u",
1629 __func__, &route->prefix,
1630 (void *)old_route,
1631 listcount(ecmp_path->nh_list),
1632 old_route->paths ? listcount(
1633 old_route->paths)
1634 : 0,
1635 listcount(old_route->nh_list));
1636 }
1637 } else {
1638 list_delete_all_node(o_path->nh_list);
1639 ospf6_copy_nexthops(o_path->nh_list,
1640 route->nh_list);
1641
1642 }
1643
1644 list_delete_all_node(old_route->nh_list);
1645
1646 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1647 o_path)) {
1648 ls_entry = ospf6_route_lookup(
1649 &o_path->ls_prefix,
1650 oa->spf_table);
1651 if (ls_entry == NULL) {
1652 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
1653 zlog_debug(
1654 "%s: ls_prfix %s ls_entry not found.",
1655 __func__, buf);
1656 continue;
1657 }
1658 lsa = ospf6_lsdb_lookup(o_path->origin.type,
1659 o_path->origin.id,
1660 o_path->origin.adv_router,
1661 oa->lsdb);
1662 if (lsa == NULL) {
1663 if (IS_OSPF6_DEBUG_EXAMIN(
1664 INTRA_PREFIX)) {
1665 struct prefix adv_prefix;
1666
1667 ospf6_linkstate_prefix(
1668 o_path->origin.adv_router,
1669 o_path->origin.id, &adv_prefix);
1670 zlog_debug(
1671 "%s: adv_router %pFX lsa not found",
1672 __func__, &adv_prefix);
1673 }
1674 continue;
1675 }
1676 intra_prefix_lsa =
1677 (struct ospf6_intra_prefix_lsa *)
1678 OSPF6_LSA_HEADER_END(lsa->header);
1679
1680 if (intra_prefix_lsa->ref_adv_router
1681 == oa->ospf6->router_id) {
1682 ifp = if_lookup_prefix(
1683 &old_route->prefix,
1684 oa->ospf6->vrf_id);
1685 }
1686
1687 if (ifp) {
1688 /* Nexthop interface found */
1689 ospf6_route_add_nexthop(old_route,
1690 ifp->ifindex,
1691 NULL);
1692 } else {
1693 /* The connected interfaces between
1694 * routers can be in different networks.
1695 * In this case the matching interface
1696 * is not found. Copy nexthops from the
1697 * link state entry
1698 */
1699 ospf6_route_merge_nexthops(old_route,
1700 ls_entry);
1701 }
1702 }
1703
1704 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
1705 zlog_debug(
1706 "%s: route %pFX %p with final effective paths %u nh %u",
1707 __func__, &route->prefix,
1708 (void *)old_route,
1709 old_route->paths
1710 ? listcount(old_route->paths)
1711 : 0,
1712 listcount(old_route->nh_list));
1713
1714 /* used in intra_route_calculation() to add to
1715 * global ospf6 route table.
1716 */
1717 UNSET_FLAG(old_route->flag, OSPF6_ROUTE_REMOVE);
1718 SET_FLAG(old_route->flag, OSPF6_ROUTE_ADD);
1719 /* Update ospf6 route table and RIB/FIB */
1720 if (oa->route_table->hook_add)
1721 (*oa->route_table->hook_add)(old_route);
1722 /* Delete the new route its info added to existing
1723 * route.
1724 */
1725 ospf6_route_delete(route);
1726
1727 break;
1728 }
1729 }
1730
1731 if (!route_found) {
1732 /* Add new route to existing node in ospf6 route table. */
1733 ospf6_route_add(route, oa->route_table);
1734 }
1735 }
1736
1737 void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
1738 {
1739 struct ospf6_area *oa;
1740 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1741 struct prefix ls_prefix;
1742 struct ospf6_route *route, *ls_entry, *old;
1743 int prefix_num;
1744 struct ospf6_prefix *op;
1745 char *start, *current, *end;
1746 char buf[PREFIX2STR_BUFFER];
1747 struct interface *ifp = NULL;
1748 int direct_connect = 0;
1749 struct ospf6_path *path;
1750
1751 if (OSPF6_LSA_IS_MAXAGE(lsa))
1752 return;
1753
1754 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
1755 zlog_debug("%s: LSA %s found", __func__, lsa->name);
1756
1757 oa = OSPF6_AREA(lsa->lsdb->data);
1758
1759 intra_prefix_lsa =
1760 (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
1761 lsa->header);
1762 if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_ROUTER))
1763 ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
1764 intra_prefix_lsa->ref_id, &ls_prefix);
1765 else if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK))
1766 ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
1767 intra_prefix_lsa->ref_id, &ls_prefix);
1768 else {
1769 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
1770 zlog_debug("Unknown reference LS-type: %#hx",
1771 ntohs(intra_prefix_lsa->ref_type));
1772 return;
1773 }
1774
1775 ls_entry = ospf6_route_lookup(&ls_prefix, oa->spf_table);
1776 if (ls_entry == NULL) {
1777 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1778 ospf6_linkstate_prefix2str(&ls_prefix, buf,
1779 sizeof(buf));
1780 zlog_debug("LS entry does not exist: %s", buf);
1781 }
1782 return;
1783 }
1784
1785 if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id) {
1786 /* the intra-prefix are directly connected */
1787 direct_connect = 1;
1788 }
1789
1790 prefix_num = ntohs(intra_prefix_lsa->prefix_num);
1791 start = (caddr_t)intra_prefix_lsa
1792 + sizeof(struct ospf6_intra_prefix_lsa);
1793 end = OSPF6_LSA_END(lsa->header);
1794 for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
1795 op = (struct ospf6_prefix *)current;
1796 if (prefix_num == 0)
1797 break;
1798 if (end < current + OSPF6_PREFIX_SIZE(op))
1799 break;
1800
1801 /* Appendix A.4.1.1 */
1802 if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU)) {
1803 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1804 ospf6_linkstate_prefix2str(
1805 (struct prefix *)OSPF6_PREFIX_BODY(op),
1806 buf, sizeof(buf));
1807 zlog_debug(
1808 "%s: Skipping Prefix %s has NU option set",
1809 __func__, buf);
1810 }
1811 continue;
1812 }
1813
1814 route = ospf6_route_create();
1815
1816 memset(&route->prefix, 0, sizeof(struct prefix));
1817 route->prefix.family = AF_INET6;
1818 route->prefix.prefixlen = op->prefix_length;
1819 ospf6_prefix_in6_addr(&route->prefix.u.prefix6,
1820 intra_prefix_lsa, op);
1821
1822 route->type = OSPF6_DEST_TYPE_NETWORK;
1823 route->path.origin.type = lsa->header->type;
1824 route->path.origin.id = lsa->header->id;
1825 route->path.origin.adv_router = lsa->header->adv_router;
1826 route->path.prefix_options = op->prefix_options;
1827 route->path.area_id = oa->area_id;
1828 route->path.type = OSPF6_PATH_TYPE_INTRA;
1829 route->path.metric_type = 1;
1830 route->path.cost =
1831 ls_entry->path.cost + ntohs(op->prefix_metric);
1832 memcpy(&route->path.ls_prefix, &ls_prefix,
1833 sizeof(struct prefix));
1834 if (direct_connect) {
1835 ifp = if_lookup_prefix(&route->prefix,
1836 oa->ospf6->vrf_id);
1837 }
1838
1839 if (ifp) {
1840 /* Nexthop interface found */
1841 ospf6_route_add_nexthop(route, ifp->ifindex, NULL);
1842 } else {
1843 /* The connected interfaces between routers can be in
1844 * different networks. In this case the matching
1845 * interface is not found. Copy nexthops from the
1846 * link state entry
1847 */
1848 ospf6_route_copy_nexthops(route, ls_entry);
1849 }
1850
1851 path = ospf6_path_dup(&route->path);
1852 ospf6_copy_nexthops(path->nh_list, route->path.nh_list);
1853 listnode_add_sort(route->paths, path);
1854
1855 old = ospf6_route_lookup(&route->prefix, oa->route_table);
1856 if (old) {
1857 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1858 prefix2str(&route->prefix, buf, sizeof(buf));
1859 zlog_debug(
1860 "%s Update route: %s old cost %u new cost %u paths %u nh %u",
1861 __func__, buf, old->path.cost,
1862 route->path.cost,
1863 listcount(route->paths),
1864 listcount(route->nh_list));
1865 }
1866 ospf6_intra_prefix_route_ecmp_path(oa, old, route);
1867 } else {
1868 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1869 prefix2str(&route->prefix, buf, sizeof(buf));
1870 zlog_debug(
1871 "%s route %s add with cost %u paths %u nh %u",
1872 __func__, buf, route->path.cost,
1873 listcount(route->paths),
1874 listcount(route->nh_list));
1875 }
1876 ospf6_route_add(route, oa->route_table);
1877 }
1878 prefix_num--;
1879 }
1880
1881 if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
1882 zlog_debug("Trailing garbage ignored");
1883 }
1884
1885 static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa *lsa,
1886 struct ospf6_area *oa,
1887 struct ospf6_route *route)
1888 {
1889 struct listnode *anode, *anext;
1890 struct listnode *nnode, *rnode, *rnext;
1891 struct ospf6_nexthop *nh, *rnh;
1892 struct ospf6_path *o_path;
1893 bool nh_updated = false;
1894 char buf[PREFIX2STR_BUFFER];
1895
1896 /* Iterate all paths of route to find maching
1897 * with LSA remove info.
1898 * If route->path is same, replace
1899 * from paths list.
1900 */
1901 for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path)) {
1902 if ((o_path->origin.type != lsa->header->type) ||
1903 (o_path->origin.adv_router != lsa->header->adv_router) ||
1904 (o_path->origin.id != lsa->header->id))
1905 continue;
1906
1907 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1908 prefix2str(&route->prefix, buf, sizeof(buf));
1909 zlog_debug(
1910 "%s: route %s path found with cost %u nh %u to remove.",
1911 __func__, buf, o_path->cost,
1912 listcount(o_path->nh_list));
1913 }
1914
1915 /* Remove found path's nh_list from
1916 * the route's nh_list.
1917 */
1918 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
1919 for (ALL_LIST_ELEMENTS(route->nh_list, rnode,
1920 rnext, rnh)) {
1921 if (!ospf6_nexthop_is_same(rnh, nh))
1922 continue;
1923 listnode_delete(route->nh_list, rnh);
1924 ospf6_nexthop_delete(rnh);
1925 }
1926 }
1927 /* Delete the path from route's
1928 * path list
1929 */
1930 listnode_delete(route->paths, o_path);
1931 ospf6_path_free(o_path);
1932 nh_updated = true;
1933 break;
1934 }
1935
1936 if (nh_updated) {
1937 /* Iterate all paths and merge nexthop,
1938 * unlesss any of the nexthop similar to
1939 * ones deleted as part of path deletion.
1940 */
1941 for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path))
1942 ospf6_merge_nexthops(route->nh_list, o_path->nh_list);
1943
1944
1945 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1946 prefix2str(&route->prefix, buf, sizeof(buf));
1947 zlog_debug(
1948 "%s: route %s update paths %u nh %u", __func__,
1949 buf, route->paths ? listcount(route->paths) : 0,
1950 route->nh_list ? listcount(route->nh_list) : 0);
1951 }
1952
1953 /* Update Global Route table and
1954 * RIB/FIB with effective
1955 * nh_list
1956 */
1957 if (oa->route_table->hook_add)
1958 (*oa->route_table->hook_add)(route);
1959
1960 /* route's primary path is similar
1961 * to LSA, replace route's primary
1962 * path with route's paths list
1963 * head.
1964 */
1965 if ((route->path.origin.id == lsa->header->id) &&
1966 (route->path.origin.adv_router ==
1967 lsa->header->adv_router)) {
1968 ospf6_intra_prefix_update_route_origin(route,
1969 oa->ospf6);
1970 }
1971 }
1972
1973 }
1974
1975 void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa)
1976 {
1977 struct ospf6_area *oa;
1978 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1979 struct prefix prefix;
1980 struct ospf6_route *route, *nroute;
1981 int prefix_num;
1982 struct ospf6_prefix *op;
1983 char *start, *current, *end;
1984 char buf[PREFIX2STR_BUFFER];
1985
1986 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
1987 zlog_debug("%s: %s disappearing", __func__, lsa->name);
1988
1989 oa = OSPF6_AREA(lsa->lsdb->data);
1990
1991 intra_prefix_lsa =
1992 (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
1993 lsa->header);
1994
1995 prefix_num = ntohs(intra_prefix_lsa->prefix_num);
1996 start = (caddr_t)intra_prefix_lsa
1997 + sizeof(struct ospf6_intra_prefix_lsa);
1998 end = OSPF6_LSA_END(lsa->header);
1999 for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
2000 op = (struct ospf6_prefix *)current;
2001 if (prefix_num == 0)
2002 break;
2003 if (end < current + OSPF6_PREFIX_SIZE(op))
2004 break;
2005 prefix_num--;
2006
2007 memset(&prefix, 0, sizeof(struct prefix));
2008 prefix.family = AF_INET6;
2009 prefix.prefixlen = op->prefix_length;
2010 ospf6_prefix_in6_addr(&prefix.u.prefix6, intra_prefix_lsa, op);
2011
2012 route = ospf6_route_lookup(&prefix, oa->route_table);
2013 if (route == NULL)
2014 continue;
2015
2016 for (ospf6_route_lock(route);
2017 route && ospf6_route_is_prefix(&prefix, route);
2018 route = nroute) {
2019 nroute = ospf6_route_next(route);
2020 if (route->type != OSPF6_DEST_TYPE_NETWORK)
2021 continue;
2022 if (route->path.area_id != oa->area_id)
2023 continue;
2024 if (route->path.type != OSPF6_PATH_TYPE_INTRA)
2025 continue;
2026 /* Route has multiple ECMP paths, remove matching
2027 * path. Update current route's effective nh list
2028 * after removal of one of the path.
2029 */
2030 if (listcount(route->paths) > 1) {
2031 ospf6_intra_prefix_lsa_remove_update_route(
2032 lsa, oa, route);
2033 } else {
2034
2035 if (route->path.origin.type != lsa->header->type
2036 || route->path.origin.id != lsa->header->id
2037 || route->path.origin.adv_router
2038 != lsa->header->adv_router)
2039 continue;
2040
2041 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
2042 prefix2str(&route->prefix, buf,
2043 sizeof(buf));
2044 zlog_debug(
2045 "%s: route remove %s with path type %u cost %u paths %u nh %u",
2046 __func__, buf, route->path.type,
2047 route->path.cost,
2048 listcount(route->paths),
2049 listcount(route->nh_list));
2050 }
2051 ospf6_route_remove(route, oa->route_table);
2052 }
2053 }
2054 if (route)
2055 ospf6_route_unlock(route);
2056 }
2057
2058 if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
2059 zlog_debug("Trailing garbage ignored");
2060 }
2061
2062 void ospf6_intra_route_calculation(struct ospf6_area *oa)
2063 {
2064 struct ospf6_route *route, *nroute;
2065 uint16_t type;
2066 struct ospf6_lsa *lsa;
2067 void (*hook_add)(struct ospf6_route *) = NULL;
2068 void (*hook_remove)(struct ospf6_route *) = NULL;
2069
2070 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
2071 zlog_debug("Re-examin intra-routes for area %s", oa->name);
2072
2073 hook_add = oa->route_table->hook_add;
2074 hook_remove = oa->route_table->hook_remove;
2075 oa->route_table->hook_add = NULL;
2076 oa->route_table->hook_remove = NULL;
2077
2078 for (route = ospf6_route_head(oa->route_table); route;
2079 route = ospf6_route_next(route))
2080 route->flag = OSPF6_ROUTE_REMOVE;
2081
2082 type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
2083 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
2084 ospf6_intra_prefix_lsa_add(lsa);
2085
2086 oa->route_table->hook_add = hook_add;
2087 oa->route_table->hook_remove = hook_remove;
2088
2089 for (route = ospf6_route_head(oa->route_table); route; route = nroute) {
2090 nroute = ospf6_route_next(route);
2091 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)
2092 && CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)) {
2093 UNSET_FLAG(route->flag, OSPF6_ROUTE_REMOVE);
2094 UNSET_FLAG(route->flag, OSPF6_ROUTE_ADD);
2095 }
2096
2097 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE))
2098 ospf6_route_remove(route, oa->route_table);
2099 else if (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)
2100 || CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE)) {
2101 if (hook_add)
2102 (*hook_add)(route);
2103 route->flag = 0;
2104 } else {
2105 /* Redo the summaries as things might have changed */
2106 ospf6_abr_originate_summary(route, oa->ospf6);
2107 route->flag = 0;
2108 }
2109 }
2110
2111 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
2112 zlog_debug("Re-examin intra-routes for area %s: Done",
2113 oa->name);
2114 }
2115
2116 static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
2117 {
2118 uint32_t brouter_id;
2119 char brouter_name[16];
2120 char area_name[16];
2121 char destination[64];
2122 char installed[64], changed[64];
2123 struct timeval now, res;
2124 char id[16], adv_router[16];
2125 char capa[16], options[16];
2126
2127 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
2128 inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name));
2129 inet_ntop(AF_INET, &brouter->path.area_id, area_name,
2130 sizeof(area_name));
2131 ospf6_linkstate_prefix2str(&brouter->prefix, destination,
2132 sizeof(destination));
2133
2134 monotime(&now);
2135 timersub(&now, &brouter->installed, &res);
2136 timerstring(&res, installed, sizeof(installed));
2137
2138 monotime(&now);
2139 timersub(&now, &brouter->changed, &res);
2140 timerstring(&res, changed, sizeof(changed));
2141
2142 inet_ntop(AF_INET, &brouter->path.origin.id, id, sizeof(id));
2143 inet_ntop(AF_INET, &brouter->path.origin.adv_router, adv_router,
2144 sizeof(adv_router));
2145
2146 ospf6_options_printbuf(brouter->path.options, options, sizeof(options));
2147 ospf6_capability_printbuf(brouter->path.router_bits, capa,
2148 sizeof(capa));
2149
2150 zlog_info("Brouter: %s via area %s", brouter_name, area_name);
2151 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
2152 (void *)brouter->prev, (void *)brouter, (void *)brouter->next,
2153 (void *)brouter->rnode);
2154 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
2155 brouter->type, destination, installed, changed);
2156 zlog_info(" lock: %d flags: %s%s%s%s", brouter->lock,
2157 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
2158 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
2159 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
2160 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
2161 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
2162 OSPF6_PATH_TYPE_NAME(brouter->path.type),
2163 ospf6_lstype_name(brouter->path.origin.type), id, adv_router);
2164 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
2165 options, capa, brouter->path.metric_type, brouter->path.cost,
2166 brouter->path.u.cost_e2);
2167 zlog_info(" paths %u nh %u", listcount(brouter->paths),
2168 listcount(brouter->nh_list));
2169 }
2170
2171 void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
2172 {
2173 struct ospf6_route *brouter, *nbrouter, *copy;
2174 void (*hook_add)(struct ospf6_route *) = NULL;
2175 void (*hook_remove)(struct ospf6_route *) = NULL;
2176 uint32_t brouter_id;
2177 char brouter_name[16];
2178
2179 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
2180 IS_OSPF6_DEBUG_ROUTE(MEMORY))
2181 zlog_debug("%s: border-router calculation for area %s",
2182 __func__, oa->name);
2183
2184 hook_add = oa->ospf6->brouter_table->hook_add;
2185 hook_remove = oa->ospf6->brouter_table->hook_remove;
2186 oa->ospf6->brouter_table->hook_add = NULL;
2187 oa->ospf6->brouter_table->hook_remove = NULL;
2188
2189 /* withdraw the previous router entries for the area */
2190 for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
2191 brouter = ospf6_route_next(brouter)) {
2192 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
2193 inet_ntop(AF_INET, &brouter_id, brouter_name,
2194 sizeof(brouter_name));
2195
2196 if (brouter->path.area_id != oa->area_id)
2197 continue;
2198
2199 SET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
2200
2201 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id)
2202 || IS_OSPF6_DEBUG_ROUTE(MEMORY)) {
2203 zlog_debug("%p: mark as removing: area %s brouter %s",
2204 (void *)brouter, oa->name, brouter_name);
2205 ospf6_brouter_debug_print(brouter);
2206 }
2207 }
2208
2209 for (brouter = ospf6_route_head(oa->spf_table); brouter;
2210 brouter = ospf6_route_next(brouter)) {
2211 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
2212 inet_ntop(AF_INET, &brouter_id, brouter_name,
2213 sizeof(brouter_name));
2214
2215 if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
2216 continue;
2217
2218 if (ospf6_linkstate_prefix_id(&brouter->prefix) != htonl(0))
2219 continue;
2220
2221 if (!CHECK_FLAG(brouter->path.router_bits, OSPF6_ROUTER_BIT_E)
2222 && !CHECK_FLAG(brouter->path.router_bits,
2223 OSPF6_ROUTER_BIT_B))
2224 continue;
2225
2226 if (!OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_V6)
2227 || !OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_R))
2228 continue;
2229
2230 copy = ospf6_route_copy(brouter);
2231 copy->type = OSPF6_DEST_TYPE_ROUTER;
2232 copy->path.area_id = oa->area_id;
2233 ospf6_route_add(copy, oa->ospf6->brouter_table);
2234
2235 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id)
2236 || IS_OSPF6_DEBUG_ROUTE(MEMORY)) {
2237 zlog_debug("%p: transfer: area %s brouter %s",
2238 (void *)brouter, oa->name, brouter_name);
2239 ospf6_brouter_debug_print(brouter);
2240 }
2241 }
2242
2243 oa->ospf6->brouter_table->hook_add = hook_add;
2244 oa->ospf6->brouter_table->hook_remove = hook_remove;
2245
2246 for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
2247 brouter = nbrouter) {
2248
2249 /*
2250 * brouter may have been "deleted" in the last loop iteration.
2251 * If this is the case there is still 1 final refcount lock
2252 * taken by ospf6_route_next, that will be released by the same
2253 * call and result in deletion. To avoid heap UAF we must then
2254 * skip processing the deleted route.
2255 */
2256 if (brouter->lock == 1) {
2257 if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
2258 ospf6_brouter_debug_print(brouter);
2259 nbrouter = ospf6_route_next(brouter);
2260 continue;
2261 } else {
2262 nbrouter = ospf6_route_next(brouter);
2263 }
2264
2265 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
2266 inet_ntop(AF_INET, &brouter_id, brouter_name,
2267 sizeof(brouter_name));
2268
2269 if (brouter->path.area_id != oa->area_id)
2270 continue;
2271
2272 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
2273 continue;
2274
2275 /* After iterating spf_table for all routers including
2276 * intra brouter, clear mark for remove flag for
2277 * inter border router if its adv router present in
2278 * SPF table.
2279 */
2280 if (brouter->path.type == OSPF6_PATH_TYPE_INTER) {
2281 struct prefix adv_prefix;
2282
2283 ospf6_linkstate_prefix(brouter->path.origin.adv_router,
2284 htonl(0), &adv_prefix);
2285
2286 if (ospf6_route_lookup(&adv_prefix, oa->spf_table)) {
2287 if (IS_OSPF6_DEBUG_BROUTER) {
2288 zlog_debug(
2289 "%s: keep inter brouter %s as adv router 0x%x found in spf",
2290 __func__, brouter_name,
2291 brouter->path.origin
2292 .adv_router);
2293 ospf6_brouter_debug_print(brouter);
2294 }
2295 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
2296 }
2297 }
2298
2299 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)
2300 && CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)) {
2301 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
2302 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
2303 }
2304
2305 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)) {
2306 if (IS_OSPF6_DEBUG_BROUTER
2307 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2308 brouter_id)
2309 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2310 oa->area_id))
2311 zlog_debug(
2312 "%s: brouter %s disappears via area %s",
2313 __func__, brouter_name, oa->name);
2314 /* This is used to protect nbrouter from removed from
2315 * the table. For an example, ospf6_abr_examin_summary,
2316 * removes brouters which are marked for remove.
2317 */
2318 oa->intra_brouter_calc = 1;
2319 ospf6_route_remove(brouter, oa->ospf6->brouter_table);
2320 brouter = NULL;
2321 } else if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)
2322 || CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE)) {
2323 if (IS_OSPF6_DEBUG_BROUTER
2324 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2325 brouter_id)
2326 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2327 oa->area_id))
2328 zlog_info("%s: brouter %s appears via area %s",
2329 __func__, brouter_name, oa->name);
2330
2331 /* newly added */
2332 if (hook_add)
2333 (*hook_add)(brouter);
2334 } else {
2335 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2336 brouter_id)
2337 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2338 oa->area_id))
2339 zlog_debug(
2340 "brouter %s still exists via area %s",
2341 brouter_name, oa->name);
2342 /* But re-originate summaries */
2343 ospf6_abr_originate_summary(brouter, oa->ospf6);
2344 }
2345
2346 if (brouter) {
2347 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
2348 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE);
2349 }
2350 /* Reset for nbrouter */
2351 oa->intra_brouter_calc = 0;
2352 }
2353
2354 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
2355 IS_OSPF6_DEBUG_ROUTE(MEMORY))
2356 zlog_debug("%s: border-router calculation for area %s: done",
2357 __func__, oa->name);
2358 }
2359
2360 static struct ospf6_lsa_handler router_handler = {
2361 .lh_type = OSPF6_LSTYPE_ROUTER,
2362 .lh_name = "Router",
2363 .lh_short_name = "Rtr",
2364 .lh_show = ospf6_router_lsa_show,
2365 .lh_get_prefix_str = ospf6_router_lsa_get_nbr_id,
2366 .lh_debug = 0};
2367
2368 static struct ospf6_lsa_handler network_handler = {
2369 .lh_type = OSPF6_LSTYPE_NETWORK,
2370 .lh_name = "Network",
2371 .lh_short_name = "Net",
2372 .lh_show = ospf6_network_lsa_show,
2373 .lh_get_prefix_str = ospf6_network_lsa_get_ar_id,
2374 .lh_debug = 0};
2375
2376 static struct ospf6_lsa_handler link_handler = {
2377 .lh_type = OSPF6_LSTYPE_LINK,
2378 .lh_name = "Link",
2379 .lh_short_name = "Lnk",
2380 .lh_show = ospf6_link_lsa_show,
2381 .lh_get_prefix_str = ospf6_link_lsa_get_prefix_str,
2382 .lh_debug = 0};
2383
2384 static struct ospf6_lsa_handler intra_prefix_handler = {
2385 .lh_type = OSPF6_LSTYPE_INTRA_PREFIX,
2386 .lh_name = "Intra-Prefix",
2387 .lh_short_name = "INP",
2388 .lh_show = ospf6_intra_prefix_lsa_show,
2389 .lh_get_prefix_str = ospf6_intra_prefix_lsa_get_prefix_str,
2390 .lh_debug = 0};
2391
2392 void ospf6_intra_init(void)
2393 {
2394 ospf6_install_lsa_handler(&router_handler);
2395 ospf6_install_lsa_handler(&network_handler);
2396 ospf6_install_lsa_handler(&link_handler);
2397 ospf6_install_lsa_handler(&intra_prefix_handler);
2398 }
2399
2400 DEFUN (debug_ospf6_brouter,
2401 debug_ospf6_brouter_cmd,
2402 "debug ospf6 border-routers",
2403 DEBUG_STR
2404 OSPF6_STR
2405 "Debug border router\n"
2406 )
2407 {
2408 OSPF6_DEBUG_BROUTER_ON();
2409 return CMD_SUCCESS;
2410 }
2411
2412 DEFUN (no_debug_ospf6_brouter,
2413 no_debug_ospf6_brouter_cmd,
2414 "no debug ospf6 border-routers",
2415 NO_STR
2416 DEBUG_STR
2417 OSPF6_STR
2418 "Debug border router\n"
2419 )
2420 {
2421 OSPF6_DEBUG_BROUTER_OFF();
2422 return CMD_SUCCESS;
2423 }
2424
2425 DEFUN (debug_ospf6_brouter_router,
2426 debug_ospf6_brouter_router_cmd,
2427 "debug ospf6 border-routers router-id A.B.C.D",
2428 DEBUG_STR
2429 OSPF6_STR
2430 "Debug border router\n"
2431 "Debug specific border router\n"
2432 "Specify border-router's router-id\n"
2433 )
2434 {
2435 int idx_ipv4 = 4;
2436 uint32_t router_id;
2437 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
2438 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id);
2439 return CMD_SUCCESS;
2440 }
2441
2442 DEFUN (no_debug_ospf6_brouter_router,
2443 no_debug_ospf6_brouter_router_cmd,
2444 "no debug ospf6 border-routers router-id",
2445 NO_STR
2446 DEBUG_STR
2447 OSPF6_STR
2448 "Debug border router\n"
2449 "Debug specific border router\n"
2450 )
2451 {
2452 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
2453 return CMD_SUCCESS;
2454 }
2455
2456 DEFUN (debug_ospf6_brouter_area,
2457 debug_ospf6_brouter_area_cmd,
2458 "debug ospf6 border-routers area-id A.B.C.D",
2459 DEBUG_STR
2460 OSPF6_STR
2461 "Debug border router\n"
2462 "Debug border routers in specific Area\n"
2463 "Specify Area-ID\n"
2464 )
2465 {
2466 int idx_ipv4 = 4;
2467 uint32_t area_id;
2468 inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id);
2469 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id);
2470 return CMD_SUCCESS;
2471 }
2472
2473 DEFUN (no_debug_ospf6_brouter_area,
2474 no_debug_ospf6_brouter_area_cmd,
2475 "no debug ospf6 border-routers area-id",
2476 NO_STR
2477 DEBUG_STR
2478 OSPF6_STR
2479 "Debug border router\n"
2480 "Debug border routers in specific Area\n"
2481 )
2482 {
2483 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
2484 return CMD_SUCCESS;
2485 }
2486
2487 int config_write_ospf6_debug_brouter(struct vty *vty)
2488 {
2489 char buf[16];
2490 if (IS_OSPF6_DEBUG_BROUTER)
2491 vty_out(vty, "debug ospf6 border-routers\n");
2492 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER) {
2493 inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
2494 buf, sizeof(buf));
2495 vty_out(vty, "debug ospf6 border-routers router-id %s\n", buf);
2496 }
2497 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA) {
2498 inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
2499 buf, sizeof(buf));
2500 vty_out(vty, "debug ospf6 border-routers area-id %s\n", buf);
2501 }
2502 return 0;
2503 }
2504
2505 void install_element_ospf6_debug_brouter(void)
2506 {
2507 install_element(ENABLE_NODE, &debug_ospf6_brouter_cmd);
2508 install_element(ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
2509 install_element(ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
2510 install_element(ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
2511 install_element(ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
2512 install_element(ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
2513 install_element(CONFIG_NODE, &debug_ospf6_brouter_cmd);
2514 install_element(CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
2515 install_element(CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
2516 install_element(CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
2517 install_element(CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
2518 install_element(CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);
2519 }