2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
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
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.
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
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"
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"
49 #include "ospf6_spf.h"
51 unsigned char conf_debug_ospf6_brouter
= 0;
52 u_int32_t conf_debug_ospf6_brouter_specific_router_id
;
53 u_int32_t conf_debug_ospf6_brouter_specific_area_id
;
55 /******************************/
56 /* RFC2740 3.4.3.1 Router-LSA */
57 /******************************/
59 static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa
*lsa
, char *buf
,
62 struct ospf6_router_lsa
*router_lsa
;
63 struct ospf6_router_lsdesc
*lsdesc
;
65 char buf1
[INET_ADDRSTRLEN
], buf2
[INET_ADDRSTRLEN
];
68 router_lsa
= (struct ospf6_router_lsa
69 *)((char *)lsa
->header
70 + sizeof(struct ospf6_lsa_header
));
71 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
72 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
74 lsdesc
= (struct ospf6_router_lsdesc
76 + pos
* (sizeof(struct
77 ospf6_router_lsdesc
)));
78 if ((char *)lsdesc
< end
) {
79 if (buf
&& (buflen
> INET_ADDRSTRLEN
* 2)) {
81 &lsdesc
->neighbor_interface_id
, buf1
,
83 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
85 sprintf(buf
, "%s/%s", buf2
, buf1
);
94 static int ospf6_router_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
96 char *start
, *end
, *current
;
97 char buf
[32], name
[32], bits
[16], options
[32];
98 struct ospf6_router_lsa
*router_lsa
;
99 struct ospf6_router_lsdesc
*lsdesc
;
102 (struct ospf6_router_lsa
*)((char *)lsa
->header
103 + sizeof(struct ospf6_lsa_header
));
105 ospf6_capability_printbuf(router_lsa
->bits
, bits
, sizeof(bits
));
106 ospf6_options_printbuf(router_lsa
->options
, options
, sizeof(options
));
107 vty_out(vty
, " Bits: %s Options: %s\n", bits
, options
);
109 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
110 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
111 for (current
= start
;
112 current
+ sizeof(struct ospf6_router_lsdesc
) <= end
;
113 current
+= sizeof(struct ospf6_router_lsdesc
)) {
114 lsdesc
= (struct ospf6_router_lsdesc
*)current
;
116 if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_POINTTOPOINT
)
117 snprintf(name
, sizeof(name
), "Point-To-Point");
118 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
)
119 snprintf(name
, sizeof(name
), "Transit-Network");
120 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_STUB_NETWORK
)
121 snprintf(name
, sizeof(name
), "Stub-Network");
122 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_VIRTUAL_LINK
)
123 snprintf(name
, sizeof(name
), "Virtual-Link");
125 snprintf(name
, sizeof(name
), "Unknown (%#x)",
128 vty_out(vty
, " Type: %s Metric: %d\n", name
,
129 ntohs(lsdesc
->metric
));
130 vty_out(vty
, " Interface ID: %s\n",
131 inet_ntop(AF_INET
, &lsdesc
->interface_id
, buf
,
133 vty_out(vty
, " Neighbor Interface ID: %s\n",
134 inet_ntop(AF_INET
, &lsdesc
->neighbor_interface_id
, buf
,
136 vty_out(vty
, " Neighbor Router ID: %s\n",
137 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
, buf
,
143 static void ospf6_router_lsa_options_set(struct ospf6_area
*oa
,
144 struct ospf6_router_lsa
*router_lsa
)
146 OSPF6_OPT_CLEAR_ALL(router_lsa
->options
);
147 memcpy(router_lsa
->options
, oa
->options
, 3);
149 if (ospf6_is_router_abr(ospf6
))
150 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
152 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
154 if (!IS_AREA_STUB(oa
) && ospf6_asbr_is_asbr(oa
->ospf6
)) {
155 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
157 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
160 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_V
);
161 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_W
);
164 int ospf6_router_is_stub_router(struct ospf6_lsa
*lsa
)
166 struct ospf6_router_lsa
*rtr_lsa
;
168 if (lsa
!= NULL
&& OSPF6_LSA_IS_TYPE(ROUTER
, lsa
)) {
169 rtr_lsa
= (struct ospf6_router_lsa
170 *)((caddr_t
)lsa
->header
171 + sizeof(struct ospf6_lsa_header
));
173 if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_R
)) {
174 return (OSPF6_IS_STUB_ROUTER
);
175 } else if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_V6
)) {
176 return (OSPF6_IS_STUB_ROUTER_V6
);
180 return (OSPF6_NOT_STUB_ROUTER
);
183 int ospf6_router_lsa_originate(struct thread
*thread
)
185 struct ospf6_area
*oa
;
187 char buffer
[OSPF6_MAX_LSASIZE
];
188 struct ospf6_lsa_header
*lsa_header
;
189 struct ospf6_lsa
*lsa
;
191 u_int32_t link_state_id
= 0;
192 struct listnode
*node
, *nnode
;
194 struct ospf6_interface
*oi
;
195 struct ospf6_neighbor
*on
, *drouter
= NULL
;
196 struct ospf6_router_lsa
*router_lsa
;
197 struct ospf6_router_lsdesc
*lsdesc
;
202 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
203 oa
->thread_router_lsa
= NULL
;
205 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
206 zlog_debug("Originate Router-LSA for Area %s", oa
->name
);
208 memset(buffer
, 0, sizeof(buffer
));
209 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
211 (struct ospf6_router_lsa
*)((caddr_t
)lsa_header
212 + sizeof(struct ospf6_lsa_header
));
214 ospf6_router_lsa_options_set(oa
, router_lsa
);
216 /* describe links for each interfaces */
217 lsdesc
= (struct ospf6_router_lsdesc
218 *)((caddr_t
)router_lsa
219 + sizeof(struct ospf6_router_lsa
));
221 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
222 /* Interfaces in state Down or Loopback are not described */
223 if (oi
->state
== OSPF6_INTERFACE_DOWN
224 || oi
->state
== OSPF6_INTERFACE_LOOPBACK
)
227 /* Nor are interfaces without any full adjacencies described */
229 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
230 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
236 /* Multiple Router-LSA instance according to size limit setting
238 if ((oa
->router_lsa_size_limit
!= 0)
239 && ((size_t)((char *)lsdesc
- buffer
)
240 + sizeof(struct ospf6_router_lsdesc
)
241 > oa
->router_lsa_size_limit
)) {
243 == (caddr_t
)router_lsa
244 + sizeof(struct ospf6_router_lsa
)) {
245 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
247 "Size limit setting for Router-LSA too short");
254 /* Point-to-Point interfaces */
255 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
256 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
)) {
257 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
260 lsdesc
->type
= OSPF6_ROUTER_LSDESC_POINTTOPOINT
;
261 lsdesc
->metric
= htons(oi
->cost
);
262 lsdesc
->interface_id
=
263 htonl(oi
->interface
->ifindex
);
264 lsdesc
->neighbor_interface_id
=
266 lsdesc
->neighbor_router_id
= on
->router_id
;
272 /* Broadcast and NBMA interfaces */
273 else if (oi
->type
== OSPF_IFTYPE_BROADCAST
) {
274 /* If this router is not DR,
275 and If this router not fully adjacent with DR,
276 this interface is not transit yet: ignore. */
277 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
279 ospf6_neighbor_lookup(oi
->drouter
, oi
);
281 || drouter
->state
!= OSPF6_NEIGHBOR_FULL
)
285 lsdesc
->type
= OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
;
286 lsdesc
->metric
= htons(oi
->cost
);
287 lsdesc
->interface_id
= htonl(oi
->interface
->ifindex
);
288 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
289 lsdesc
->neighbor_interface_id
=
290 htonl(drouter
->ifindex
);
291 lsdesc
->neighbor_router_id
= drouter
->router_id
;
293 lsdesc
->neighbor_interface_id
=
294 htonl(oi
->interface
->ifindex
);
295 lsdesc
->neighbor_router_id
=
296 oi
->area
->ospf6
->router_id
;
301 assert(0); /* Unknown interface type */
306 /* Point-to-Multipoint interfaces */
310 /* Fill LSA Header */
312 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
313 lsa_header
->id
= htonl(link_state_id
);
314 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
316 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
317 lsa_header
->adv_router
, oa
->lsdb
);
318 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
321 ospf6_lsa_checksum(lsa_header
);
324 lsa
= ospf6_lsa_create(lsa_header
);
327 ospf6_lsa_originate_area(lsa
, oa
);
331 /* Do premature-aging of rest, undesired Router-LSAs */
332 type
= ntohs(OSPF6_LSTYPE_ROUTER
);
333 router
= oa
->ospf6
->router_id
;
335 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router
, lsa
)) {
336 if (ntohl(lsa
->header
->id
) < link_state_id
)
338 ospf6_lsa_purge(lsa
);
343 * Waiting till the LSA is actually removed from the database to trigger
344 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
345 * interfaces associated with an area are gone, triggering an SPF right
347 * helps convergence with inter-area routes.
349 if (count
&& !link_state_id
)
350 ospf6_spf_schedule(oa
->ospf6
,
351 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED
);
356 /*******************************/
357 /* RFC2740 3.4.3.2 Network-LSA */
358 /*******************************/
360 static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa
*lsa
, char *buf
,
363 char *start
, *end
, *current
;
364 struct ospf6_network_lsa
*network_lsa
;
365 struct ospf6_network_lsdesc
*lsdesc
;
368 network_lsa
= (struct ospf6_network_lsa
369 *)((caddr_t
)lsa
->header
370 + sizeof(struct ospf6_lsa_header
));
372 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
373 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
374 current
= start
+ pos
* (sizeof(struct ospf6_network_lsdesc
));
376 if ((current
+ sizeof(struct ospf6_network_lsdesc
)) <= end
) {
377 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
379 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
,
388 static int ospf6_network_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
390 char *start
, *end
, *current
;
391 struct ospf6_network_lsa
*network_lsa
;
392 struct ospf6_network_lsdesc
*lsdesc
;
393 char buf
[128], options
[32];
396 (struct ospf6_network_lsa
*)((caddr_t
)lsa
->header
397 + sizeof(struct ospf6_lsa_header
));
399 ospf6_options_printbuf(network_lsa
->options
, options
, sizeof(options
));
400 vty_out(vty
, " Options: %s\n", options
);
402 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
403 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
404 for (current
= start
;
405 current
+ sizeof(struct ospf6_network_lsdesc
) <= end
;
406 current
+= sizeof(struct ospf6_network_lsdesc
)) {
407 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
408 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
, sizeof(buf
));
409 vty_out(vty
, " Attached Router: %s\n", buf
);
414 int ospf6_network_lsa_originate(struct thread
*thread
)
416 struct ospf6_interface
*oi
;
418 char buffer
[OSPF6_MAX_LSASIZE
];
419 struct ospf6_lsa_header
*lsa_header
;
422 struct ospf6_lsa
*old
, *lsa
;
423 struct ospf6_network_lsa
*network_lsa
;
424 struct ospf6_network_lsdesc
*lsdesc
;
425 struct ospf6_neighbor
*on
;
426 struct ospf6_link_lsa
*link_lsa
;
430 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
431 oi
->thread_network_lsa
= NULL
;
433 /* The interface must be enabled until here. A Network-LSA of a
434 disabled interface (but was once enabled) should be flushed
435 by ospf6_lsa_refresh (), and does not come here. */
438 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK
),
439 htonl(oi
->interface
->ifindex
),
440 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
442 /* Do not originate Network-LSA if not DR */
443 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
445 ospf6_lsa_purge(old
);
447 * Waiting till the LSA is actually removed from the
449 * trigger SPF delays network convergence.
453 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED
);
458 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
459 zlog_debug("Originate Network-LSA for Interface %s",
460 oi
->interface
->name
);
462 /* If none of neighbor is adjacent to us */
465 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
466 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
470 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
471 zlog_debug("Interface stub, ignore");
473 ospf6_lsa_purge(old
);
478 memset(buffer
, 0, sizeof(buffer
));
479 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
481 (struct ospf6_network_lsa
*)((caddr_t
)lsa_header
482 + sizeof(struct ospf6_lsa_header
));
484 /* Collect the interface's Link-LSAs to describe
485 network's optional capabilities */
486 type
= htons(OSPF6_LSTYPE_LINK
);
487 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
488 link_lsa
= (struct ospf6_link_lsa
489 *)((caddr_t
)lsa
->header
490 + sizeof(struct ospf6_lsa_header
));
491 network_lsa
->options
[0] |= link_lsa
->options
[0];
492 network_lsa
->options
[1] |= link_lsa
->options
[1];
493 network_lsa
->options
[2] |= link_lsa
->options
[2];
496 lsdesc
= (struct ospf6_network_lsdesc
497 *)((caddr_t
)network_lsa
498 + sizeof(struct ospf6_network_lsa
));
500 /* set Link Description to the router itself */
501 lsdesc
->router_id
= oi
->area
->ospf6
->router_id
;
504 /* Walk through the neighbors */
505 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
)) {
506 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
509 /* set this neighbor's Router-ID to LSA */
510 lsdesc
->router_id
= on
->router_id
;
514 /* Fill LSA Header */
516 lsa_header
->type
= htons(OSPF6_LSTYPE_NETWORK
);
517 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
518 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
520 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
521 lsa_header
->adv_router
, oi
->area
->lsdb
);
522 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
525 ospf6_lsa_checksum(lsa_header
);
528 lsa
= ospf6_lsa_create(lsa_header
);
531 ospf6_lsa_originate_area(lsa
, oi
->area
);
537 /****************************/
538 /* RFC2740 3.4.3.6 Link-LSA */
539 /****************************/
541 static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa
*lsa
, char *buf
,
544 char *start
, *end
, *current
;
545 struct ospf6_link_lsa
*link_lsa
;
547 struct ospf6_prefix
*prefix
;
548 int cnt
= 0, prefixnum
;
551 link_lsa
= (struct ospf6_link_lsa
552 *)((caddr_t
)lsa
->header
553 + sizeof(struct ospf6_lsa_header
));
556 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
,
561 prefixnum
= ntohl(link_lsa
->prefix_num
);
565 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
566 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
570 prefix
= (struct ospf6_prefix
*)current
;
571 if (prefix
->prefix_length
== 0
572 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
578 start
+ pos
* OSPF6_PREFIX_SIZE(prefix
);
581 memset(&in6
, 0, sizeof(in6
));
582 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
584 prefix
->prefix_length
));
585 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
588 } while (current
<= end
);
593 static int ospf6_link_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
595 char *start
, *end
, *current
;
596 struct ospf6_link_lsa
*link_lsa
;
598 char buf
[128], options
[32];
599 struct ospf6_prefix
*prefix
;
600 const char *p
, *mc
, *la
, *nu
;
603 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa
->header
604 + sizeof(struct ospf6_lsa_header
));
606 ospf6_options_printbuf(link_lsa
->options
, options
, sizeof(options
));
607 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
, sizeof(buf
));
608 prefixnum
= ntohl(link_lsa
->prefix_num
);
610 vty_out(vty
, " Priority: %d Options: %s\n", link_lsa
->priority
,
612 vty_out(vty
, " LinkLocal Address: %s\n", buf
);
613 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
615 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
616 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
617 for (current
= start
; current
< end
;
618 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
619 prefix
= (struct ospf6_prefix
*)current
;
620 if (prefix
->prefix_length
== 0
621 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
624 p
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_P
)
627 mc
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_MC
)
630 la
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_LA
)
633 nu
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)
636 vty_out(vty
, " Prefix Options: %s|%s|%s|%s\n", p
, mc
, la
,
639 memset(&in6
, 0, sizeof(in6
));
640 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
641 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
642 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
643 vty_out(vty
, " Prefix: %s/%d\n", buf
,
644 prefix
->prefix_length
);
650 int ospf6_link_lsa_originate(struct thread
*thread
)
652 struct ospf6_interface
*oi
;
654 char buffer
[OSPF6_MAX_LSASIZE
];
655 struct ospf6_lsa_header
*lsa_header
;
656 struct ospf6_lsa
*old
, *lsa
;
658 struct ospf6_link_lsa
*link_lsa
;
659 struct ospf6_route
*route
;
660 struct ospf6_prefix
*op
;
662 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
663 oi
->thread_link_lsa
= NULL
;
667 /* find previous LSA */
668 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK
),
669 htonl(oi
->interface
->ifindex
),
670 oi
->area
->ospf6
->router_id
, oi
->lsdb
);
672 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
674 ospf6_lsa_purge(old
);
678 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
679 zlog_debug("Originate Link-LSA for Interface %s",
680 oi
->interface
->name
);
682 /* can't make Link-LSA if linklocal address not set */
683 if (oi
->linklocal_addr
== NULL
) {
684 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
686 "No Linklocal address on %s, defer originating",
687 oi
->interface
->name
);
689 ospf6_lsa_purge(old
);
694 memset(buffer
, 0, sizeof(buffer
));
695 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
696 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa_header
697 + sizeof(struct ospf6_lsa_header
));
700 link_lsa
->priority
= oi
->priority
;
701 memcpy(link_lsa
->options
, oi
->area
->options
, 3);
702 memcpy(&link_lsa
->linklocal_addr
, oi
->linklocal_addr
,
703 sizeof(struct in6_addr
));
704 link_lsa
->prefix_num
= htonl(oi
->route_connected
->count
);
706 op
= (struct ospf6_prefix
*)((caddr_t
)link_lsa
707 + sizeof(struct ospf6_link_lsa
));
709 /* connected prefix to advertise */
710 for (route
= ospf6_route_head(oi
->route_connected
); route
;
711 route
= ospf6_route_next(route
)) {
712 op
->prefix_length
= route
->prefix
.prefixlen
;
713 op
->prefix_options
= route
->path
.prefix_options
;
714 op
->prefix_metric
= htons(0);
715 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
716 OSPF6_PREFIX_SPACE(op
->prefix_length
));
717 op
= OSPF6_PREFIX_NEXT(op
);
720 /* Fill LSA Header */
722 lsa_header
->type
= htons(OSPF6_LSTYPE_LINK
);
723 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
724 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
726 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
727 lsa_header
->adv_router
, oi
->lsdb
);
728 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)buffer
);
731 ospf6_lsa_checksum(lsa_header
);
734 lsa
= ospf6_lsa_create(lsa_header
);
737 ospf6_lsa_originate_interface(lsa
, oi
);
743 /*****************************************/
744 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
745 /*****************************************/
746 static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
747 char *buf
, int buflen
,
750 char *start
, *end
, *current
;
751 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
753 int prefixnum
, cnt
= 0;
754 struct ospf6_prefix
*prefix
;
758 (struct ospf6_intra_prefix_lsa
759 *)((caddr_t
)lsa
->header
760 + sizeof(struct ospf6_lsa_header
));
762 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
766 start
= (char *)intra_prefix_lsa
767 + sizeof(struct ospf6_intra_prefix_lsa
);
768 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
772 prefix
= (struct ospf6_prefix
*)current
;
773 if (prefix
->prefix_length
== 0
774 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
780 start
+ pos
* OSPF6_PREFIX_SIZE(prefix
);
783 memset(&in6
, 0, sizeof(in6
));
784 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
786 prefix
->prefix_length
));
787 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
788 sprintf(&buf
[strlen(buf
)], "/%d",
789 prefix
->prefix_length
);
792 } while (current
<= end
);
797 static int ospf6_intra_prefix_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
799 char *start
, *end
, *current
;
800 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
803 struct ospf6_prefix
*prefix
;
804 char id
[16], adv_router
[16];
805 const char *p
, *mc
, *la
, *nu
;
808 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
809 *)((caddr_t
)lsa
->header
810 + sizeof(struct ospf6_lsa_header
));
812 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
814 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
816 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_id
, id
, sizeof(id
));
817 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_adv_router
, adv_router
,
819 vty_out(vty
, " Reference: %s Id: %s Adv: %s\n",
820 ospf6_lstype_name(intra_prefix_lsa
->ref_type
), id
, adv_router
);
822 start
= (char *)intra_prefix_lsa
823 + sizeof(struct ospf6_intra_prefix_lsa
);
824 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
825 for (current
= start
; current
< end
;
826 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
827 prefix
= (struct ospf6_prefix
*)current
;
828 if (prefix
->prefix_length
== 0
829 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
832 p
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_P
)
835 mc
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_MC
)
838 la
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_LA
)
841 nu
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)
844 vty_out(vty
, " Prefix Options: %s|%s|%s|%s\n", p
, mc
, la
,
847 memset(&in6
, 0, sizeof(in6
));
848 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
849 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
850 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
851 vty_out(vty
, " Prefix: %s/%d\n", buf
,
852 prefix
->prefix_length
);
858 int ospf6_intra_prefix_lsa_originate_stub(struct thread
*thread
)
860 struct ospf6_area
*oa
;
862 char buffer
[OSPF6_MAX_LSASIZE
];
863 struct ospf6_lsa_header
*lsa_header
;
864 struct ospf6_lsa
*old
, *lsa
;
866 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
867 struct ospf6_interface
*oi
;
868 struct ospf6_neighbor
*on
;
869 struct ospf6_route
*route
;
870 struct ospf6_prefix
*op
;
871 struct listnode
*i
, *j
;
873 unsigned short prefix_num
= 0;
874 char buf
[PREFIX2STR_BUFFER
];
875 struct ospf6_route_table
*route_advertise
;
877 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
878 oa
->thread_intra_prefix_lsa
= NULL
;
880 /* find previous LSA */
881 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
), htonl(0),
882 oa
->ospf6
->router_id
, oa
->lsdb
);
884 if (!IS_AREA_ENABLED(oa
)) {
886 ospf6_lsa_purge(old
);
890 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
892 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
896 memset(buffer
, 0, sizeof(buffer
));
897 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
898 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
899 *)((caddr_t
)lsa_header
900 + sizeof(struct ospf6_lsa_header
));
902 /* Fill Intra-Area-Prefix-LSA */
903 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
904 intra_prefix_lsa
->ref_id
= htonl(0);
905 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
907 route_advertise
= ospf6_route_table_create(0, 0);
909 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, i
, oi
)) {
910 if (oi
->state
== OSPF6_INTERFACE_DOWN
) {
911 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
912 zlog_debug(" Interface %s is down, ignore",
913 oi
->interface
->name
);
919 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
920 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
923 if (oi
->state
!= OSPF6_INTERFACE_LOOPBACK
924 && oi
->state
!= OSPF6_INTERFACE_POINTTOPOINT
925 && full_count
!= 0) {
926 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
927 zlog_debug(" Interface %s is not stub, ignore",
928 oi
->interface
->name
);
932 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
933 zlog_debug(" Interface %s:", oi
->interface
->name
);
935 /* connected prefix to advertise */
936 for (route
= ospf6_route_head(oi
->route_connected
); route
;
937 route
= ospf6_route_best_next(route
)) {
938 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
)) {
939 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
940 zlog_debug(" include %s", buf
);
942 ospf6_route_add(ospf6_route_copy(route
),
947 if (route_advertise
->count
== 0) {
949 ospf6_lsa_purge(old
);
950 ospf6_route_table_delete(route_advertise
);
954 /* put prefixes to advertise */
956 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
957 + sizeof(struct ospf6_intra_prefix_lsa
));
958 for (route
= ospf6_route_head(route_advertise
); route
;
959 route
= ospf6_route_best_next(route
)) {
960 op
->prefix_length
= route
->prefix
.prefixlen
;
961 op
->prefix_options
= route
->path
.prefix_options
;
962 op
->prefix_metric
= htons(route
->path
.cost
);
963 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
964 OSPF6_PREFIX_SPACE(op
->prefix_length
));
965 op
= OSPF6_PREFIX_NEXT(op
);
969 ospf6_route_table_delete(route_advertise
);
971 if (prefix_num
== 0) {
972 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
974 "Quit to Advertise Intra-Prefix: no route to advertise");
978 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
980 /* Fill LSA Header */
982 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
983 lsa_header
->id
= htonl(0);
984 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
986 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
987 lsa_header
->adv_router
, oa
->lsdb
);
988 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
991 ospf6_lsa_checksum(lsa_header
);
994 lsa
= ospf6_lsa_create(lsa_header
);
997 ospf6_lsa_originate_area(lsa
, oa
);
1003 int ospf6_intra_prefix_lsa_originate_transit(struct thread
*thread
)
1005 struct ospf6_interface
*oi
;
1007 char buffer
[OSPF6_MAX_LSASIZE
];
1008 struct ospf6_lsa_header
*lsa_header
;
1009 struct ospf6_lsa
*old
, *lsa
;
1011 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1012 struct ospf6_neighbor
*on
;
1013 struct ospf6_route
*route
;
1014 struct ospf6_prefix
*op
;
1017 unsigned short prefix_num
= 0;
1018 struct ospf6_route_table
*route_advertise
;
1019 struct ospf6_link_lsa
*link_lsa
;
1020 char *start
, *end
, *current
;
1022 char buf
[PREFIX2STR_BUFFER
];
1024 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1025 oi
->thread_intra_prefix_lsa
= NULL
;
1029 /* find previous LSA */
1030 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1031 htonl(oi
->interface
->ifindex
),
1032 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
1034 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1036 ospf6_lsa_purge(old
);
1040 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1042 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1043 oi
->interface
->name
);
1045 /* prepare buffer */
1046 memset(buffer
, 0, sizeof(buffer
));
1047 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1048 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1049 *)((caddr_t
)lsa_header
1050 + sizeof(struct ospf6_lsa_header
));
1052 /* Fill Intra-Area-Prefix-LSA */
1053 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_NETWORK
);
1054 intra_prefix_lsa
->ref_id
= htonl(oi
->interface
->ifindex
);
1055 intra_prefix_lsa
->ref_adv_router
= oi
->area
->ospf6
->router_id
;
1057 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
1058 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1059 zlog_debug(" Interface is not DR");
1061 ospf6_lsa_purge(old
);
1066 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
1067 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1070 if (full_count
== 0) {
1071 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1072 zlog_debug(" Interface is stub");
1074 ospf6_lsa_purge(old
);
1078 /* connected prefix to advertise */
1079 route_advertise
= ospf6_route_table_create(0, 0);
1081 type
= ntohs(OSPF6_LSTYPE_LINK
);
1082 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
1083 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1086 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1087 zlog_debug(" include prefix from %s", lsa
->name
);
1089 if (lsa
->header
->adv_router
!= oi
->area
->ospf6
->router_id
) {
1090 on
= ospf6_neighbor_lookup(lsa
->header
->adv_router
, oi
);
1091 if (on
== NULL
|| on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1092 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1094 " Neighbor not found or not Full, ignore");
1099 link_lsa
= (struct ospf6_link_lsa
1100 *)((caddr_t
)lsa
->header
1101 + sizeof(struct ospf6_lsa_header
));
1103 prefix_num
= (unsigned short)ntohl(link_lsa
->prefix_num
);
1104 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
1105 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
1106 for (current
= start
; current
< end
&& prefix_num
;
1107 current
+= OSPF6_PREFIX_SIZE(op
)) {
1108 op
= (struct ospf6_prefix
*)current
;
1109 if (op
->prefix_length
== 0
1110 || current
+ OSPF6_PREFIX_SIZE(op
) > end
)
1113 route
= ospf6_route_create();
1115 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1116 route
->prefix
.family
= AF_INET6
;
1117 route
->prefix
.prefixlen
= op
->prefix_length
;
1118 memset(&route
->prefix
.u
.prefix6
, 0,
1119 sizeof(struct in6_addr
));
1120 memcpy(&route
->prefix
.u
.prefix6
, OSPF6_PREFIX_BODY(op
),
1121 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1123 route
->path
.origin
.type
= lsa
->header
->type
;
1124 route
->path
.origin
.id
= lsa
->header
->id
;
1125 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1126 route
->path
.options
[0] = link_lsa
->options
[0];
1127 route
->path
.options
[1] = link_lsa
->options
[1];
1128 route
->path
.options
[2] = link_lsa
->options
[2];
1129 route
->path
.prefix_options
= op
->prefix_options
;
1130 route
->path
.area_id
= oi
->area
->area_id
;
1131 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1133 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
)) {
1134 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1135 zlog_debug(" include %s", buf
);
1138 ospf6_route_add(route
, route_advertise
);
1141 if (current
!= end
&& IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1142 zlog_debug("Trailing garbage in %s", lsa
->name
);
1145 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1146 + sizeof(struct ospf6_intra_prefix_lsa
));
1149 for (route
= ospf6_route_head(route_advertise
); route
;
1150 route
= ospf6_route_best_next(route
)) {
1151 op
->prefix_length
= route
->prefix
.prefixlen
;
1152 op
->prefix_options
= route
->path
.prefix_options
;
1153 op
->prefix_metric
= htons(0);
1154 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1155 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1156 op
= OSPF6_PREFIX_NEXT(op
);
1160 ospf6_route_table_delete(route_advertise
);
1162 if (prefix_num
== 0) {
1163 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1165 "Quit to Advertise Intra-Prefix: no route to advertise");
1169 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1171 /* Fill LSA Header */
1172 lsa_header
->age
= 0;
1173 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1174 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
1175 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
1176 lsa_header
->seqnum
=
1177 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1178 lsa_header
->adv_router
, oi
->area
->lsdb
);
1179 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1182 ospf6_lsa_checksum(lsa_header
);
1185 lsa
= ospf6_lsa_create(lsa_header
);
1188 ospf6_lsa_originate_area(lsa
, oi
->area
);
1193 void ospf6_intra_prefix_lsa_add(struct ospf6_lsa
*lsa
)
1195 struct ospf6_area
*oa
;
1196 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1197 struct prefix ls_prefix
;
1198 struct ospf6_route
*route
, *ls_entry
;
1200 struct ospf6_prefix
*op
;
1201 char *start
, *current
, *end
;
1202 char buf
[PREFIX2STR_BUFFER
];
1203 struct interface
*ifp
;
1204 int direct_connect
= 0;
1206 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1209 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1210 zlog_debug("%s found", lsa
->name
);
1212 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1215 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1217 if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_ROUTER
))
1218 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1219 htonl(0), &ls_prefix
);
1220 else if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_NETWORK
))
1221 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1222 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1224 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1225 zlog_debug("Unknown reference LS-type: %#hx",
1226 ntohs(intra_prefix_lsa
->ref_type
));
1230 ls_entry
= ospf6_route_lookup(&ls_prefix
, oa
->spf_table
);
1231 if (ls_entry
== NULL
) {
1232 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1233 ospf6_linkstate_prefix2str(&ls_prefix
, buf
,
1235 zlog_debug("LS entry does not exist: %s", buf
);
1240 if (intra_prefix_lsa
->ref_adv_router
== oa
->ospf6
->router_id
) {
1241 /* the intra-prefix are directly connected */
1245 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1246 start
= (caddr_t
)intra_prefix_lsa
1247 + sizeof(struct ospf6_intra_prefix_lsa
);
1248 end
= OSPF6_LSA_END(lsa
->header
);
1249 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1250 op
= (struct ospf6_prefix
*)current
;
1251 if (prefix_num
== 0)
1253 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1256 /* Appendix A.4.1.1 */
1257 if (CHECK_FLAG(op
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)) {
1258 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1259 ospf6_linkstate_prefix2str(
1260 (struct prefix
*)OSPF6_PREFIX_BODY(op
),
1263 "%s: Skipping Prefix %s has NU option set",
1269 route
= ospf6_route_create();
1271 memset(&route
->prefix
, 0, sizeof(struct prefix
));
1272 route
->prefix
.family
= AF_INET6
;
1273 route
->prefix
.prefixlen
= op
->prefix_length
;
1274 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
, op
);
1276 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1277 route
->path
.origin
.type
= lsa
->header
->type
;
1278 route
->path
.origin
.id
= lsa
->header
->id
;
1279 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1280 route
->path
.prefix_options
= op
->prefix_options
;
1281 route
->path
.area_id
= oa
->area_id
;
1282 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1283 route
->path
.metric_type
= 1;
1285 ls_entry
->path
.cost
+ ntohs(op
->prefix_metric
);
1287 if (direct_connect
) {
1288 ifp
= if_lookup_prefix(&route
->prefix
, VRF_DEFAULT
);
1290 ospf6_route_add_nexthop(route
, ifp
->ifindex
,
1293 ospf6_route_copy_nexthops(route
, ls_entry
);
1296 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1297 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1298 zlog_debug(" add %s", buf
);
1301 ospf6_route_add(route
, oa
->route_table
);
1305 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1306 zlog_debug("Trailing garbage ignored");
1309 void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa
*lsa
)
1311 struct ospf6_area
*oa
;
1312 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1313 struct prefix prefix
;
1314 struct ospf6_route
*route
, *nroute
;
1316 struct ospf6_prefix
*op
;
1317 char *start
, *current
, *end
;
1318 char buf
[PREFIX2STR_BUFFER
];
1320 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1321 zlog_debug("%s disappearing", lsa
->name
);
1323 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1326 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1329 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1330 start
= (caddr_t
)intra_prefix_lsa
1331 + sizeof(struct ospf6_intra_prefix_lsa
);
1332 end
= OSPF6_LSA_END(lsa
->header
);
1333 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1334 op
= (struct ospf6_prefix
*)current
;
1335 if (prefix_num
== 0)
1337 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1341 memset(&prefix
, 0, sizeof(struct prefix
));
1342 prefix
.family
= AF_INET6
;
1343 prefix
.prefixlen
= op
->prefix_length
;
1344 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, op
);
1346 route
= ospf6_route_lookup(&prefix
, oa
->route_table
);
1350 for (ospf6_route_lock(route
);
1351 route
&& ospf6_route_is_prefix(&prefix
, route
);
1353 nroute
= ospf6_route_next(route
);
1354 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
1356 if (route
->path
.area_id
!= oa
->area_id
)
1358 if (route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
1360 if (route
->path
.origin
.type
!= lsa
->header
->type
1361 || route
->path
.origin
.id
!= lsa
->header
->id
1362 || route
->path
.origin
.adv_router
1363 != lsa
->header
->adv_router
)
1366 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1367 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1368 zlog_debug("remove %s", buf
);
1370 ospf6_route_remove(route
, oa
->route_table
);
1373 ospf6_route_unlock(route
);
1376 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1377 zlog_debug("Trailing garbage ignored");
1380 void ospf6_intra_route_calculation(struct ospf6_area
*oa
)
1382 struct ospf6_route
*route
, *nroute
;
1384 struct ospf6_lsa
*lsa
;
1385 void (*hook_add
)(struct ospf6_route
*) = NULL
;
1386 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
1388 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1389 zlog_debug("Re-examin intra-routes for area %s", oa
->name
);
1391 hook_add
= oa
->route_table
->hook_add
;
1392 hook_remove
= oa
->route_table
->hook_remove
;
1393 oa
->route_table
->hook_add
= NULL
;
1394 oa
->route_table
->hook_remove
= NULL
;
1396 for (route
= ospf6_route_head(oa
->route_table
); route
;
1397 route
= ospf6_route_next(route
))
1398 route
->flag
= OSPF6_ROUTE_REMOVE
;
1400 type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1401 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
1402 ospf6_intra_prefix_lsa_add(lsa
);
1404 oa
->route_table
->hook_add
= hook_add
;
1405 oa
->route_table
->hook_remove
= hook_remove
;
1407 for (route
= ospf6_route_head(oa
->route_table
); route
; route
= nroute
) {
1408 nroute
= ospf6_route_next(route
);
1409 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)
1410 && CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)) {
1411 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
);
1412 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_ADD
);
1415 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
))
1416 ospf6_route_remove(route
, oa
->route_table
);
1417 else if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)
1418 || CHECK_FLAG(route
->flag
, OSPF6_ROUTE_CHANGE
)) {
1423 /* Redo the summaries as things might have changed */
1424 ospf6_abr_originate_summary(route
);
1429 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1430 zlog_debug("Re-examin intra-routes for area %s: Done",
1434 static void ospf6_brouter_debug_print(struct ospf6_route
*brouter
)
1436 u_int32_t brouter_id
;
1437 char brouter_name
[16];
1439 char destination
[64];
1440 char installed
[64], changed
[64];
1441 struct timeval now
, res
;
1442 char id
[16], adv_router
[16];
1443 char capa
[16], options
[16];
1445 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
1446 inet_ntop(AF_INET
, &brouter_id
, brouter_name
, sizeof(brouter_name
));
1447 inet_ntop(AF_INET
, &brouter
->path
.area_id
, area_name
,
1449 ospf6_linkstate_prefix2str(&brouter
->prefix
, destination
,
1450 sizeof(destination
));
1453 timersub(&now
, &brouter
->installed
, &res
);
1454 timerstring(&res
, installed
, sizeof(installed
));
1457 timersub(&now
, &brouter
->changed
, &res
);
1458 timerstring(&res
, changed
, sizeof(changed
));
1460 inet_ntop(AF_INET
, &brouter
->path
.origin
.id
, id
, sizeof(id
));
1461 inet_ntop(AF_INET
, &brouter
->path
.origin
.adv_router
, adv_router
,
1462 sizeof(adv_router
));
1464 ospf6_options_printbuf(brouter
->path
.options
, options
, sizeof(options
));
1465 ospf6_capability_printbuf(brouter
->path
.router_bits
, capa
,
1468 zlog_info("Brouter: %s via area %s", brouter_name
, area_name
);
1469 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
1470 (void *)brouter
->prev
, (void *)brouter
, (void *)brouter
->next
,
1471 (void *)brouter
->rnode
);
1472 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
1473 brouter
->type
, destination
, installed
, changed
);
1474 zlog_info(" lock: %d flags: %s%s%s%s", brouter
->lock
,
1475 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
1476 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
1477 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
1478 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"));
1479 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
1480 OSPF6_PATH_TYPE_NAME(brouter
->path
.type
),
1481 ospf6_lstype_name(brouter
->path
.origin
.type
), id
, adv_router
);
1482 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
1483 options
, capa
, brouter
->path
.metric_type
, brouter
->path
.cost
,
1484 brouter
->path
.u
.cost_e2
);
1487 void ospf6_intra_brouter_calculation(struct ospf6_area
*oa
)
1489 struct ospf6_route
*brouter
, *nbrouter
, *copy
;
1490 void (*hook_add
)(struct ospf6_route
*) = NULL
;
1491 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
1492 u_int32_t brouter_id
;
1493 char brouter_name
[16];
1495 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
))
1496 zlog_info("border-router calculation for area %s", oa
->name
);
1498 hook_add
= oa
->ospf6
->brouter_table
->hook_add
;
1499 hook_remove
= oa
->ospf6
->brouter_table
->hook_remove
;
1500 oa
->ospf6
->brouter_table
->hook_add
= NULL
;
1501 oa
->ospf6
->brouter_table
->hook_remove
= NULL
;
1503 /* withdraw the previous router entries for the area */
1504 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
1505 brouter
= ospf6_route_next(brouter
)) {
1506 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
1507 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
1508 sizeof(brouter_name
));
1509 if (brouter
->path
.area_id
!= oa
->area_id
)
1511 SET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
1513 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
1514 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
1515 zlog_info("%p: mark as removing: area %s brouter %s",
1516 (void *)brouter
, oa
->name
, brouter_name
);
1517 ospf6_brouter_debug_print(brouter
);
1521 for (brouter
= ospf6_route_head(oa
->spf_table
); brouter
;
1522 brouter
= ospf6_route_next(brouter
)) {
1523 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
1524 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
1525 sizeof(brouter_name
));
1527 if (brouter
->type
!= OSPF6_DEST_TYPE_LINKSTATE
)
1529 if (ospf6_linkstate_prefix_id(&brouter
->prefix
) != htonl(0))
1531 if (!CHECK_FLAG(brouter
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)
1532 && !CHECK_FLAG(brouter
->path
.router_bits
,
1533 OSPF6_ROUTER_BIT_B
))
1536 if (!OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_V6
)
1537 || !OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_R
))
1540 copy
= ospf6_route_copy(brouter
);
1541 copy
->type
= OSPF6_DEST_TYPE_ROUTER
;
1542 copy
->path
.area_id
= oa
->area_id
;
1543 ospf6_route_add(copy
, oa
->ospf6
->brouter_table
);
1545 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
1546 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
1547 zlog_info("%p: transfer: area %s brouter %s",
1548 (void *)brouter
, oa
->name
, brouter_name
);
1549 ospf6_brouter_debug_print(brouter
);
1553 oa
->ospf6
->brouter_table
->hook_add
= hook_add
;
1554 oa
->ospf6
->brouter_table
->hook_remove
= hook_remove
;
1556 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
1557 brouter
= nbrouter
) {
1559 * brouter may have been "deleted" in the last loop iteration.
1560 * If this is the case there is still 1 final refcount lock
1561 * taken by ospf6_route_next, that will be released by the same
1562 * call and result in deletion. To avoid heap UAF we must then
1563 * skip processing the deleted route.
1565 if (brouter
->lock
== 1) {
1566 nbrouter
= ospf6_route_next(brouter
);
1569 nbrouter
= ospf6_route_next(brouter
);
1572 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
1573 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
1574 sizeof(brouter_name
));
1576 if (brouter
->path
.area_id
!= oa
->area_id
)
1579 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
1582 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)
1583 && CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)) {
1584 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
1585 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
1588 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)) {
1589 if (IS_OSPF6_DEBUG_BROUTER
1590 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
1592 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
1594 zlog_info("brouter %s disappears via area %s",
1595 brouter_name
, oa
->name
);
1596 ospf6_route_remove(brouter
, oa
->ospf6
->brouter_table
);
1598 } else if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)
1599 || CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
)) {
1600 if (IS_OSPF6_DEBUG_BROUTER
1601 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
1603 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
1605 zlog_info("brouter %s appears via area %s",
1606 brouter_name
, oa
->name
);
1610 (*hook_add
)(brouter
);
1612 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
1614 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
1616 zlog_info("brouter %s still exists via area %s",
1617 brouter_name
, oa
->name
);
1618 /* But re-originate summaries */
1619 ospf6_abr_originate_summary(brouter
);
1623 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
1624 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
);
1628 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
))
1629 zlog_info("border-router calculation for area %s: done",
1633 struct ospf6_lsa_handler router_handler
= {OSPF6_LSTYPE_ROUTER
, "Router", "Rtr",
1634 ospf6_router_lsa_show
,
1635 ospf6_router_lsa_get_nbr_id
};
1637 struct ospf6_lsa_handler network_handler
= {OSPF6_LSTYPE_NETWORK
, "Network",
1638 "Net", ospf6_network_lsa_show
,
1639 ospf6_network_lsa_get_ar_id
};
1641 struct ospf6_lsa_handler link_handler
= {OSPF6_LSTYPE_LINK
, "Link", "Lnk",
1642 ospf6_link_lsa_show
,
1643 ospf6_link_lsa_get_prefix_str
};
1645 struct ospf6_lsa_handler intra_prefix_handler
= {
1646 OSPF6_LSTYPE_INTRA_PREFIX
, "Intra-Prefix", "INP",
1647 ospf6_intra_prefix_lsa_show
, ospf6_intra_prefix_lsa_get_prefix_str
};
1649 void ospf6_intra_init(void)
1651 ospf6_install_lsa_handler(&router_handler
);
1652 ospf6_install_lsa_handler(&network_handler
);
1653 ospf6_install_lsa_handler(&link_handler
);
1654 ospf6_install_lsa_handler(&intra_prefix_handler
);
1657 DEFUN (debug_ospf6_brouter
,
1658 debug_ospf6_brouter_cmd
,
1659 "debug ospf6 border-routers",
1662 "Debug border router\n"
1665 OSPF6_DEBUG_BROUTER_ON();
1669 DEFUN (no_debug_ospf6_brouter
,
1670 no_debug_ospf6_brouter_cmd
,
1671 "no debug ospf6 border-routers",
1675 "Debug border router\n"
1678 OSPF6_DEBUG_BROUTER_OFF();
1682 DEFUN (debug_ospf6_brouter_router
,
1683 debug_ospf6_brouter_router_cmd
,
1684 "debug ospf6 border-routers router-id A.B.C.D",
1687 "Debug border router\n"
1688 "Debug specific border router\n"
1689 "Specify border-router's router-id\n"
1693 u_int32_t router_id
;
1694 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &router_id
);
1695 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id
);
1699 DEFUN (no_debug_ospf6_brouter_router
,
1700 no_debug_ospf6_brouter_router_cmd
,
1701 "no debug ospf6 border-routers router-id",
1705 "Debug border router\n"
1706 "Debug specific border router\n"
1709 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
1713 DEFUN (debug_ospf6_brouter_area
,
1714 debug_ospf6_brouter_area_cmd
,
1715 "debug ospf6 border-routers area-id A.B.C.D",
1718 "Debug border router\n"
1719 "Debug border routers in specific Area\n"
1725 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &area_id
);
1726 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id
);
1730 DEFUN (no_debug_ospf6_brouter_area
,
1731 no_debug_ospf6_brouter_area_cmd
,
1732 "no debug ospf6 border-routers area-id",
1736 "Debug border router\n"
1737 "Debug border routers in specific Area\n"
1740 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
1744 int config_write_ospf6_debug_brouter(struct vty
*vty
)
1747 if (IS_OSPF6_DEBUG_BROUTER
)
1748 vty_out(vty
, "debug ospf6 border-routers\n");
1749 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER
) {
1750 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_router_id
,
1752 vty_out(vty
, "debug ospf6 border-routers router-id %s\n", buf
);
1754 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA
) {
1755 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_area_id
,
1757 vty_out(vty
, "debug ospf6 border-routers area-id %s\n", buf
);
1762 void install_element_ospf6_debug_brouter(void)
1764 install_element(ENABLE_NODE
, &debug_ospf6_brouter_cmd
);
1765 install_element(ENABLE_NODE
, &debug_ospf6_brouter_router_cmd
);
1766 install_element(ENABLE_NODE
, &debug_ospf6_brouter_area_cmd
);
1767 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_cmd
);
1768 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_router_cmd
);
1769 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_area_cmd
);
1770 install_element(CONFIG_NODE
, &debug_ospf6_brouter_cmd
);
1771 install_element(CONFIG_NODE
, &debug_ospf6_brouter_router_cmd
);
1772 install_element(CONFIG_NODE
, &debug_ospf6_brouter_area_cmd
);
1773 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_cmd
);
1774 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_router_cmd
);
1775 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_area_cmd
);