2 * Copyright (C) 2002 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
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 static int intra_index
;
25 #define IS_OSPF6_DUMP_INTRA (ospf6_dump_is_on (intra_index))
31 ospf6_intra_route_calculate (int type
, struct ospf6_lsa
*lsa
,
32 struct ospf6_route_req
*topo_entry
)
34 struct ospf6_intra_area_prefix_lsa
*intra_prefix
;
36 struct ospf6_prefix
*ospf6_prefix
;
37 struct ospf6_route_req request
;
38 struct ospf6_area
*area
;
40 if (IS_OSPF6_DUMP_INTRA
)
43 struct prefix_ls
*p_ls
;
44 p_ls
= (struct prefix_ls
*) &topo_entry
->route
.prefix
;
45 inet_ntop (AF_INET
, &p_ls
->adv_router
, buf
, sizeof (buf
));
46 zlog_info ("INTRA: Calculate [%s] %s and %s",
47 (type
== ADD
? "add" : "remove"), lsa
->str
, buf
);
50 intra_prefix
= OSPF6_LSA_HEADER_END (lsa
->header
);
55 start
= (char *) (intra_prefix
+ 1);
56 end
= (char *) lsa
->header
+ ntohs (lsa
->header
->length
);
57 for (ospf6_prefix
= (struct ospf6_prefix
*) start
;
58 (char *) ospf6_prefix
< end
;
59 ospf6_prefix
= OSPF6_NEXT_PREFIX (ospf6_prefix
))
61 memset (&request
, 0, sizeof (request
));
63 request
.route
.type
= OSPF6_DEST_TYPE_NETWORK
;
64 request
.route
.prefix
.family
= AF_INET6
;
65 request
.route
.prefix
.prefixlen
= ospf6_prefix
->prefix_length
;
66 ospf6_prefix_in6_addr (ospf6_prefix
, &request
.route
.prefix
.u
.prefix6
);
68 request
.path
.type
= OSPF6_PATH_TYPE_INTRA
;
69 request
.path
.area_id
= area
->area_id
;
70 request
.path
.origin
.type
= lsa
->header
->type
;
71 request
.path
.origin
.id
= lsa
->header
->id
;
72 request
.path
.origin
.adv_router
= lsa
->header
->adv_router
;
73 request
.path
.cost
= topo_entry
->path
.cost
+
74 ntohs (ospf6_prefix
->prefix_metric
);
75 request
.path
.capability
[0] = topo_entry
->path
.capability
[0];
76 request
.path
.capability
[1] = topo_entry
->path
.capability
[1];
77 request
.path
.capability
[2] = topo_entry
->path
.capability
[2];
79 memcpy (&request
.nexthop
.address
, &topo_entry
->nexthop
.address
,
80 sizeof (request
.nexthop
.address
));
81 request
.nexthop
.ifindex
= topo_entry
->nexthop
.ifindex
;
84 ospf6_route_add (&request
, area
->route_table
);
85 else if (type
== REMOVE
)
86 ospf6_route_remove (&request
, area
->route_table
);
93 ospf6_intra_prefix_database_hook_remove (void *data
)
95 struct ospf6_lsa
*lsa
= data
;
96 struct ospf6_area
*area
;
97 struct ospf6_intra_area_prefix_lsa
*iap
;
98 struct prefix_ls prefix_ls
;
99 struct ospf6_route_req topo_entry
;
101 if (lsa
->header
->type
!= htons (OSPF6_LSA_TYPE_INTRA_PREFIX
))
104 area
= (struct ospf6_area
*) lsa
->scope
;
107 if (IS_OSPF6_DUMP_INTRA
)
108 zlog_info ("INTRA: area %s remove: %s", area
->str
, lsa
->str
);
110 iap
= OSPF6_LSA_HEADER_END (lsa
->header
);
111 memset (&prefix_ls
, 0, sizeof (prefix_ls
));
112 prefix_ls
.prefixlen
= 64;
113 prefix_ls
.adv_router
.s_addr
= iap
->refer_advrtr
;
114 prefix_ls
.id
.s_addr
= iap
->refer_lsid
;
116 if (iap
->refer_lstype
== htons (OSPF6_LSA_TYPE_ROUTER
) &&
117 iap
->refer_lsid
!= htonl (0))
119 zlog_warn ("SPF: Malformed ID %lu of Router reference in %s",
120 (u_long
) ntohl (iap
->refer_lsid
), lsa
->str
);
121 prefix_ls
.id
.s_addr
= htonl (0);
124 ospf6_route_lookup (&topo_entry
, (struct prefix
*) &prefix_ls
,
125 area
->table_topology
);
127 while (iap
->refer_lstype
== topo_entry
.path
.origin
.type
&&
128 iap
->refer_lsid
== topo_entry
.path
.origin
.id
&&
129 iap
->refer_advrtr
== topo_entry
.path
.origin
.adv_router
)
131 ospf6_intra_route_calculate (REMOVE
, lsa
, &topo_entry
);
132 ospf6_route_next (&topo_entry
);
138 ospf6_intra_prefix_database_hook_add (void *data
)
140 struct ospf6_lsa
*lsa
= data
;
141 struct ospf6_area
*area
;
142 struct ospf6_intra_area_prefix_lsa
*iap
;
143 struct prefix_ls prefix_ls
;
144 struct ospf6_route_req topo_entry
;
146 if (lsa
->header
->type
!= htons (OSPF6_LSA_TYPE_INTRA_PREFIX
))
149 area
= (struct ospf6_area
*) lsa
->scope
;
152 if (IS_LSA_MAXAGE (lsa
))
154 ospf6_intra_prefix_database_hook_remove (lsa
);
158 if (IS_OSPF6_DUMP_INTRA
)
159 zlog_info ("INTRA: area %s add: %s", area
->str
, lsa
->str
);
161 iap
= OSPF6_LSA_HEADER_END (lsa
->header
);
163 memset (&prefix_ls
, 0, sizeof (struct prefix_ls
));
164 prefix_ls
.prefixlen
= 64;
165 prefix_ls
.adv_router
.s_addr
= iap
->refer_advrtr
;
166 prefix_ls
.id
.s_addr
= iap
->refer_lsid
;
168 if (iap
->refer_lstype
== htons (OSPF6_LSA_TYPE_ROUTER
) &&
169 iap
->refer_lsid
!= htonl (0))
171 zlog_warn ("INTRA: Malformed ID %lu of Router reference in %s",
172 (u_long
) ntohl (iap
->refer_lsid
), lsa
->str
);
173 prefix_ls
.id
.s_addr
= htonl (0);
176 ospf6_route_lookup (&topo_entry
, (struct prefix
*) &prefix_ls
,
177 area
->table_topology
);
179 while (iap
->refer_lstype
== topo_entry
.path
.origin
.type
&&
180 iap
->refer_lsid
== topo_entry
.path
.origin
.id
&&
181 iap
->refer_advrtr
== topo_entry
.path
.origin
.adv_router
)
183 ospf6_intra_route_calculate (ADD
, lsa
, &topo_entry
);
184 ospf6_route_next (&topo_entry
);
190 ospf6_intra_topology_add (void *data
)
192 struct ospf6_route_req
*topo_entry
= data
;
193 struct ospf6_area
*area
;
194 struct ospf6_intra_area_prefix_lsa
*iap
;
195 struct ospf6_lsdb_node node
;
197 area
= ospf6_area_lookup (topo_entry
->path
.area_id
, ospf6
);
201 if (topo_entry
->route
.type
== OSPF6_DEST_TYPE_ROUTER
&&
202 (CHECK_FLAG (topo_entry
->path
.router_bits
, OSPF6_ROUTER_LSA_BIT_B
) ||
203 CHECK_FLAG (topo_entry
->path
.router_bits
, OSPF6_ROUTER_LSA_BIT_E
)))
204 ospf6_route_add (topo_entry
, ospf6
->topology_table
);
206 for (ospf6_lsdb_type (&node
, htons (OSPF6_LSA_TYPE_INTRA_PREFIX
),
208 ! ospf6_lsdb_is_end (&node
);
209 ospf6_lsdb_next (&node
))
211 if (IS_LSA_MAXAGE (node
.lsa
))
214 iap
= OSPF6_LSA_HEADER_END (node
.lsa
->header
);
216 if (iap
->refer_lstype
== htons (OSPF6_LSA_TYPE_ROUTER
) &&
217 iap
->refer_lsid
!= htonl (0))
219 zlog_warn ("INTRA: Malformed ID %lu of Router reference in %s",
220 (u_long
) ntohl (iap
->refer_lsid
), node
.lsa
->str
);
223 if (iap
->refer_lstype
!= topo_entry
->path
.origin
.type
||
224 iap
->refer_lsid
!= topo_entry
->path
.origin
.id
||
225 iap
->refer_advrtr
!= topo_entry
->path
.origin
.adv_router
)
228 ospf6_intra_route_calculate (ADD
, node
.lsa
, topo_entry
);
233 ospf6_intra_topology_remove (void *data
)
235 struct ospf6_route_req
*topo_entry
= data
;
236 struct ospf6_area
*area
;
237 struct ospf6_intra_area_prefix_lsa
*iap
;
238 struct ospf6_lsdb_node node
;
240 area
= ospf6_area_lookup (topo_entry
->path
.area_id
, ospf6
);
244 if (topo_entry
->route
.type
== OSPF6_DEST_TYPE_ROUTER
&&
245 (CHECK_FLAG (topo_entry
->path
.router_bits
, OSPF6_ROUTER_LSA_BIT_B
) ||
246 CHECK_FLAG (topo_entry
->path
.router_bits
, OSPF6_ROUTER_LSA_BIT_E
)))
247 ospf6_route_remove (topo_entry
, ospf6
->topology_table
);
249 for (ospf6_lsdb_type (&node
, htons (OSPF6_LSA_TYPE_INTRA_PREFIX
),
251 ! ospf6_lsdb_is_end (&node
);
252 ospf6_lsdb_next (&node
))
254 if (IS_LSA_MAXAGE (node
.lsa
))
257 iap
= OSPF6_LSA_HEADER_END (node
.lsa
->header
);
259 if (iap
->refer_lstype
== htons (OSPF6_LSA_TYPE_ROUTER
) &&
260 iap
->refer_lsid
!= htonl (0))
261 zlog_warn ("SPF: Malformed ID %lu of Router reference in %s",
262 (u_long
) ntohl (iap
->refer_lsid
), node
.lsa
->str
);
264 if (iap
->refer_lstype
!= topo_entry
->path
.origin
.type
||
265 iap
->refer_lsid
!= topo_entry
->path
.origin
.id
||
266 iap
->refer_advrtr
!= topo_entry
->path
.origin
.adv_router
)
269 ospf6_intra_route_calculate (REMOVE
, node
.lsa
, topo_entry
);
274 /*****************************************/
275 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
276 /*****************************************/
278 #define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\
279 if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6))\
282 prefix2str (addr, buf, sizeof (buf));\
283 if (IS_OSPF6_DUMP_PREFIX)\
284 zlog_info (" Filter out Linklocal: %s", buf);\
288 #define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr)\
289 if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6))\
292 prefix2str (addr, buf, sizeof (buf));\
293 if (IS_OSPF6_DUMP_PREFIX)\
294 zlog_info (" Filter out Unspecified: %s", buf);\
298 #define CONTINUE_IF_ADDRESS_LOOPBACK(addr)\
299 if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6))\
302 prefix2str (addr, buf, sizeof (buf));\
303 if (IS_OSPF6_DUMP_PREFIX)\
304 zlog_info (" Filter out Loopback: %s", buf);\
308 #define CONTINUE_IF_ADDRESS_V4COMPAT(addr)\
309 if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6))\
312 prefix2str (addr, buf, sizeof (buf));\
313 if (IS_OSPF6_DUMP_PREFIX)\
314 zlog_info (" Filter out V4Compat: %s", buf);\
318 #define CONTINUE_IF_ADDRESS_V4MAPPED(addr)\
319 if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6))\
322 prefix2str (addr, buf, sizeof (buf));\
323 if (IS_OSPF6_DUMP_PREFIX)\
324 zlog_info (" Filter out V4Mapped: %s", buf);\
330 ospf6_lsa_intra_prefix_show (struct vty
*vty
, struct ospf6_lsa
*lsa
)
332 struct ospf6_intra_area_prefix_lsa
*iap_lsa
;
333 struct ospf6_prefix
*prefix
;
334 unsigned short prefixnum
;
335 char buf
[128], type
[32], id
[32], adv_router
[32];
337 char *start
, *end
, *current
;
339 assert (lsa
->header
);
340 iap_lsa
= (struct ospf6_intra_area_prefix_lsa
*) (lsa
->header
+ 1);
342 prefixnum
= ntohs (iap_lsa
->prefix_number
);
343 ospf6_lsa_type_string (iap_lsa
->refer_lstype
, type
, sizeof (type
));
344 inet_ntop (AF_INET
, &iap_lsa
->refer_lsid
, id
, sizeof (id
));
345 inet_ntop (AF_INET
, &iap_lsa
->refer_advrtr
, adv_router
,
346 sizeof (adv_router
));
348 vty_out (vty
, " Number of Prefix: %d%s", prefixnum
, VTY_NEWLINE
);
349 vty_out (vty
, " Referenced LS Type: %s%s", type
, VTY_NEWLINE
);
350 vty_out (vty
, " Referenced LS ID: %s%s", id
, VTY_NEWLINE
);
351 vty_out (vty
, " Referenced Advertising Router: %s%s", adv_router
,
354 start
= (char *) lsa
->header
+ sizeof (struct ospf6_lsa_header
)
355 + sizeof (struct ospf6_intra_area_prefix_lsa
);
356 end
= (char *) lsa
->header
+ ntohs (lsa
->header
->length
);
358 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE (prefix
))
360 prefix
= (struct ospf6_prefix
*) current
;
361 if (current
+ OSPF6_PREFIX_SIZE (prefix
) > end
)
363 vty_out (vty
, " Trailing %d byte garbage ... Malformed%s",
364 end
- current
, VTY_NEWLINE
);
368 ospf6_prefix_options_str (prefix
->prefix_options
, buf
, sizeof (buf
));
369 vty_out (vty
, " Prefix Options: %s%s", buf
, VTY_NEWLINE
);
371 ospf6_prefix_in6_addr (prefix
, &in6
);
372 inet_ntop (AF_INET6
, &in6
, buf
, sizeof (buf
));
373 vty_out (vty
, " Prefix: %s/%d%s",
374 buf
, prefix
->prefix_length
, VTY_NEWLINE
);
381 ospf6_lsa_intra_prefix_update_transit (char *ifname
)
383 char buffer
[MAXLSASIZE
];
385 struct ospf6_lsa
*old
;
386 struct interface
*ifp
;
387 struct ospf6_interface
*o6i
;
388 struct ospf6_neighbor
*o6n
;
390 struct ospf6_intra_area_prefix_lsa
*iap
;
391 struct ospf6_lsdb_node n
;
393 char *start
, *end
, *current
;
394 struct ospf6_prefix
*prefix
, *dup
, *src
, *dst
;
395 struct ospf6_link_lsa
*link
;
397 int count
, prefix_num
;
401 ifp
= if_lookup_by_name (ifname
);
404 zlog_warn ("Update Intra-Prefix (Transit): No such Interface: %s",
409 o6i
= (struct ospf6_interface
*) ifp
->info
;
410 if (! o6i
|| ! o6i
->area
)
412 zlog_warn ("Update Intra-Prefix (Transit): Interface not enabled: %s",
417 /* find previous LSA */
418 old
= ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX
),
419 htonl (o6i
->if_id
), ospf6
->router_id
,
422 /* Don't originate Network-LSA if not DR */
423 if (o6i
->state
!= IFS_DR
)
427 if (IS_OSPF6_DUMP_PREFIX
)
428 zlog_info ("Update Intra-Prefix (Transit): %s not DR",
429 o6i
->interface
->name
);
430 ospf6_lsa_premature_aging (old
);
435 /* If none of neighbor is adjacent to us */
437 o6i
->foreach_nei (o6i
, &count
, NBS_FULL
, ospf6_count_state
);
440 if (IS_OSPF6_DUMP_PREFIX
)
441 zlog_info ("Update Intra-Prefix (Transit): %s is Stub",
442 o6i
->interface
->name
);
444 ospf6_lsa_premature_aging (old
);
448 if (IS_OSPF6_DUMP_PREFIX
)
449 zlog_info ("Update Intra-Prefix (Transit): Interface %s",
450 o6i
->interface
->name
);
452 adv_list
= list_new ();
454 /* foreach Link-LSA associated with this Link */
455 for (ospf6_lsdb_type (&n
, htons (OSPF6_LSA_TYPE_LINK
), o6i
->lsdb
);
456 ! ospf6_lsdb_is_end (&n
); ospf6_lsdb_next (&n
))
458 if (IS_LSA_MAXAGE (n
.lsa
))
461 if (IS_OSPF6_DUMP_PREFIX
)
462 zlog_info ("Update Intra-Prefix (Transit): Checking %s",
465 /* Check status of the advertising router */
466 if (n
.lsa
->header
->adv_router
!= o6i
->area
->ospf6
->router_id
)
468 o6n
= ospf6_neighbor_lookup (n
.lsa
->header
->adv_router
, o6i
);
471 if (IS_OSPF6_DUMP_PREFIX
)
472 zlog_info ("Update Intra-Prefix (Transit): neighbor not found");
476 if (o6n
->state
!= NBS_FULL
)
478 if (IS_OSPF6_DUMP_PREFIX
)
479 zlog_info ("Update Intra-Prefix (Transit): %s not FULL",
485 /* For each Prefix in this Link-LSA */
486 link
= (struct ospf6_link_lsa
*) (n
.lsa
->header
+ 1);
487 prefix_num
= ntohl (link
->llsa_prefix_num
);
489 if (IS_OSPF6_DUMP_PREFIX
)
490 zlog_info (" Prefix #%d", prefix_num
);
492 start
= (char *) (link
+ 1);
493 end
= (char *) (n
.lsa
->header
) + ntohs (n
.lsa
->header
->length
);
494 prefix
= (struct ospf6_prefix
*) start
;
495 for (current
= start
; current
< end
;
496 current
+= OSPF6_PREFIX_SIZE (prefix
))
498 prefix
= (struct ospf6_prefix
*) current
;
499 ospf6_prefix_string (prefix
, buf
, sizeof (buf
));
501 /* Check duplicate prefix */
502 dup
= ospf6_prefix_lookup (adv_list
, prefix
);
505 if (IS_OSPF6_DUMP_PREFIX
)
506 zlog_info (" Duplicate %s", buf
);
507 dup
->prefix_options
|= prefix
->prefix_options
;
513 zlog_warn (" Wong prefix number ...");
517 if (IS_OSPF6_DUMP_PREFIX
)
518 zlog_info (" Prefix %s", buf
);
520 /* copy prefix to advertise list */
521 ospf6_prefix_add (adv_list
, prefix
);
527 /* if no prefix to advertise, return */
528 if (listcount (adv_list
) == 0)
530 if (IS_OSPF6_DUMP_PREFIX
)
531 zlog_info (" No Prefix to advertise");
533 ospf6_lsa_premature_aging (old
);
538 memset (buffer
, 0, sizeof (buffer
));
539 size
= sizeof (struct ospf6_intra_area_prefix_lsa
);
540 iap
= (struct ospf6_intra_area_prefix_lsa
*) buffer
;
542 /* Set Referenced LSA field */
543 iap
->refer_lstype
= htons (OSPF6_LSA_TYPE_NETWORK
);
544 iap
->refer_lsid
= htonl (o6i
->if_id
);
545 iap
->refer_advrtr
= o6i
->area
->ospf6
->router_id
;
547 dst
= (struct ospf6_prefix
*) (iap
+ 1);
548 for (node
= listhead (adv_list
); node
; nextnode (node
))
550 src
= (struct ospf6_prefix
*) getdata (node
);
552 memcpy (dst
, src
, OSPF6_PREFIX_SIZE (src
));
554 size
+= OSPF6_PREFIX_SIZE (dst
);
555 dst
= OSPF6_NEXT_PREFIX (dst
);
557 iap
->prefix_number
= htons (listcount (adv_list
));
559 while ((node
= listhead (adv_list
)) != NULL
)
561 prefix
= getdata (node
);
562 ospf6_prefix_delete (prefix
);
563 listnode_delete (adv_list
, prefix
);
565 list_delete (adv_list
);
567 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX
),
568 htonl (o6i
->if_id
), ospf6
->router_id
,
569 buffer
, size
, o6i
->area
);
573 ospf6_lsa_intra_prefix_update_stub (u_int32_t area_id
)
575 char buffer
[MAXLSASIZE
];
577 struct ospf6_lsa
*old
;
578 struct ospf6_area
*o6a
;
581 struct ospf6_intra_area_prefix_lsa
*iap
;
583 struct ospf6_interface
*o6i
= NULL
;
584 struct ospf6_prefix
*prefix
, *dst
, *src
;
590 char prefix_buf
[sizeof (struct ospf6_prefix
) + sizeof (struct in6_addr
)];
592 o6a
= ospf6_area_lookup (area_id
, ospf6
);
596 inet_ntop (AF_INET
, &area_id
, tmp
, sizeof (tmp
));
597 zlog_warn ("Update Intra-Prefix (Stub): No such area: %s", tmp
);
600 else if (IS_OSPF6_DUMP_PREFIX
)
602 zlog_info ("Update Intra-Prefix (Stub): area: %s", o6a
->str
);
605 /* find previous LSA */
606 old
= ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX
),
607 htonl (0), ospf6
->router_id
,
608 o6a
); /* xxx, ls-id */
610 adv_list
= list_new ();
612 /* Examin for each interface */
613 for (i
= listhead (o6a
->if_list
); i
; nextnode (i
))
615 o6i
= (struct ospf6_interface
*) getdata (i
);
617 if (o6i
->state
== IFS_DOWN
)
619 if (IS_OSPF6_DUMP_PREFIX
)
620 zlog_info (" Interface %s: down", o6i
->interface
->name
);
625 o6i
->foreach_nei (o6i
, &count
, NBS_FULL
, ospf6_count_state
);
626 if (o6i
->state
!= IFS_LOOPBACK
&& o6i
->state
!= IFS_PTOP
&&
629 /* This interface's prefix will be included in DR's */
630 if (IS_OSPF6_DUMP_PREFIX
)
631 zlog_info (" Interface %s: not stub", o6i
->interface
->name
);
635 if (IS_OSPF6_DUMP_PREFIX
)
636 zlog_info (" Interface %s:", o6i
->interface
->name
);
638 /* copy foreach address prefix */
639 for (j
= listhead (o6i
->interface
->connected
); j
; nextnode (j
))
641 c
= (struct connected
*) getdata (j
);
643 /* filter prefix not IPv6 */
644 if (c
->address
->family
!= AF_INET6
)
648 prefix2str (c
->address
, buf
, sizeof (buf
));
650 CONTINUE_IF_ADDRESS_LINKLOCAL (c
->address
);
651 CONTINUE_IF_ADDRESS_UNSPECIFIED (c
->address
);
652 CONTINUE_IF_ADDRESS_LOOPBACK (c
->address
);
653 CONTINUE_IF_ADDRESS_V4COMPAT (c
->address
);
654 CONTINUE_IF_ADDRESS_V4MAPPED (c
->address
);
656 /* filter prefix specified by configuration */
659 struct prefix_list
*plist
;
660 enum prefix_list_type result
= PREFIX_PERMIT
;
662 plist
= prefix_list_lookup (AFI_IP6
, o6i
->plist_name
);
664 result
= prefix_list_apply (plist
, c
->address
);
666 zlog_warn ("Update Intra-Prefix (Stub): "
667 "Prefix list \"%s\" not found",
670 if (result
== PREFIX_DENY
)
672 if (IS_OSPF6_DUMP_PREFIX
)
673 zlog_info (" %s: Filtered by %s",
674 buf
, o6i
->plist_name
);
679 /* initialize buffer for ospf6 prefix */
680 memset (prefix_buf
, 0, sizeof (prefix_buf
));
681 prefix
= (struct ospf6_prefix
*) prefix_buf
;
683 /* set ospf6 prefix according to its state */
684 /* xxx, virtual links */
685 if (! CHECK_FLAG (o6i
->flag
, OSPF6_INTERFACE_FLAG_FORCE_PREFIX
) &&
686 (o6i
->state
== IFS_LOOPBACK
|| o6i
->state
== IFS_PTOP
687 /* xxx, PoinToMultiPoint I/F type */ ))
689 prefix
->prefix_length
= 128;
690 prefix
->prefix_options
= OSPF6_PREFIX_OPTION_LA
;
691 prefix
->prefix_metric
= htons (0);
692 memcpy (prefix
+ 1, &c
->address
->u
.prefix6
,
693 OSPF6_PREFIX_SPACE (prefix
->prefix_length
));
697 struct prefix_ipv6 prefix_ipv6
;
699 prefix_copy ((struct prefix
*) &prefix_ipv6
, c
->address
);
700 apply_mask_ipv6 (&prefix_ipv6
);
702 prefix
->prefix_length
= prefix_ipv6
.prefixlen
;
703 prefix
->prefix_options
= 0; /* xxx, no options yet */
704 prefix
->prefix_metric
= htons (o6i
->cost
);
705 memcpy (prefix
+ 1, &prefix_ipv6
.prefix
,
706 OSPF6_PREFIX_SPACE (prefix
->prefix_length
));
709 ospf6_prefix_string (prefix
, buf
, sizeof (buf
));
710 if (IS_OSPF6_DUMP_PREFIX
)
711 zlog_info (" Advertise %s", buf
);
713 /* check in the prefix to advertising prefix list */
714 ospf6_prefix_add (adv_list
, prefix
);
718 /* If no prefix to advertise */
719 if (listcount (adv_list
) == 0)
721 if (IS_OSPF6_DUMP_PREFIX
)
722 zlog_info (" No prefix to advertise");
724 ospf6_lsa_premature_aging (old
);
729 memset (buffer
, 0, sizeof (buffer
));
730 size
= sizeof (struct ospf6_intra_area_prefix_lsa
);
731 iap
= (struct ospf6_intra_area_prefix_lsa
*) buffer
;
733 /* Set Referenced LSA field */
734 iap
->refer_lstype
= htons (OSPF6_LSA_TYPE_ROUTER
);
735 iap
->refer_lsid
= htonl (0);
736 iap
->refer_advrtr
= o6a
->ospf6
->router_id
;
738 dst
= (struct ospf6_prefix
*) (iap
+ 1);
739 for (node
= listhead (adv_list
); node
; nextnode (node
))
741 src
= (struct ospf6_prefix
*) getdata (node
);
743 memcpy (dst
, src
, OSPF6_PREFIX_SIZE (src
));
745 size
+= OSPF6_PREFIX_SIZE (dst
);
746 dst
= OSPF6_NEXT_PREFIX (dst
);
748 iap
->prefix_number
= htons (listcount (adv_list
));
750 while ((node
= listhead (adv_list
)) != NULL
)
752 prefix
= getdata (node
);
753 ospf6_prefix_delete (prefix
);
754 listnode_delete (adv_list
, prefix
);
756 list_delete (adv_list
);
758 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX
),
759 htonl (0) /* xxx */, ospf6
->router_id
,
764 ospf6_lsa_intra_prefix_hook_interface (void *interface
)
766 struct ospf6_interface
*o6i
= interface
;
769 ospf6_lsa_intra_prefix_update_transit (o6i
->interface
->name
);
770 ospf6_lsa_intra_prefix_update_stub (o6i
->area
->area_id
);
776 ospf6_lsa_intra_prefix_hook_neighbor (void *neighbor
)
778 struct ospf6_neighbor
*o6n
= neighbor
;
779 if (o6n
->ospf6_interface
->area
)
781 ospf6_lsa_intra_prefix_update_transit (o6n
->ospf6_interface
->interface
->name
);
782 ospf6_lsa_intra_prefix_update_stub (o6n
->ospf6_interface
->area
->area_id
);
788 ospf6_intra_prefix_link_database_hook (void *new)
790 struct ospf6_lsa
*lsa
= new;
791 struct ospf6_interface
*o6i
;
793 if (lsa
->header
->type
!= htons (OSPF6_LSA_TYPE_LINK
))
797 if (o6i
->state
!= IFS_DR
)
800 ospf6_lsa_intra_prefix_update_transit (o6i
->interface
->name
);
801 ospf6_lsa_intra_prefix_update_stub (o6i
->area
->area_id
);
806 ospf6_lsa_intra_prefix_refresh (void *old
)
808 struct ospf6_lsa
*lsa
= old
;
809 struct ospf6_interface
*o6i
;
810 struct ospf6_area
*o6a
;
813 id
= ntohl (lsa
->header
->id
);
816 o6i
= ospf6_interface_lookup_by_index (id
);
818 ospf6_lsa_intra_prefix_update_transit (o6i
->interface
->name
);
820 ospf6_lsa_premature_aging (lsa
);
825 ospf6_lsa_intra_prefix_update_stub (o6a
->area_id
);
832 ospf6_intra_prefix_register ()
834 struct ospf6_lsa_slot slot
, *sp
;
835 struct ospf6_hook hook
;
837 memset (&slot
, 0, sizeof (struct ospf6_lsa_slot
));
838 slot
.type
= htons (OSPF6_LSA_TYPE_INTRA_PREFIX
);
839 slot
.name
= "Intra-Prefix";
840 slot
.func_show
= ospf6_lsa_intra_prefix_show
;
841 slot
.func_refresh
= ospf6_lsa_intra_prefix_refresh
;
842 ospf6_lsa_slot_register (&slot
);
844 memset (&hook
, 0, sizeof (hook
));
845 hook
.name
= "OriginateIntraPrefix";
846 hook
.hook_add
= ospf6_lsa_intra_prefix_hook_interface
;
847 hook
.hook_change
= ospf6_lsa_intra_prefix_hook_interface
;
848 hook
.hook_remove
= NULL
; /* XXX */
849 ospf6_hook_register (&hook
, &interface_hook
);
851 memset (&hook
, 0, sizeof (hook
));
852 hook
.name
= "OriginateIntraPrefix";
853 hook
.hook_add
= ospf6_lsa_intra_prefix_hook_neighbor
;
854 hook
.hook_change
= ospf6_lsa_intra_prefix_hook_neighbor
;
855 hook
.hook_remove
= ospf6_lsa_intra_prefix_hook_neighbor
;
856 ospf6_hook_register (&hook
, &neighbor_hook
);
858 sp
= ospf6_lsa_slot_get (htons (OSPF6_LSA_TYPE_INTRA_PREFIX
));
859 hook
.name
= "CalculateIntraPrefix";
860 hook
.hook_add
= ospf6_intra_prefix_database_hook_add
;
861 hook
.hook_change
= ospf6_intra_prefix_database_hook_add
;
862 hook
.hook_remove
= ospf6_intra_prefix_database_hook_remove
;
863 ospf6_hook_register (&hook
, &sp
->database_hook
);
867 ospf6_intra_database_hook_intra_prefix (struct ospf6_lsa
*old
,
868 struct ospf6_lsa
*new)
871 ospf6_intra_prefix_database_hook_remove (old
);
872 if (new && ! IS_LSA_MAXAGE (new))
873 ospf6_intra_prefix_database_hook_add (new);
877 ospf6_intra_database_hook_link (struct ospf6_lsa
*old
,
878 struct ospf6_lsa
*new)
880 ospf6_intra_prefix_link_database_hook (new);
881 ospf6_spf_database_hook (old
, new);
887 ospf6_lsdb_hook
[OSPF6_LSA_TYPE_INTRA_PREFIX
& OSPF6_LSTYPE_CODE_MASK
].hook
=
888 ospf6_intra_database_hook_intra_prefix
;
889 ospf6_lsdb_hook
[OSPF6_LSA_TYPE_LINK
& OSPF6_LSTYPE_CODE_MASK
].hook
=
890 ospf6_intra_database_hook_link
;
892 intra_index
= ospf6_dump_install ("intra-area", "Intra-area calculation\n");
893 ospf6_intra_prefix_register ();