blob: fe1f45db58b487d936a5442d45e7fa8e707446f2 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Zebra connect library for OSPFd
3 * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "thread.h"
26#include "command.h"
27#include "network.h"
28#include "prefix.h"
29#include "routemap.h"
30#include "table.h"
31#include "stream.h"
32#include "memory.h"
33#include "zclient.h"
34#include "filter.h"
hassodd669bb2004-05-10 07:43:59 +000035#include "plist.h"
paul718e3742002-12-13 20:15:29 +000036#include "log.h"
37
38#include "ospfd/ospfd.h"
39#include "ospfd/ospf_interface.h"
40#include "ospfd/ospf_ism.h"
41#include "ospfd/ospf_asbr.h"
42#include "ospfd/ospf_asbr.h"
43#include "ospfd/ospf_abr.h"
44#include "ospfd/ospf_lsa.h"
45#include "ospfd/ospf_dump.h"
46#include "ospfd/ospf_route.h"
47#include "ospfd/ospf_zebra.h"
48#ifdef HAVE_SNMP
49#include "ospfd/ospf_snmp.h"
50#endif /* HAVE_SNMP */
51
52/* Zebra structure to hold current status. */
53struct zclient *zclient = NULL;
54
55/* For registering threads. */
56extern struct thread_master *master;
hasso18a6dce2004-10-03 18:18:34 +000057struct in_addr router_id_zebra;
58
59/* Router-id update message from zebra. */
paul4dadc292005-05-06 21:37:42 +000060static int
hasso18a6dce2004-10-03 18:18:34 +000061ospf_router_id_update_zebra (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +080062 zebra_size_t length, vrf_id_t vrf_id)
hasso18a6dce2004-10-03 18:18:34 +000063{
64 struct ospf *ospf;
65 struct prefix router_id;
66 zebra_router_id_update_read(zclient->ibuf,&router_id);
67
Andrew J. Schorr7f643eb2006-11-30 16:17:02 +000068 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
69 {
70 char buf[128];
71 prefix2str(&router_id, buf, sizeof(buf));
72 zlog_debug("Zebra rcvd: router id update %s", buf);
73 }
74
hasso18a6dce2004-10-03 18:18:34 +000075 router_id_zebra = router_id.u.prefix4;
76
77 ospf = ospf_lookup ();
paulb29800a2005-11-20 14:50:45 +000078
hasso18a6dce2004-10-03 18:18:34 +000079 if (ospf != NULL)
paulb29800a2005-11-20 14:50:45 +000080 ospf_router_id_update (ospf);
81
hasso18a6dce2004-10-03 18:18:34 +000082 return 0;
83}
paul718e3742002-12-13 20:15:29 +000084
85/* Inteface addition message from zebra. */
paul4dadc292005-05-06 21:37:42 +000086static int
Feng Luc99f3482014-10-16 09:52:36 +080087ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length,
88 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000089{
90 struct interface *ifp;
91
Feng Luc99f3482014-10-16 09:52:36 +080092 ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +000093
94 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
Stephen Hemminger30d20592009-07-28 11:58:51 +010095 zlog_debug ("Zebra: interface add %s index %d flags %llx metric %d mtu %d",
96 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
97 ifp->metric, ifp->mtu);
paul718e3742002-12-13 20:15:29 +000098
paulcf795c52003-06-19 02:13:25 +000099 assert (ifp->info);
paulf2c80652002-12-13 21:44:27 +0000100
paul718e3742002-12-13 20:15:29 +0000101 if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
102 {
103 SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
ajsbc18d612004-12-15 15:07:19 +0000104 IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp);
paul718e3742002-12-13 20:15:29 +0000105 }
106
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100107 ospf_if_update (NULL, ifp);
paul718e3742002-12-13 20:15:29 +0000108
109#ifdef HAVE_SNMP
110 ospf_snmp_if_update (ifp);
111#endif /* HAVE_SNMP */
112
113 return 0;
114}
115
paul4dadc292005-05-06 21:37:42 +0000116static int
paul718e3742002-12-13 20:15:29 +0000117ospf_interface_delete (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800118 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000119{
120 struct interface *ifp;
121 struct stream *s;
122 struct route_node *rn;
123
paulcf795c52003-06-19 02:13:25 +0000124 s = zclient->ibuf;
paul718e3742002-12-13 20:15:29 +0000125 /* zebra_interface_state_read() updates interface structure in iflist */
Feng Luc99f3482014-10-16 09:52:36 +0800126 ifp = zebra_interface_state_read (s, vrf_id);
paul718e3742002-12-13 20:15:29 +0000127
128 if (ifp == NULL)
129 return 0;
130
131 if (if_is_up (ifp))
132 zlog_warn ("Zebra: got delete of %s, but interface is still up",
paulcf795c52003-06-19 02:13:25 +0000133 ifp->name);
134
paul718e3742002-12-13 20:15:29 +0000135 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000136 zlog_debug
Andrew Certain0798cee2012-12-04 13:43:42 -0800137 ("Zebra: interface delete %s index %d flags %llx metric %d mtu %d",
138 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
paul718e3742002-12-13 20:15:29 +0000139
140#ifdef HAVE_SNMP
141 ospf_snmp_if_delete (ifp);
142#endif /* HAVE_SNMP */
143
144 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
145 if (rn->info)
146 ospf_if_free ((struct ospf_interface *) rn->info);
147
ajsd2fc8892005-04-02 18:38:43 +0000148 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000149 return 0;
150}
151
ajsd2fc8892005-04-02 18:38:43 +0000152static struct interface *
Feng Luc99f3482014-10-16 09:52:36 +0800153zebra_interface_if_lookup (struct stream *s, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000154{
ajs21fefa92005-04-02 23:16:41 +0000155 char ifname_tmp[INTERFACE_NAMSIZ];
paul718e3742002-12-13 20:15:29 +0000156
157 /* Read interface name. */
158 stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
159
ajsd2fc8892005-04-02 18:38:43 +0000160 /* And look it up. */
ajs21fefa92005-04-02 23:16:41 +0000161 return if_lookup_by_name_len(ifname_tmp,
162 strnlen(ifname_tmp, INTERFACE_NAMSIZ));
paul718e3742002-12-13 20:15:29 +0000163}
164
paul4dadc292005-05-06 21:37:42 +0000165static int
paul718e3742002-12-13 20:15:29 +0000166ospf_interface_state_up (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800167 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000168{
169 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +0000170 struct ospf_interface *oi;
171 struct route_node *rn;
paulcf795c52003-06-19 02:13:25 +0000172
Feng Luc99f3482014-10-16 09:52:36 +0800173 ifp = zebra_interface_if_lookup (zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000174
175 if (ifp == NULL)
176 return 0;
177
178 /* Interface is already up. */
paul2e3b2e42002-12-13 21:03:13 +0000179 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000180 {
181 /* Temporarily keep ifp values. */
ajsa608bbf2005-03-29 17:03:49 +0000182 struct interface if_tmp;
paul718e3742002-12-13 20:15:29 +0000183 memcpy (&if_tmp, ifp, sizeof (struct interface));
184
185 zebra_interface_if_set_value (zclient->ibuf, ifp);
186
187 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000188 zlog_debug ("Zebra: Interface[%s] state update.", ifp->name);
paul718e3742002-12-13 20:15:29 +0000189
190 if (if_tmp.bandwidth != ifp->bandwidth)
paulcf795c52003-06-19 02:13:25 +0000191 {
192 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000193 zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.",
paulcf795c52003-06-19 02:13:25 +0000194 ifp->name, if_tmp.bandwidth, ifp->bandwidth);
paul718e3742002-12-13 20:15:29 +0000195
paulcf795c52003-06-19 02:13:25 +0000196 ospf_if_recalculate_output_cost (ifp);
197 }
ajsa608bbf2005-03-29 17:03:49 +0000198
199 if (if_tmp.mtu != ifp->mtu)
200 {
201 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
202 zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.",
203 ifp->name, if_tmp.mtu, ifp->mtu);
204
205 /* Must reset the interface (simulate down/up) when MTU changes. */
206 ospf_if_reset(ifp);
207 }
paul718e3742002-12-13 20:15:29 +0000208 return 0;
209 }
paulcf795c52003-06-19 02:13:25 +0000210
paul718e3742002-12-13 20:15:29 +0000211 zebra_interface_if_set_value (zclient->ibuf, ifp);
paulcf795c52003-06-19 02:13:25 +0000212
paul718e3742002-12-13 20:15:29 +0000213 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000214 zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name);
paulcf795c52003-06-19 02:13:25 +0000215
216 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000217 {
paulcf795c52003-06-19 02:13:25 +0000218 if ((oi = rn->info) == NULL)
219 continue;
220
paul718e3742002-12-13 20:15:29 +0000221 ospf_if_up (oi);
222 }
paulcf795c52003-06-19 02:13:25 +0000223
paul718e3742002-12-13 20:15:29 +0000224 return 0;
225}
226
paul4dadc292005-05-06 21:37:42 +0000227static int
paul718e3742002-12-13 20:15:29 +0000228ospf_interface_state_down (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800229 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000230{
231 struct interface *ifp;
232 struct ospf_interface *oi;
233 struct route_node *node;
234
Feng Luc99f3482014-10-16 09:52:36 +0800235 ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000236
237 if (ifp == NULL)
238 return 0;
239
240 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000241 zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name);
paul718e3742002-12-13 20:15:29 +0000242
paulcf795c52003-06-19 02:13:25 +0000243 for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
paul718e3742002-12-13 20:15:29 +0000244 {
paulcf795c52003-06-19 02:13:25 +0000245 if ((oi = node->info) == NULL)
246 continue;
paul718e3742002-12-13 20:15:29 +0000247 ospf_if_down (oi);
248 }
249
250 return 0;
251}
252
paul4dadc292005-05-06 21:37:42 +0000253static int
paul718e3742002-12-13 20:15:29 +0000254ospf_interface_address_add (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800255 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000256{
257 struct connected *c;
258
Feng Luc99f3482014-10-16 09:52:36 +0800259 c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000260
261 if (c == NULL)
262 return 0;
263
Andrew J. Schorr7f643eb2006-11-30 16:17:02 +0000264 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
265 {
266 char buf[128];
267 prefix2str(c->address, buf, sizeof(buf));
268 zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
269 }
270
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100271 ospf_if_update (NULL, c->ifp);
paul718e3742002-12-13 20:15:29 +0000272
273#ifdef HAVE_SNMP
274 ospf_snmp_if_update (c->ifp);
275#endif /* HAVE_SNMP */
276
277 return 0;
278}
279
paul4dadc292005-05-06 21:37:42 +0000280static int
paul718e3742002-12-13 20:15:29 +0000281ospf_interface_address_delete (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800282 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000283{
284 struct connected *c;
285 struct interface *ifp;
286 struct ospf_interface *oi;
287 struct route_node *rn;
288 struct prefix p;
289
Feng Luc99f3482014-10-16 09:52:36 +0800290 c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000291
292 if (c == NULL)
293 return 0;
294
Andrew J. Schorr7f643eb2006-11-30 16:17:02 +0000295 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
296 {
297 char buf[128];
298 prefix2str(c->address, buf, sizeof(buf));
299 zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf);
300 }
301
paul718e3742002-12-13 20:15:29 +0000302 ifp = c->ifp;
303 p = *c->address;
304 p.prefixlen = IPV4_MAX_PREFIXLEN;
305
306 rn = route_node_lookup (IF_OIFS (ifp), &p);
paulcf795c52003-06-19 02:13:25 +0000307 if (!rn)
paul98429f62006-01-10 22:11:54 +0000308 {
309 connected_free (c);
310 return 0;
311 }
paul718e3742002-12-13 20:15:29 +0000312
313 assert (rn->info);
314 oi = rn->info;
paulcf795c52003-06-19 02:13:25 +0000315
paul718e3742002-12-13 20:15:29 +0000316 /* Call interface hook functions to clean up */
317 ospf_if_free (oi);
paulcf795c52003-06-19 02:13:25 +0000318
paul718e3742002-12-13 20:15:29 +0000319#ifdef HAVE_SNMP
320 ospf_snmp_if_update (c->ifp);
321#endif /* HAVE_SNMP */
322
323 connected_free (c);
324
paul718e3742002-12-13 20:15:29 +0000325 return 0;
326}
paul72357f22003-06-19 02:11:23 +0000327
paul718e3742002-12-13 20:15:29 +0000328void
329ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
330{
331 u_char message;
332 u_char distance;
333 u_char flags;
334 int psize;
335 struct stream *s;
336 struct ospf_path *path;
hasso52dc7ee2004-09-23 19:18:23 +0000337 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000338
Feng Luc99f3482014-10-16 09:52:36 +0800339 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000340 {
341 message = 0;
342 flags = 0;
343
344 /* OSPF pass nexthop and metric */
345 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
346 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
347
348 /* Distance value. */
349 distance = ospf_distance_apply (p, or);
350 if (distance)
paul72357f22003-06-19 02:11:23 +0000351 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
paul718e3742002-12-13 20:15:29 +0000352
353 /* Make packet. */
354 s = zclient->obuf;
355 stream_reset (s);
356
paul718e3742002-12-13 20:15:29 +0000357 /* Put command, type, flags, message. */
Feng Luc99f3482014-10-16 09:52:36 +0800358 zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000359 stream_putc (s, ZEBRA_ROUTE_OSPF);
360 stream_putc (s, flags);
361 stream_putc (s, message);
Denis Ovsienkob4e45f62011-12-05 16:35:14 +0400362 stream_putw (s, SAFI_UNICAST);
paulcf795c52003-06-19 02:13:25 +0000363
paul718e3742002-12-13 20:15:29 +0000364 /* Put prefix information. */
365 psize = PSIZE (p->prefixlen);
366 stream_putc (s, p->prefixlen);
paulcf795c52003-06-19 02:13:25 +0000367 stream_write (s, (u_char *) & p->prefix, psize);
paul718e3742002-12-13 20:15:29 +0000368
369 /* Nexthop count. */
paul96735ee2003-08-10 02:51:22 +0000370 stream_putc (s, or->paths->count);
paul718e3742002-12-13 20:15:29 +0000371
372 /* Nexthop, ifindex, distance and metric information. */
paul1eb8ef22005-04-07 07:30:20 +0000373 for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
paul72357f22003-06-19 02:11:23 +0000374 {
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200375 if (path->nexthop.s_addr != INADDR_ANY &&
376 path->ifindex != 0)
377 {
378 stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
379 stream_put_in_addr (s, &path->nexthop);
380 stream_putl (s, path->ifindex);
381 }
382 else if (path->nexthop.s_addr != INADDR_ANY)
paulcf795c52003-06-19 02:13:25 +0000383 {
384 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
385 stream_put_in_addr (s, &path->nexthop);
386 }
387 else
388 {
389 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200390 if (path->ifindex)
391 stream_putl (s, path->ifindex);
paulcf795c52003-06-19 02:13:25 +0000392 else
393 stream_putl (s, 0);
394 }
paul72357f22003-06-19 02:11:23 +0000395
396 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
397 {
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000398 char buf[2][INET_ADDRSTRLEN];
399 zlog_debug("Zebra: Route add %s/%d nexthop %s",
400 inet_ntop(AF_INET, &p->prefix,
401 buf[0], sizeof(buf[0])),
402 p->prefixlen,
403 inet_ntop(AF_INET, &path->nexthop,
404 buf[1], sizeof(buf[1])));
paulcf795c52003-06-19 02:13:25 +0000405 }
406 }
paul718e3742002-12-13 20:15:29 +0000407
408 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
paulcf795c52003-06-19 02:13:25 +0000409 stream_putc (s, distance);
paul718e3742002-12-13 20:15:29 +0000410 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
paulcf795c52003-06-19 02:13:25 +0000411 {
412 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
413 stream_putl (s, or->cost + or->u.ext.type2_cost);
414 else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
415 stream_putl (s, or->u.ext.type2_cost);
416 else
417 stream_putl (s, or->cost);
418 }
paul718e3742002-12-13 20:15:29 +0000419
420 stream_putw_at (s, 0, stream_get_endp (s));
421
ajs634f9ea2005-04-11 15:51:40 +0000422 zclient_send_message(zclient);
paul718e3742002-12-13 20:15:29 +0000423 }
424}
425
426void
427ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
428{
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200429 u_char message;
430 u_char distance;
431 u_char flags;
432 int psize;
433 struct stream *s;
paul72357f22003-06-19 02:11:23 +0000434 struct ospf_path *path;
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200435 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000436
Feng Luc99f3482014-10-16 09:52:36 +0800437 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000438 {
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200439 message = 0;
440 flags = 0;
441 /* Distance value. */
442 distance = ospf_distance_apply (p, or);
443 /* Make packet. */
444 s = zclient->obuf;
445 stream_reset (s);
paul718e3742002-12-13 20:15:29 +0000446
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200447 /* Put command, type, flags, message. */
Feng Luc99f3482014-10-16 09:52:36 +0800448 zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT);
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200449 stream_putc (s, ZEBRA_ROUTE_OSPF);
450 stream_putc (s, flags);
451 stream_putc (s, message);
452 stream_putw (s, SAFI_UNICAST);
paul72357f22003-06-19 02:11:23 +0000453
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200454 /* Put prefix information. */
455 psize = PSIZE (p->prefixlen);
456 stream_putc (s, p->prefixlen);
457 stream_write (s, (u_char *) & p->prefix, psize);
paul72357f22003-06-19 02:11:23 +0000458
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200459 /* Nexthop count. */
460 stream_putc (s, or->paths->count);
461
462 /* Nexthop, ifindex, distance and metric information. */
463 for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
464 {
465 if (path->nexthop.s_addr != INADDR_ANY &&
466 path->ifindex != 0)
467 {
468 stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
469 stream_put_in_addr (s, &path->nexthop);
470 stream_putl (s, path->ifindex);
471 }
472 else if (path->nexthop.s_addr != INADDR_ANY)
473 {
474 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
475 stream_put_in_addr (s, &path->nexthop);
476 }
477 else
478 {
479 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
480 stream_putl (s, path->ifindex);
481 }
482
483 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
484 {
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000485 char buf[2][INET_ADDRSTRLEN];
Christian Frankea25a1262013-11-27 14:36:05 +0000486 zlog_debug("Zebra: Route delete %s/%d nexthop %s",
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200487 inet_ntop(AF_INET, &p->prefix,
488 buf[0], sizeof(buf[0])),
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000489 p->prefixlen,
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200490 inet_ntop(AF_INET, &path->nexthop,
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000491 buf[1], sizeof(buf[1])));
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200492 }
493 }
494
495 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
496 stream_putc (s, distance);
497 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
498 {
499 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
500 stream_putl (s, or->cost + or->u.ext.type2_cost);
501 else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
502 stream_putl (s, or->u.ext.type2_cost);
503 else
504 stream_putl (s, or->cost);
505 }
506
507 stream_putw_at (s, 0, stream_get_endp (s));
508
509 zclient_send_message(zclient);
paul718e3742002-12-13 20:15:29 +0000510 }
511}
512
513void
514ospf_zebra_add_discard (struct prefix_ipv4 *p)
515{
516 struct zapi_ipv4 api;
517
Feng Luc99f3482014-10-16 09:52:36 +0800518 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000519 {
Feng Luc99f3482014-10-16 09:52:36 +0800520 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000521 api.type = ZEBRA_ROUTE_OSPF;
522 api.flags = ZEBRA_FLAG_BLACKHOLE;
523 api.message = 0;
Denis Ovsienkob4e45f62011-12-05 16:35:14 +0400524 api.safi = SAFI_UNICAST;
paul718e3742002-12-13 20:15:29 +0000525 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
526 api.nexthop_num = 0;
527 api.ifindex_num = 0;
528
paul0a589352004-05-08 11:48:26 +0000529 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
Andrew J. Schorr7f643eb2006-11-30 16:17:02 +0000530
531 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
532 zlog_debug ("Zebra: Route add discard %s/%d",
533 inet_ntoa (p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +0000534 }
535}
536
537void
538ospf_zebra_delete_discard (struct prefix_ipv4 *p)
539{
540 struct zapi_ipv4 api;
541
Feng Luc99f3482014-10-16 09:52:36 +0800542 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000543 {
Feng Luc99f3482014-10-16 09:52:36 +0800544 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000545 api.type = ZEBRA_ROUTE_OSPF;
546 api.flags = ZEBRA_FLAG_BLACKHOLE;
547 api.message = 0;
Denis Ovsienkob4e45f62011-12-05 16:35:14 +0400548 api.safi = SAFI_UNICAST;
paul718e3742002-12-13 20:15:29 +0000549 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
550 api.nexthop_num = 0;
551 api.ifindex_num = 0;
552
paul0a589352004-05-08 11:48:26 +0000553 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
paul72357f22003-06-19 02:11:23 +0000554
555 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000556 zlog_debug ("Zebra: Route delete discard %s/%d",
paulcf795c52003-06-19 02:13:25 +0000557 inet_ntoa (p->prefix), p->prefixlen);
paul72357f22003-06-19 02:11:23 +0000558
paul718e3742002-12-13 20:15:29 +0000559 }
560}
561
562int
563ospf_is_type_redistributed (int type)
564{
565 return (DEFAULT_ROUTE_TYPE (type)) ?
Feng Luc99f3482014-10-16 09:52:36 +0800566 vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : \
567 vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000568}
569
570int
paul020709f2003-04-04 02:44:16 +0000571ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue)
paul718e3742002-12-13 20:15:29 +0000572{
573 int force = 0;
paulcf795c52003-06-19 02:13:25 +0000574
paul718e3742002-12-13 20:15:29 +0000575 if (ospf_is_type_redistributed (type))
576 {
paul68980082003-03-25 05:07:42 +0000577 if (mtype != ospf->dmetric[type].type)
paulcf795c52003-06-19 02:13:25 +0000578 {
579 ospf->dmetric[type].type = mtype;
580 force = LSA_REFRESH_FORCE;
581 }
paul68980082003-03-25 05:07:42 +0000582 if (mvalue != ospf->dmetric[type].value)
paulcf795c52003-06-19 02:13:25 +0000583 {
584 ospf->dmetric[type].value = mvalue;
585 force = LSA_REFRESH_FORCE;
586 }
587
paul68980082003-03-25 05:07:42 +0000588 ospf_external_lsa_refresh_type (ospf, type, force);
paulcf795c52003-06-19 02:13:25 +0000589
paul718e3742002-12-13 20:15:29 +0000590 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000591 zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000592 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000593 metric_type (ospf, type), metric_value (ospf, type));
594
paul718e3742002-12-13 20:15:29 +0000595 return CMD_SUCCESS;
596 }
597
paul68980082003-03-25 05:07:42 +0000598 ospf->dmetric[type].type = mtype;
599 ospf->dmetric[type].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000600
Feng Luc99f3482014-10-16 09:52:36 +0800601 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000602
603 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000604 zlog_debug ("Redistribute[%s]: Start Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000605 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000606 metric_type (ospf, type), metric_value (ospf, type));
607
paul68980082003-03-25 05:07:42 +0000608 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000609
610 return CMD_SUCCESS;
611}
612
613int
paul020709f2003-04-04 02:44:16 +0000614ospf_redistribute_unset (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000615{
616 if (type == zclient->redist_default)
617 return CMD_SUCCESS;
618
paulcf795c52003-06-19 02:13:25 +0000619 if (!ospf_is_type_redistributed (type))
paul718e3742002-12-13 20:15:29 +0000620 return CMD_SUCCESS;
621
Feng Luc99f3482014-10-16 09:52:36 +0800622 zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type, VRF_DEFAULT);
paulcf795c52003-06-19 02:13:25 +0000623
paul718e3742002-12-13 20:15:29 +0000624 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000625 zlog_debug ("Redistribute[%s]: Stop",
ajsf52d13c2005-10-01 17:38:06 +0000626 ospf_redist_string(type));
paul718e3742002-12-13 20:15:29 +0000627
paul68980082003-03-25 05:07:42 +0000628 ospf->dmetric[type].type = -1;
629 ospf->dmetric[type].value = -1;
paul718e3742002-12-13 20:15:29 +0000630
631 /* Remove the routes from OSPF table. */
Paul Jakma6db3a6f2006-05-12 23:02:46 +0000632 ospf_redistribute_withdraw (ospf, type);
paul718e3742002-12-13 20:15:29 +0000633
paul68980082003-03-25 05:07:42 +0000634 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000635
636 return CMD_SUCCESS;
637}
638
639int
paul020709f2003-04-04 02:44:16 +0000640ospf_redistribute_default_set (struct ospf *ospf, int originate,
paulcf795c52003-06-19 02:13:25 +0000641 int mtype, int mvalue)
paul718e3742002-12-13 20:15:29 +0000642{
Andrew J. Schorr8fb8a502006-10-24 19:04:26 +0000643 ospf->default_originate = originate;
644 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
645 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
paul020709f2003-04-04 02:44:16 +0000646
paul718e3742002-12-13 20:15:29 +0000647 if (ospf_is_type_redistributed (DEFAULT_ROUTE))
648 {
Andrew J. Schorr8fb8a502006-10-24 19:04:26 +0000649 /* if ospf->default_originate changes value, is calling
650 ospf_external_lsa_refresh_default sufficient to implement
651 the change? */
paul68980082003-03-25 05:07:42 +0000652 ospf_external_lsa_refresh_default (ospf);
paulcf795c52003-06-19 02:13:25 +0000653
paul718e3742002-12-13 20:15:29 +0000654 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000655 zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000656 ospf_redist_string(DEFAULT_ROUTE),
paulcf795c52003-06-19 02:13:25 +0000657 metric_type (ospf, DEFAULT_ROUTE),
658 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000659 return CMD_SUCCESS;
660 }
661
Feng Luc99f3482014-10-16 09:52:36 +0800662 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
663 VRF_DEFAULT);
paulcf795c52003-06-19 02:13:25 +0000664
paul718e3742002-12-13 20:15:29 +0000665 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000666 zlog_debug ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
paulcf795c52003-06-19 02:13:25 +0000667 metric_type (ospf, DEFAULT_ROUTE),
668 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000669
paul68980082003-03-25 05:07:42 +0000670 if (ospf->router_id.s_addr == 0)
671 ospf->external_origin |= (1 << DEFAULT_ROUTE);
paul718e3742002-12-13 20:15:29 +0000672 else
Paul Jakma4021b602006-05-12 22:55:41 +0000673 thread_add_timer (master, ospf_default_originate_timer, ospf, 1);
paul718e3742002-12-13 20:15:29 +0000674
paul68980082003-03-25 05:07:42 +0000675 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000676
677 return CMD_SUCCESS;
678}
679
680int
paul020709f2003-04-04 02:44:16 +0000681ospf_redistribute_default_unset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000682{
683 if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
684 return CMD_SUCCESS;
685
paul68980082003-03-25 05:07:42 +0000686 ospf->default_originate = DEFAULT_ORIGINATE_NONE;
687 ospf->dmetric[DEFAULT_ROUTE].type = -1;
688 ospf->dmetric[DEFAULT_ROUTE].value = -1;
paul718e3742002-12-13 20:15:29 +0000689
Feng Luc99f3482014-10-16 09:52:36 +0800690 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient,
691 VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000692
693 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000694 zlog_debug ("Redistribute[DEFAULT]: Stop");
paulcf795c52003-06-19 02:13:25 +0000695
paul68980082003-03-25 05:07:42 +0000696 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000697
698 return CMD_SUCCESS;
699}
700
paul4dadc292005-05-06 21:37:42 +0000701static int
paul020709f2003-04-04 02:44:16 +0000702ospf_external_lsa_originate_check (struct ospf *ospf,
paulcf795c52003-06-19 02:13:25 +0000703 struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000704{
705 /* If prefix is multicast, then do not originate LSA. */
706 if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
707 {
708 zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
paulcf795c52003-06-19 02:13:25 +0000709 "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
paul718e3742002-12-13 20:15:29 +0000710 return 0;
711 }
712
713 /* Take care of default-originate. */
714 if (is_prefix_default (&ei->p))
paul68980082003-03-25 05:07:42 +0000715 if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
paul718e3742002-12-13 20:15:29 +0000716 {
Denis Ovsienkobcc6c592011-09-10 23:29:19 +0400717 zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA "
paulcf795c52003-06-19 02:13:25 +0000718 "for default");
719 return 0;
paul718e3742002-12-13 20:15:29 +0000720 }
721
722 return 1;
723}
724
725/* If connected prefix is OSPF enable interface, then do not announce. */
726int
paulcf795c52003-06-19 02:13:25 +0000727ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000728{
Joakim Tjernlund5d8de932009-08-07 13:48:15 +0200729 struct listnode *node;
730 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000731
Joakim Tjernlund5d8de932009-08-07 13:48:15 +0200732
733 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
734 if (prefix_match (oi->address, (struct prefix *) &ei->p))
paulcf795c52003-06-19 02:13:25 +0000735 return 0;
paul718e3742002-12-13 20:15:29 +0000736 return 1;
737}
738
739/* return 1 if external LSA must be originated, 0 otherwise */
740int
paul68980082003-03-25 05:07:42 +0000741ospf_redistribute_check (struct ospf *ospf,
paulcf795c52003-06-19 02:13:25 +0000742 struct external_info *ei, int *changed)
paul718e3742002-12-13 20:15:29 +0000743{
744 struct route_map_set_values save_values;
745 struct prefix_ipv4 *p = &ei->p;
746 u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
paulcf795c52003-06-19 02:13:25 +0000747
paul718e3742002-12-13 20:15:29 +0000748 if (changed)
749 *changed = 0;
750
paul020709f2003-04-04 02:44:16 +0000751 if (!ospf_external_lsa_originate_check (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000752 return 0;
753
754 /* Take care connected route. */
paul68980082003-03-25 05:07:42 +0000755 if (type == ZEBRA_ROUTE_CONNECT &&
756 !ospf_distribute_check_connected (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000757 return 0;
758
paul020709f2003-04-04 02:44:16 +0000759 if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000760 /* distirbute-list exists, but access-list may not? */
paul020709f2003-04-04 02:44:16 +0000761 if (DISTRIBUTE_LIST (ospf, type))
762 if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
paulcf795c52003-06-19 02:13:25 +0000763 {
764 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000765 zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
ajsf52d13c2005-10-01 17:38:06 +0000766 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000767 inet_ntoa (p->prefix), p->prefixlen);
768 return 0;
769 }
paul718e3742002-12-13 20:15:29 +0000770
771 save_values = ei->route_map_set;
772 ospf_reset_route_map_set_values (&ei->route_map_set);
paulcf795c52003-06-19 02:13:25 +0000773
paul718e3742002-12-13 20:15:29 +0000774 /* apply route-map if needed */
paul020709f2003-04-04 02:44:16 +0000775 if (ROUTEMAP_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000776 {
777 int ret;
778
paulcf795c52003-06-19 02:13:25 +0000779 ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p,
780 RMAP_OSPF, ei);
paul718e3742002-12-13 20:15:29 +0000781
782 if (ret == RMAP_DENYMATCH)
paulcf795c52003-06-19 02:13:25 +0000783 {
784 ei->route_map_set = save_values;
785 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000786 zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.",
ajsf52d13c2005-10-01 17:38:06 +0000787 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000788 inet_ntoa (p->prefix), p->prefixlen);
789 return 0;
790 }
791
paul718e3742002-12-13 20:15:29 +0000792 /* check if 'route-map set' changed something */
793 if (changed)
paulcf795c52003-06-19 02:13:25 +0000794 *changed = !ospf_route_map_set_compare (&ei->route_map_set,
795 &save_values);
paul718e3742002-12-13 20:15:29 +0000796 }
797
798 return 1;
799}
800
801/* OSPF route-map set for redistribution */
802void
paul6c835672004-10-11 11:00:30 +0000803ospf_routemap_set (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000804{
paul020709f2003-04-04 02:44:16 +0000805 if (ROUTEMAP_NAME (ospf, type))
806 free (ROUTEMAP_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000807
paul020709f2003-04-04 02:44:16 +0000808 ROUTEMAP_NAME (ospf, type) = strdup (name);
809 ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);
paul718e3742002-12-13 20:15:29 +0000810}
811
812void
paul020709f2003-04-04 02:44:16 +0000813ospf_routemap_unset (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000814{
paul020709f2003-04-04 02:44:16 +0000815 if (ROUTEMAP_NAME (ospf, type))
816 free (ROUTEMAP_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000817
paul020709f2003-04-04 02:44:16 +0000818 ROUTEMAP_NAME (ospf, type) = NULL;
819 ROUTEMAP (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000820}
821
822/* Zebra route add and delete treatment. */
paul4dadc292005-05-06 21:37:42 +0000823static int
paul718e3742002-12-13 20:15:29 +0000824ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800825 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000826{
827 struct stream *s;
828 struct zapi_ipv4 api;
829 unsigned long ifindex;
830 struct in_addr nexthop;
831 struct prefix_ipv4 p;
832 struct external_info *ei;
paul020709f2003-04-04 02:44:16 +0000833 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000834
835 s = zclient->ibuf;
836 ifindex = 0;
837 nexthop.s_addr = 0;
838
839 /* Type, flags, message. */
840 api.type = stream_getc (s);
841 api.flags = stream_getc (s);
842 api.message = stream_getc (s);
843
844 /* IPv4 prefix. */
845 memset (&p, 0, sizeof (struct prefix_ipv4));
846 p.family = AF_INET;
847 p.prefixlen = stream_getc (s);
848 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
849
hasso8585d4e2004-04-20 17:25:12 +0000850 if (IPV4_NET127(ntohl(p.prefix.s_addr)))
851 return 0;
852
paul718e3742002-12-13 20:15:29 +0000853 /* Nexthop, ifindex, distance, metric. */
854 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
855 {
856 api.nexthop_num = stream_getc (s);
857 nexthop.s_addr = stream_get_ipv4 (s);
858 }
859 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
860 {
861 api.ifindex_num = stream_getc (s);
gdt6a8da852004-02-13 17:40:51 +0000862 /* XXX assert(api.ifindex_num == 1); */
paul718e3742002-12-13 20:15:29 +0000863 ifindex = stream_getl (s);
864 }
865 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
866 api.distance = stream_getc (s);
867 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
868 api.metric = stream_getl (s);
869
paul020709f2003-04-04 02:44:16 +0000870 ospf = ospf_lookup ();
871 if (ospf == NULL)
872 return 0;
873
paul718e3742002-12-13 20:15:29 +0000874 if (command == ZEBRA_IPV4_ROUTE_ADD)
875 {
paul7021c422003-07-15 12:52:22 +0000876 /* XXX|HACK|TODO|FIXME:
hassoa0a39762004-04-23 08:51:10 +0000877 * Maybe we should ignore reject/blackhole routes? Testing shows that
878 * there is no problems though and this is only way to "summarize"
879 * routes in ASBR at the moment. Maybe we need just a better generalised
880 * solution for these types?
881 *
882 * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE)
883 * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
884 * return 0;
paul7021c422003-07-15 12:52:22 +0000885 */
paul7021c422003-07-15 12:52:22 +0000886
paul718e3742002-12-13 20:15:29 +0000887 ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
888
paul68980082003-03-25 05:07:42 +0000889 if (ospf->router_id.s_addr == 0)
paulcf795c52003-06-19 02:13:25 +0000890 /* Set flags to generate AS-external-LSA originate event
891 for each redistributed protocols later. */
892 ospf->external_origin |= (1 << api.type);
paul718e3742002-12-13 20:15:29 +0000893 else
paulcf795c52003-06-19 02:13:25 +0000894 {
895 if (ei)
896 {
897 if (is_prefix_default (&p))
898 ospf_external_lsa_refresh_default (ospf);
899 else
900 {
901 struct ospf_lsa *current;
paul718e3742002-12-13 20:15:29 +0000902
paulcf795c52003-06-19 02:13:25 +0000903 current = ospf_external_info_find_lsa (ospf, &ei->p);
904 if (!current)
905 ospf_external_lsa_originate (ospf, ei);
906 else if (IS_LSA_MAXAGE (current))
907 ospf_external_lsa_refresh (ospf, current,
908 ei, LSA_REFRESH_FORCE);
909 else
910 zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
911 inet_ntoa (p.prefix));
912 }
913 }
914 }
paul718e3742002-12-13 20:15:29 +0000915 }
paulcf795c52003-06-19 02:13:25 +0000916 else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
paul718e3742002-12-13 20:15:29 +0000917 {
918 ospf_external_info_delete (api.type, p);
paul7021c422003-07-15 12:52:22 +0000919 if (is_prefix_default (&p))
paulcf795c52003-06-19 02:13:25 +0000920 ospf_external_lsa_refresh_default (ospf);
paul7021c422003-07-15 12:52:22 +0000921 else
ajs5339cfd2005-09-19 13:28:05 +0000922 ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */);
paul718e3742002-12-13 20:15:29 +0000923 }
924
925 return 0;
926}
David Lamparter6b0655a2014-06-04 06:53:35 +0200927
paulcf795c52003-06-19 02:13:25 +0000928
paul718e3742002-12-13 20:15:29 +0000929int
paul6c835672004-10-11 11:00:30 +0000930ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000931{
932 /* Lookup access-list for distribute-list. */
paul020709f2003-04-04 02:44:16 +0000933 DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
paul718e3742002-12-13 20:15:29 +0000934
935 /* Clear previous distribute-name. */
paul020709f2003-04-04 02:44:16 +0000936 if (DISTRIBUTE_NAME (ospf, type))
937 free (DISTRIBUTE_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000938
939 /* Set distribute-name. */
paul020709f2003-04-04 02:44:16 +0000940 DISTRIBUTE_NAME (ospf, type) = strdup (name);
paul718e3742002-12-13 20:15:29 +0000941
942 /* If access-list have been set, schedule update timer. */
paul020709f2003-04-04 02:44:16 +0000943 if (DISTRIBUTE_LIST (ospf, type))
paul68980082003-03-25 05:07:42 +0000944 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000945
946 return CMD_SUCCESS;
947}
948
949int
paul6c835672004-10-11 11:00:30 +0000950ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000951{
952 /* Schedule update timer. */
paul020709f2003-04-04 02:44:16 +0000953 if (DISTRIBUTE_LIST (ospf, type))
paul68980082003-03-25 05:07:42 +0000954 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000955
956 /* Unset distribute-list. */
paul020709f2003-04-04 02:44:16 +0000957 DISTRIBUTE_LIST (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000958
959 /* Clear distribute-name. */
paul020709f2003-04-04 02:44:16 +0000960 if (DISTRIBUTE_NAME (ospf, type))
961 free (DISTRIBUTE_NAME (ospf, type));
paulcf795c52003-06-19 02:13:25 +0000962
paul020709f2003-04-04 02:44:16 +0000963 DISTRIBUTE_NAME (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000964
965 return CMD_SUCCESS;
966}
967
968/* distribute-list update timer. */
paul4dadc292005-05-06 21:37:42 +0000969static int
paul718e3742002-12-13 20:15:29 +0000970ospf_distribute_list_update_timer (struct thread *thread)
971{
972 struct route_node *rn;
973 struct external_info *ei;
974 struct route_table *rt;
975 struct ospf_lsa *lsa;
Joakim Tjernlund46154fe2010-04-14 16:01:25 +0200976 int type, default_refresh = 0;
paul020709f2003-04-04 02:44:16 +0000977 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000978
paul020709f2003-04-04 02:44:16 +0000979 ospf = ospf_lookup ();
980 if (ospf == NULL)
981 return 0;
982
paul68980082003-03-25 05:07:42 +0000983 ospf->t_distribute_update = NULL;
paul718e3742002-12-13 20:15:29 +0000984
985 zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
986
987 /* foreach all external info. */
Joakim Tjernlund274d3f02010-04-14 11:05:27 +0200988 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
989 {
990 rt = EXTERNAL_INFO (type);
991 if (!rt)
992 continue;
993 for (rn = route_top (rt); rn; rn = route_next (rn))
994 if ((ei = rn->info) != NULL)
995 {
996 if (is_prefix_default (&ei->p))
Joakim Tjernlund46154fe2010-04-14 16:01:25 +0200997 default_refresh = 1;
Joakim Tjernlund274d3f02010-04-14 11:05:27 +0200998 else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
999 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
1000 else
1001 ospf_external_lsa_originate (ospf, ei);
1002 }
1003 }
Joakim Tjernlund46154fe2010-04-14 16:01:25 +02001004 if (default_refresh)
1005 ospf_external_lsa_refresh_default (ospf);
paul718e3742002-12-13 20:15:29 +00001006 return 0;
1007}
1008
1009#define OSPF_DISTRIBUTE_UPDATE_DELAY 5
1010
1011/* Update distribute-list and set timer to apply access-list. */
1012void
Andrew Certain0798cee2012-12-04 13:43:42 -08001013ospf_distribute_list_update (struct ospf *ospf, uintptr_t type)
paul718e3742002-12-13 20:15:29 +00001014{
1015 struct route_table *rt;
paulcf795c52003-06-19 02:13:25 +00001016
paul718e3742002-12-13 20:15:29 +00001017 /* External info does not exist. */
1018 if (!(rt = EXTERNAL_INFO (type)))
1019 return;
1020
Joakim Tjernlund45acaa02010-04-14 11:05:28 +02001021 /* If exists previously invoked thread, then let it continue. */
paul68980082003-03-25 05:07:42 +00001022 if (ospf->t_distribute_update)
Joakim Tjernlund45acaa02010-04-14 11:05:28 +02001023 return;
paul718e3742002-12-13 20:15:29 +00001024
1025 /* Set timer. */
paul68980082003-03-25 05:07:42 +00001026 ospf->t_distribute_update =
paul718e3742002-12-13 20:15:29 +00001027 thread_add_timer (master, ospf_distribute_list_update_timer,
paulcf795c52003-06-19 02:13:25 +00001028 (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +00001029}
1030
1031/* If access-list is updated, apply some check. */
paul4dadc292005-05-06 21:37:42 +00001032static void
paul718e3742002-12-13 20:15:29 +00001033ospf_filter_update (struct access_list *access)
1034{
paul020709f2003-04-04 02:44:16 +00001035 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001036 int type;
1037 int abr_inv = 0;
1038 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +00001039 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001040
1041 /* If OSPF instatnce does not exist, return right now. */
paul020709f2003-04-04 02:44:16 +00001042 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001043 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001044 return;
1045
paul718e3742002-12-13 20:15:29 +00001046 /* Update distribute-list, and apply filter. */
hasso01018ce2005-08-05 07:40:15 +00001047 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +00001048 {
paul020709f2003-04-04 02:44:16 +00001049 if (ROUTEMAP (ospf, type) != NULL)
paulcf795c52003-06-19 02:13:25 +00001050 {
1051 /* if route-map is not NULL it may be using this access list */
1052 ospf_distribute_list_update (ospf, type);
1053 continue;
1054 }
1055
hasso01018ce2005-08-05 07:40:15 +00001056 /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX),
1057 * but no distribute list. */
1058 if (type == ZEBRA_ROUTE_MAX)
1059 break;
paul718e3742002-12-13 20:15:29 +00001060
paul020709f2003-04-04 02:44:16 +00001061 if (DISTRIBUTE_NAME (ospf, type))
paulcf795c52003-06-19 02:13:25 +00001062 {
1063 /* Keep old access-list for distribute-list. */
1064 struct access_list *old = DISTRIBUTE_LIST (ospf, type);
1065
1066 /* Update access-list for distribute-list. */
1067 DISTRIBUTE_LIST (ospf, type) =
1068 access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type));
1069
1070 /* No update for this distribute type. */
1071 if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL)
1072 continue;
1073
1074 /* Schedule distribute-list update timer. */
1075 if (DISTRIBUTE_LIST (ospf, type) == NULL ||
1076 strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
1077 ospf_distribute_list_update (ospf, type);
1078 }
paul718e3742002-12-13 20:15:29 +00001079 }
1080
1081 /* Update Area access-list. */
paul1eb8ef22005-04-07 07:30:20 +00001082 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1083 {
1084 if (EXPORT_NAME (area))
1085 {
1086 EXPORT_LIST (area) = NULL;
1087 abr_inv++;
1088 }
paul718e3742002-12-13 20:15:29 +00001089
paul1eb8ef22005-04-07 07:30:20 +00001090 if (IMPORT_NAME (area))
1091 {
1092 IMPORT_LIST (area) = NULL;
1093 abr_inv++;
1094 }
1095 }
paul718e3742002-12-13 20:15:29 +00001096
1097 /* Schedule ABR tasks -- this will be changed -- takada. */
paul020709f2003-04-04 02:44:16 +00001098 if (IS_OSPF_ABR (ospf) && abr_inv)
paul68980082003-03-25 05:07:42 +00001099 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001100}
hassodd669bb2004-05-10 07:43:59 +00001101
1102/* If prefix-list is updated, do some updates. */
1103void
1104ospf_prefix_list_update (struct prefix_list *plist)
1105{
1106 struct ospf *ospf;
1107 int type;
1108 int abr_inv = 0;
1109 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +00001110 struct listnode *node;
hassodd669bb2004-05-10 07:43:59 +00001111
1112 /* If OSPF instatnce does not exist, return right now. */
1113 ospf = ospf_lookup ();
1114 if (ospf == NULL)
1115 return;
1116
1117 /* Update all route-maps which are used as redistribution filters.
1118 * They might use prefix-list.
1119 */
hasso01018ce2005-08-05 07:40:15 +00001120 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
hassodd669bb2004-05-10 07:43:59 +00001121 {
1122 if (ROUTEMAP (ospf, type) != NULL)
1123 {
1124 /* If route-map is not NULL it may be using this prefix list */
1125 ospf_distribute_list_update (ospf, type);
1126 continue;
1127 }
1128 }
1129
1130 /* Update area filter-lists. */
paul1eb8ef22005-04-07 07:30:20 +00001131 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1132 {
1133 /* Update filter-list in. */
1134 if (PREFIX_NAME_IN (area))
David Lampartere66cbd12015-04-13 10:21:34 +02001135 if (strcmp (PREFIX_NAME_IN (area), prefix_list_name (plist)) == 0)
paul1eb8ef22005-04-07 07:30:20 +00001136 {
1137 PREFIX_LIST_IN (area) =
1138 prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
1139 abr_inv++;
1140 }
hassodd669bb2004-05-10 07:43:59 +00001141
paul1eb8ef22005-04-07 07:30:20 +00001142 /* Update filter-list out. */
1143 if (PREFIX_NAME_OUT (area))
David Lampartere66cbd12015-04-13 10:21:34 +02001144 if (strcmp (PREFIX_NAME_OUT (area), prefix_list_name (plist)) == 0)
paul1eb8ef22005-04-07 07:30:20 +00001145 {
1146 PREFIX_LIST_IN (area) =
1147 prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
1148 abr_inv++;
1149 }
1150 }
hassodd669bb2004-05-10 07:43:59 +00001151
1152 /* Schedule ABR task. */
1153 if (IS_OSPF_ABR (ospf) && abr_inv)
1154 ospf_schedule_abr_task (ospf);
1155}
paulcf795c52003-06-19 02:13:25 +00001156
paul4dadc292005-05-06 21:37:42 +00001157static struct ospf_distance *
1158ospf_distance_new (void)
paul718e3742002-12-13 20:15:29 +00001159{
Stephen Hemminger393deb92008-08-18 14:13:29 -07001160 return XCALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
paul718e3742002-12-13 20:15:29 +00001161}
1162
paul4dadc292005-05-06 21:37:42 +00001163static void
paul718e3742002-12-13 20:15:29 +00001164ospf_distance_free (struct ospf_distance *odistance)
1165{
1166 XFREE (MTYPE_OSPF_DISTANCE, odistance);
1167}
1168
1169int
paul6c835672004-10-11 11:00:30 +00001170ospf_distance_set (struct vty *vty, struct ospf *ospf,
1171 const char *distance_str,
1172 const char *ip_str,
1173 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00001174{
1175 int ret;
1176 struct prefix_ipv4 p;
1177 u_char distance;
1178 struct route_node *rn;
1179 struct ospf_distance *odistance;
1180
1181 ret = str2prefix_ipv4 (ip_str, &p);
1182 if (ret == 0)
1183 {
1184 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1185 return CMD_WARNING;
1186 }
1187
1188 distance = atoi (distance_str);
1189
1190 /* Get OSPF distance node. */
paul68980082003-03-25 05:07:42 +00001191 rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +00001192 if (rn->info)
1193 {
1194 odistance = rn->info;
1195 route_unlock_node (rn);
1196 }
1197 else
1198 {
1199 odistance = ospf_distance_new ();
1200 rn->info = odistance;
1201 }
1202
1203 /* Set distance value. */
1204 odistance->distance = distance;
1205
1206 /* Reset access-list configuration. */
1207 if (odistance->access_list)
1208 {
1209 free (odistance->access_list);
1210 odistance->access_list = NULL;
1211 }
1212 if (access_list_str)
1213 odistance->access_list = strdup (access_list_str);
1214
1215 return CMD_SUCCESS;
1216}
1217
1218int
paul6c835672004-10-11 11:00:30 +00001219ospf_distance_unset (struct vty *vty, struct ospf *ospf,
1220 const char *distance_str,
1221 const char *ip_str, char
1222 const *access_list_str)
paul718e3742002-12-13 20:15:29 +00001223{
1224 int ret;
1225 struct prefix_ipv4 p;
paul718e3742002-12-13 20:15:29 +00001226 struct route_node *rn;
1227 struct ospf_distance *odistance;
1228
1229 ret = str2prefix_ipv4 (ip_str, &p);
1230 if (ret == 0)
1231 {
1232 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1233 return CMD_WARNING;
1234 }
1235
paulcf795c52003-06-19 02:13:25 +00001236 rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p);
1237 if (!rn)
paul718e3742002-12-13 20:15:29 +00001238 {
1239 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
1240 return CMD_WARNING;
1241 }
1242
1243 odistance = rn->info;
1244
1245 if (odistance->access_list)
1246 free (odistance->access_list);
1247 ospf_distance_free (odistance);
1248
1249 rn->info = NULL;
1250 route_unlock_node (rn);
1251 route_unlock_node (rn);
1252
1253 return CMD_SUCCESS;
1254}
1255
1256void
paul68980082003-03-25 05:07:42 +00001257ospf_distance_reset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001258{
1259 struct route_node *rn;
1260 struct ospf_distance *odistance;
1261
paul68980082003-03-25 05:07:42 +00001262 for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001263 if ((odistance = rn->info) != NULL)
1264 {
paulcf795c52003-06-19 02:13:25 +00001265 if (odistance->access_list)
1266 free (odistance->access_list);
1267 ospf_distance_free (odistance);
1268 rn->info = NULL;
1269 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001270 }
1271}
1272
1273u_char
1274ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
1275{
paul020709f2003-04-04 02:44:16 +00001276 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001277
paul020709f2003-04-04 02:44:16 +00001278 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001279 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001280 return 0;
1281
paul68980082003-03-25 05:07:42 +00001282 if (ospf->distance_intra)
paul718e3742002-12-13 20:15:29 +00001283 if (or->path_type == OSPF_PATH_INTRA_AREA)
paul68980082003-03-25 05:07:42 +00001284 return ospf->distance_intra;
paul718e3742002-12-13 20:15:29 +00001285
paul68980082003-03-25 05:07:42 +00001286 if (ospf->distance_inter)
paul718e3742002-12-13 20:15:29 +00001287 if (or->path_type == OSPF_PATH_INTER_AREA)
paul68980082003-03-25 05:07:42 +00001288 return ospf->distance_inter;
paul718e3742002-12-13 20:15:29 +00001289
paul68980082003-03-25 05:07:42 +00001290 if (ospf->distance_external)
paul718e3742002-12-13 20:15:29 +00001291 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
paulcf795c52003-06-19 02:13:25 +00001292 || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
paul68980082003-03-25 05:07:42 +00001293 return ospf->distance_external;
paulcf795c52003-06-19 02:13:25 +00001294
paul68980082003-03-25 05:07:42 +00001295 if (ospf->distance_all)
1296 return ospf->distance_all;
paul718e3742002-12-13 20:15:29 +00001297
1298 return 0;
1299}
1300
Feng Luc99f3482014-10-16 09:52:36 +08001301static void
1302ospf_zebra_connected (struct zclient *zclient)
1303{
1304 zclient_send_requests (zclient, VRF_DEFAULT);
1305}
1306
paul718e3742002-12-13 20:15:29 +00001307void
1308ospf_zebra_init ()
1309{
1310 /* Allocate zebra structure. */
1311 zclient = zclient_new ();
1312 zclient_init (zclient, ZEBRA_ROUTE_OSPF);
Feng Luc99f3482014-10-16 09:52:36 +08001313 zclient->zebra_connected = ospf_zebra_connected;
hasso18a6dce2004-10-03 18:18:34 +00001314 zclient->router_id_update = ospf_router_id_update_zebra;
paul718e3742002-12-13 20:15:29 +00001315 zclient->interface_add = ospf_interface_add;
1316 zclient->interface_delete = ospf_interface_delete;
1317 zclient->interface_up = ospf_interface_state_up;
1318 zclient->interface_down = ospf_interface_state_down;
1319 zclient->interface_address_add = ospf_interface_address_add;
1320 zclient->interface_address_delete = ospf_interface_address_delete;
1321 zclient->ipv4_route_add = ospf_zebra_read_ipv4;
1322 zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
1323
1324 access_list_add_hook (ospf_filter_update);
1325 access_list_delete_hook (ospf_filter_update);
hassodd669bb2004-05-10 07:43:59 +00001326 prefix_list_add_hook (ospf_prefix_list_update);
1327 prefix_list_delete_hook (ospf_prefix_list_update);
paul718e3742002-12-13 20:15:29 +00001328}