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