blob: 588f0fb5c7911fcc0d627b6a8a06f6c93661203a [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;
Joakim Tjernlundfbb6c862010-03-08 13:58:09 +0100315 route_unlock_node (rn);
paulcf795c52003-06-19 02:13:25 +0000316
paul718e3742002-12-13 20:15:29 +0000317 /* Call interface hook functions to clean up */
318 ospf_if_free (oi);
paulcf795c52003-06-19 02:13:25 +0000319
paul718e3742002-12-13 20:15:29 +0000320#ifdef HAVE_SNMP
321 ospf_snmp_if_update (c->ifp);
322#endif /* HAVE_SNMP */
323
324 connected_free (c);
325
paul718e3742002-12-13 20:15:29 +0000326 return 0;
327}
paul72357f22003-06-19 02:11:23 +0000328
paul718e3742002-12-13 20:15:29 +0000329void
330ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
331{
332 u_char message;
333 u_char distance;
334 u_char flags;
335 int psize;
336 struct stream *s;
337 struct ospf_path *path;
hasso52dc7ee2004-09-23 19:18:23 +0000338 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000339
Feng Luc99f3482014-10-16 09:52:36 +0800340 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000341 {
342 message = 0;
343 flags = 0;
344
345 /* OSPF pass nexthop and metric */
346 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
347 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
348
349 /* Distance value. */
350 distance = ospf_distance_apply (p, or);
351 if (distance)
paul72357f22003-06-19 02:11:23 +0000352 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
paul718e3742002-12-13 20:15:29 +0000353
354 /* Make packet. */
355 s = zclient->obuf;
356 stream_reset (s);
357
paul718e3742002-12-13 20:15:29 +0000358 /* Put command, type, flags, message. */
Feng Luc99f3482014-10-16 09:52:36 +0800359 zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000360 stream_putc (s, ZEBRA_ROUTE_OSPF);
361 stream_putc (s, flags);
362 stream_putc (s, message);
Denis Ovsienkob4e45f62011-12-05 16:35:14 +0400363 stream_putw (s, SAFI_UNICAST);
paulcf795c52003-06-19 02:13:25 +0000364
paul718e3742002-12-13 20:15:29 +0000365 /* Put prefix information. */
366 psize = PSIZE (p->prefixlen);
367 stream_putc (s, p->prefixlen);
paulcf795c52003-06-19 02:13:25 +0000368 stream_write (s, (u_char *) & p->prefix, psize);
paul718e3742002-12-13 20:15:29 +0000369
370 /* Nexthop count. */
paul96735ee2003-08-10 02:51:22 +0000371 stream_putc (s, or->paths->count);
paul718e3742002-12-13 20:15:29 +0000372
373 /* Nexthop, ifindex, distance and metric information. */
paul1eb8ef22005-04-07 07:30:20 +0000374 for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
paul72357f22003-06-19 02:11:23 +0000375 {
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200376 if (path->nexthop.s_addr != INADDR_ANY &&
377 path->ifindex != 0)
378 {
379 stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
380 stream_put_in_addr (s, &path->nexthop);
381 stream_putl (s, path->ifindex);
382 }
383 else if (path->nexthop.s_addr != INADDR_ANY)
paulcf795c52003-06-19 02:13:25 +0000384 {
385 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
386 stream_put_in_addr (s, &path->nexthop);
387 }
388 else
389 {
390 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200391 if (path->ifindex)
392 stream_putl (s, path->ifindex);
paulcf795c52003-06-19 02:13:25 +0000393 else
394 stream_putl (s, 0);
395 }
paul72357f22003-06-19 02:11:23 +0000396
397 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
398 {
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000399 char buf[2][INET_ADDRSTRLEN];
400 zlog_debug("Zebra: Route add %s/%d nexthop %s",
401 inet_ntop(AF_INET, &p->prefix,
402 buf[0], sizeof(buf[0])),
403 p->prefixlen,
404 inet_ntop(AF_INET, &path->nexthop,
405 buf[1], sizeof(buf[1])));
paulcf795c52003-06-19 02:13:25 +0000406 }
407 }
paul718e3742002-12-13 20:15:29 +0000408
409 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
paulcf795c52003-06-19 02:13:25 +0000410 stream_putc (s, distance);
paul718e3742002-12-13 20:15:29 +0000411 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
paulcf795c52003-06-19 02:13:25 +0000412 {
413 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
414 stream_putl (s, or->cost + or->u.ext.type2_cost);
415 else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
416 stream_putl (s, or->u.ext.type2_cost);
417 else
418 stream_putl (s, or->cost);
419 }
paul718e3742002-12-13 20:15:29 +0000420
421 stream_putw_at (s, 0, stream_get_endp (s));
422
ajs634f9ea2005-04-11 15:51:40 +0000423 zclient_send_message(zclient);
paul718e3742002-12-13 20:15:29 +0000424 }
425}
426
427void
428ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
429{
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200430 u_char message;
431 u_char distance;
432 u_char flags;
433 int psize;
434 struct stream *s;
paul72357f22003-06-19 02:11:23 +0000435 struct ospf_path *path;
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200436 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000437
Feng Luc99f3482014-10-16 09:52:36 +0800438 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000439 {
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200440 message = 0;
441 flags = 0;
442 /* Distance value. */
443 distance = ospf_distance_apply (p, or);
444 /* Make packet. */
445 s = zclient->obuf;
446 stream_reset (s);
paul718e3742002-12-13 20:15:29 +0000447
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200448 /* Put command, type, flags, message. */
Feng Luc99f3482014-10-16 09:52:36 +0800449 zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT);
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200450 stream_putc (s, ZEBRA_ROUTE_OSPF);
451 stream_putc (s, flags);
452 stream_putc (s, message);
453 stream_putw (s, SAFI_UNICAST);
paul72357f22003-06-19 02:11:23 +0000454
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200455 /* Put prefix information. */
456 psize = PSIZE (p->prefixlen);
457 stream_putc (s, p->prefixlen);
458 stream_write (s, (u_char *) & p->prefix, psize);
paul72357f22003-06-19 02:11:23 +0000459
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200460 /* Nexthop count. */
461 stream_putc (s, or->paths->count);
462
463 /* Nexthop, ifindex, distance and metric information. */
464 for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
465 {
466 if (path->nexthop.s_addr != INADDR_ANY &&
467 path->ifindex != 0)
468 {
469 stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
470 stream_put_in_addr (s, &path->nexthop);
471 stream_putl (s, path->ifindex);
472 }
473 else if (path->nexthop.s_addr != INADDR_ANY)
474 {
475 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
476 stream_put_in_addr (s, &path->nexthop);
477 }
478 else
479 {
480 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
481 stream_putl (s, path->ifindex);
482 }
483
484 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
485 {
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000486 char buf[2][INET_ADDRSTRLEN];
Christian Frankea25a1262013-11-27 14:36:05 +0000487 zlog_debug("Zebra: Route delete %s/%d nexthop %s",
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200488 inet_ntop(AF_INET, &p->prefix,
489 buf[0], sizeof(buf[0])),
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000490 p->prefixlen,
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200491 inet_ntop(AF_INET, &path->nexthop,
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000492 buf[1], sizeof(buf[1])));
Joakim Tjernlundba281d32012-07-07 17:06:13 +0200493 }
494 }
495
496 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
497 stream_putc (s, distance);
498 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
499 {
500 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
501 stream_putl (s, or->cost + or->u.ext.type2_cost);
502 else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
503 stream_putl (s, or->u.ext.type2_cost);
504 else
505 stream_putl (s, or->cost);
506 }
507
508 stream_putw_at (s, 0, stream_get_endp (s));
509
510 zclient_send_message(zclient);
paul718e3742002-12-13 20:15:29 +0000511 }
512}
513
514void
515ospf_zebra_add_discard (struct prefix_ipv4 *p)
516{
517 struct zapi_ipv4 api;
518
Feng Luc99f3482014-10-16 09:52:36 +0800519 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000520 {
Feng Luc99f3482014-10-16 09:52:36 +0800521 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000522 api.type = ZEBRA_ROUTE_OSPF;
523 api.flags = ZEBRA_FLAG_BLACKHOLE;
524 api.message = 0;
Denis Ovsienkob4e45f62011-12-05 16:35:14 +0400525 api.safi = SAFI_UNICAST;
paul718e3742002-12-13 20:15:29 +0000526 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
527 api.nexthop_num = 0;
528 api.ifindex_num = 0;
529
paul0a589352004-05-08 11:48:26 +0000530 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
Andrew J. Schorr7f643eb2006-11-30 16:17:02 +0000531
532 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
533 zlog_debug ("Zebra: Route add discard %s/%d",
534 inet_ntoa (p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +0000535 }
536}
537
538void
539ospf_zebra_delete_discard (struct prefix_ipv4 *p)
540{
541 struct zapi_ipv4 api;
542
Feng Luc99f3482014-10-16 09:52:36 +0800543 if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000544 {
Feng Luc99f3482014-10-16 09:52:36 +0800545 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000546 api.type = ZEBRA_ROUTE_OSPF;
547 api.flags = ZEBRA_FLAG_BLACKHOLE;
548 api.message = 0;
Denis Ovsienkob4e45f62011-12-05 16:35:14 +0400549 api.safi = SAFI_UNICAST;
paul718e3742002-12-13 20:15:29 +0000550 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
551 api.nexthop_num = 0;
552 api.ifindex_num = 0;
553
paul0a589352004-05-08 11:48:26 +0000554 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
paul72357f22003-06-19 02:11:23 +0000555
556 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000557 zlog_debug ("Zebra: Route delete discard %s/%d",
paulcf795c52003-06-19 02:13:25 +0000558 inet_ntoa (p->prefix), p->prefixlen);
paul72357f22003-06-19 02:11:23 +0000559
paul718e3742002-12-13 20:15:29 +0000560 }
561}
562
563int
564ospf_is_type_redistributed (int type)
565{
566 return (DEFAULT_ROUTE_TYPE (type)) ?
Feng Luc99f3482014-10-16 09:52:36 +0800567 vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : \
568 vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000569}
570
571int
paul020709f2003-04-04 02:44:16 +0000572ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue)
paul718e3742002-12-13 20:15:29 +0000573{
574 int force = 0;
paulcf795c52003-06-19 02:13:25 +0000575
paul718e3742002-12-13 20:15:29 +0000576 if (ospf_is_type_redistributed (type))
577 {
paul68980082003-03-25 05:07:42 +0000578 if (mtype != ospf->dmetric[type].type)
paulcf795c52003-06-19 02:13:25 +0000579 {
580 ospf->dmetric[type].type = mtype;
581 force = LSA_REFRESH_FORCE;
582 }
paul68980082003-03-25 05:07:42 +0000583 if (mvalue != ospf->dmetric[type].value)
paulcf795c52003-06-19 02:13:25 +0000584 {
585 ospf->dmetric[type].value = mvalue;
586 force = LSA_REFRESH_FORCE;
587 }
588
paul68980082003-03-25 05:07:42 +0000589 ospf_external_lsa_refresh_type (ospf, type, force);
paulcf795c52003-06-19 02:13:25 +0000590
paul718e3742002-12-13 20:15:29 +0000591 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000592 zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000593 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000594 metric_type (ospf, type), metric_value (ospf, type));
595
paul718e3742002-12-13 20:15:29 +0000596 return CMD_SUCCESS;
597 }
598
paul68980082003-03-25 05:07:42 +0000599 ospf->dmetric[type].type = mtype;
600 ospf->dmetric[type].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000601
Feng Luc99f3482014-10-16 09:52:36 +0800602 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000603
604 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000605 zlog_debug ("Redistribute[%s]: Start Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000606 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000607 metric_type (ospf, type), metric_value (ospf, type));
608
paul68980082003-03-25 05:07:42 +0000609 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000610
611 return CMD_SUCCESS;
612}
613
614int
paul020709f2003-04-04 02:44:16 +0000615ospf_redistribute_unset (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000616{
617 if (type == zclient->redist_default)
618 return CMD_SUCCESS;
619
paulcf795c52003-06-19 02:13:25 +0000620 if (!ospf_is_type_redistributed (type))
paul718e3742002-12-13 20:15:29 +0000621 return CMD_SUCCESS;
622
Feng Luc99f3482014-10-16 09:52:36 +0800623 zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type, VRF_DEFAULT);
paulcf795c52003-06-19 02:13:25 +0000624
paul718e3742002-12-13 20:15:29 +0000625 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000626 zlog_debug ("Redistribute[%s]: Stop",
ajsf52d13c2005-10-01 17:38:06 +0000627 ospf_redist_string(type));
paul718e3742002-12-13 20:15:29 +0000628
paul68980082003-03-25 05:07:42 +0000629 ospf->dmetric[type].type = -1;
630 ospf->dmetric[type].value = -1;
paul718e3742002-12-13 20:15:29 +0000631
632 /* Remove the routes from OSPF table. */
Paul Jakma6db3a6f2006-05-12 23:02:46 +0000633 ospf_redistribute_withdraw (ospf, type);
paul718e3742002-12-13 20:15:29 +0000634
paul68980082003-03-25 05:07:42 +0000635 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000636
637 return CMD_SUCCESS;
638}
639
640int
paul020709f2003-04-04 02:44:16 +0000641ospf_redistribute_default_set (struct ospf *ospf, int originate,
paulcf795c52003-06-19 02:13:25 +0000642 int mtype, int mvalue)
paul718e3742002-12-13 20:15:29 +0000643{
Andrew J. Schorr8fb8a502006-10-24 19:04:26 +0000644 ospf->default_originate = originate;
645 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
646 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
paul020709f2003-04-04 02:44:16 +0000647
paul718e3742002-12-13 20:15:29 +0000648 if (ospf_is_type_redistributed (DEFAULT_ROUTE))
649 {
Andrew J. Schorr8fb8a502006-10-24 19:04:26 +0000650 /* if ospf->default_originate changes value, is calling
651 ospf_external_lsa_refresh_default sufficient to implement
652 the change? */
paul68980082003-03-25 05:07:42 +0000653 ospf_external_lsa_refresh_default (ospf);
paulcf795c52003-06-19 02:13:25 +0000654
paul718e3742002-12-13 20:15:29 +0000655 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000656 zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000657 ospf_redist_string(DEFAULT_ROUTE),
paulcf795c52003-06-19 02:13:25 +0000658 metric_type (ospf, DEFAULT_ROUTE),
659 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000660 return CMD_SUCCESS;
661 }
662
Feng Luc99f3482014-10-16 09:52:36 +0800663 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
664 VRF_DEFAULT);
paulcf795c52003-06-19 02:13:25 +0000665
paul718e3742002-12-13 20:15:29 +0000666 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000667 zlog_debug ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
paulcf795c52003-06-19 02:13:25 +0000668 metric_type (ospf, DEFAULT_ROUTE),
669 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000670
paul68980082003-03-25 05:07:42 +0000671 if (ospf->router_id.s_addr == 0)
672 ospf->external_origin |= (1 << DEFAULT_ROUTE);
paul718e3742002-12-13 20:15:29 +0000673 else
Paul Jakma4021b602006-05-12 22:55:41 +0000674 thread_add_timer (master, ospf_default_originate_timer, ospf, 1);
paul718e3742002-12-13 20:15:29 +0000675
paul68980082003-03-25 05:07:42 +0000676 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000677
678 return CMD_SUCCESS;
679}
680
681int
paul020709f2003-04-04 02:44:16 +0000682ospf_redistribute_default_unset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000683{
684 if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
685 return CMD_SUCCESS;
686
paul68980082003-03-25 05:07:42 +0000687 ospf->default_originate = DEFAULT_ORIGINATE_NONE;
688 ospf->dmetric[DEFAULT_ROUTE].type = -1;
689 ospf->dmetric[DEFAULT_ROUTE].value = -1;
paul718e3742002-12-13 20:15:29 +0000690
Feng Luc99f3482014-10-16 09:52:36 +0800691 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient,
692 VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000693
694 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000695 zlog_debug ("Redistribute[DEFAULT]: Stop");
paulcf795c52003-06-19 02:13:25 +0000696
paul68980082003-03-25 05:07:42 +0000697 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000698
699 return CMD_SUCCESS;
700}
701
paul4dadc292005-05-06 21:37:42 +0000702static int
paul020709f2003-04-04 02:44:16 +0000703ospf_external_lsa_originate_check (struct ospf *ospf,
paulcf795c52003-06-19 02:13:25 +0000704 struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000705{
706 /* If prefix is multicast, then do not originate LSA. */
707 if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
708 {
709 zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
paulcf795c52003-06-19 02:13:25 +0000710 "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
paul718e3742002-12-13 20:15:29 +0000711 return 0;
712 }
713
714 /* Take care of default-originate. */
715 if (is_prefix_default (&ei->p))
paul68980082003-03-25 05:07:42 +0000716 if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
paul718e3742002-12-13 20:15:29 +0000717 {
Denis Ovsienkobcc6c592011-09-10 23:29:19 +0400718 zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA "
paulcf795c52003-06-19 02:13:25 +0000719 "for default");
720 return 0;
paul718e3742002-12-13 20:15:29 +0000721 }
722
723 return 1;
724}
725
726/* If connected prefix is OSPF enable interface, then do not announce. */
727int
paulcf795c52003-06-19 02:13:25 +0000728ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000729{
Joakim Tjernlund5d8de932009-08-07 13:48:15 +0200730 struct listnode *node;
731 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000732
Joakim Tjernlund5d8de932009-08-07 13:48:15 +0200733
734 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
735 if (prefix_match (oi->address, (struct prefix *) &ei->p))
paulcf795c52003-06-19 02:13:25 +0000736 return 0;
paul718e3742002-12-13 20:15:29 +0000737 return 1;
738}
739
740/* return 1 if external LSA must be originated, 0 otherwise */
741int
paul68980082003-03-25 05:07:42 +0000742ospf_redistribute_check (struct ospf *ospf,
paulcf795c52003-06-19 02:13:25 +0000743 struct external_info *ei, int *changed)
paul718e3742002-12-13 20:15:29 +0000744{
745 struct route_map_set_values save_values;
746 struct prefix_ipv4 *p = &ei->p;
747 u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
paulcf795c52003-06-19 02:13:25 +0000748
paul718e3742002-12-13 20:15:29 +0000749 if (changed)
750 *changed = 0;
751
paul020709f2003-04-04 02:44:16 +0000752 if (!ospf_external_lsa_originate_check (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000753 return 0;
754
755 /* Take care connected route. */
paul68980082003-03-25 05:07:42 +0000756 if (type == ZEBRA_ROUTE_CONNECT &&
757 !ospf_distribute_check_connected (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000758 return 0;
759
paul020709f2003-04-04 02:44:16 +0000760 if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000761 /* distirbute-list exists, but access-list may not? */
paul020709f2003-04-04 02:44:16 +0000762 if (DISTRIBUTE_LIST (ospf, type))
763 if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
paulcf795c52003-06-19 02:13:25 +0000764 {
765 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000766 zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
ajsf52d13c2005-10-01 17:38:06 +0000767 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000768 inet_ntoa (p->prefix), p->prefixlen);
769 return 0;
770 }
paul718e3742002-12-13 20:15:29 +0000771
772 save_values = ei->route_map_set;
773 ospf_reset_route_map_set_values (&ei->route_map_set);
paulcf795c52003-06-19 02:13:25 +0000774
paul718e3742002-12-13 20:15:29 +0000775 /* apply route-map if needed */
paul020709f2003-04-04 02:44:16 +0000776 if (ROUTEMAP_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000777 {
778 int ret;
779
paulcf795c52003-06-19 02:13:25 +0000780 ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p,
781 RMAP_OSPF, ei);
paul718e3742002-12-13 20:15:29 +0000782
783 if (ret == RMAP_DENYMATCH)
paulcf795c52003-06-19 02:13:25 +0000784 {
785 ei->route_map_set = save_values;
786 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000787 zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.",
ajsf52d13c2005-10-01 17:38:06 +0000788 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000789 inet_ntoa (p->prefix), p->prefixlen);
790 return 0;
791 }
792
paul718e3742002-12-13 20:15:29 +0000793 /* check if 'route-map set' changed something */
794 if (changed)
paulcf795c52003-06-19 02:13:25 +0000795 *changed = !ospf_route_map_set_compare (&ei->route_map_set,
796 &save_values);
paul718e3742002-12-13 20:15:29 +0000797 }
798
799 return 1;
800}
801
802/* OSPF route-map set for redistribution */
803void
paul6c835672004-10-11 11:00:30 +0000804ospf_routemap_set (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000805{
paul020709f2003-04-04 02:44:16 +0000806 if (ROUTEMAP_NAME (ospf, type))
807 free (ROUTEMAP_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000808
paul020709f2003-04-04 02:44:16 +0000809 ROUTEMAP_NAME (ospf, type) = strdup (name);
810 ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);
paul718e3742002-12-13 20:15:29 +0000811}
812
813void
paul020709f2003-04-04 02:44:16 +0000814ospf_routemap_unset (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000815{
paul020709f2003-04-04 02:44:16 +0000816 if (ROUTEMAP_NAME (ospf, type))
817 free (ROUTEMAP_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000818
paul020709f2003-04-04 02:44:16 +0000819 ROUTEMAP_NAME (ospf, type) = NULL;
820 ROUTEMAP (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000821}
822
823/* Zebra route add and delete treatment. */
paul4dadc292005-05-06 21:37:42 +0000824static int
paul718e3742002-12-13 20:15:29 +0000825ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800826 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000827{
828 struct stream *s;
829 struct zapi_ipv4 api;
830 unsigned long ifindex;
831 struct in_addr nexthop;
832 struct prefix_ipv4 p;
833 struct external_info *ei;
paul020709f2003-04-04 02:44:16 +0000834 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000835
836 s = zclient->ibuf;
837 ifindex = 0;
838 nexthop.s_addr = 0;
839
840 /* Type, flags, message. */
841 api.type = stream_getc (s);
842 api.flags = stream_getc (s);
843 api.message = stream_getc (s);
844
845 /* IPv4 prefix. */
846 memset (&p, 0, sizeof (struct prefix_ipv4));
847 p.family = AF_INET;
848 p.prefixlen = stream_getc (s);
849 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
850
hasso8585d4e2004-04-20 17:25:12 +0000851 if (IPV4_NET127(ntohl(p.prefix.s_addr)))
852 return 0;
853
paul718e3742002-12-13 20:15:29 +0000854 /* Nexthop, ifindex, distance, metric. */
855 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
856 {
857 api.nexthop_num = stream_getc (s);
858 nexthop.s_addr = stream_get_ipv4 (s);
859 }
860 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
861 {
862 api.ifindex_num = stream_getc (s);
gdt6a8da852004-02-13 17:40:51 +0000863 /* XXX assert(api.ifindex_num == 1); */
paul718e3742002-12-13 20:15:29 +0000864 ifindex = stream_getl (s);
865 }
866 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
867 api.distance = stream_getc (s);
868 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
869 api.metric = stream_getl (s);
870
paul020709f2003-04-04 02:44:16 +0000871 ospf = ospf_lookup ();
872 if (ospf == NULL)
873 return 0;
874
paul718e3742002-12-13 20:15:29 +0000875 if (command == ZEBRA_IPV4_ROUTE_ADD)
876 {
paul7021c422003-07-15 12:52:22 +0000877 /* XXX|HACK|TODO|FIXME:
hassoa0a39762004-04-23 08:51:10 +0000878 * Maybe we should ignore reject/blackhole routes? Testing shows that
879 * there is no problems though and this is only way to "summarize"
880 * routes in ASBR at the moment. Maybe we need just a better generalised
881 * solution for these types?
882 *
883 * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE)
884 * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
885 * return 0;
paul7021c422003-07-15 12:52:22 +0000886 */
paul7021c422003-07-15 12:52:22 +0000887
paul718e3742002-12-13 20:15:29 +0000888 ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
889
paul68980082003-03-25 05:07:42 +0000890 if (ospf->router_id.s_addr == 0)
paulcf795c52003-06-19 02:13:25 +0000891 /* Set flags to generate AS-external-LSA originate event
892 for each redistributed protocols later. */
893 ospf->external_origin |= (1 << api.type);
paul718e3742002-12-13 20:15:29 +0000894 else
paulcf795c52003-06-19 02:13:25 +0000895 {
896 if (ei)
897 {
898 if (is_prefix_default (&p))
899 ospf_external_lsa_refresh_default (ospf);
900 else
901 {
902 struct ospf_lsa *current;
paul718e3742002-12-13 20:15:29 +0000903
paulcf795c52003-06-19 02:13:25 +0000904 current = ospf_external_info_find_lsa (ospf, &ei->p);
905 if (!current)
906 ospf_external_lsa_originate (ospf, ei);
907 else if (IS_LSA_MAXAGE (current))
908 ospf_external_lsa_refresh (ospf, current,
909 ei, LSA_REFRESH_FORCE);
910 else
911 zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
912 inet_ntoa (p.prefix));
913 }
914 }
915 }
paul718e3742002-12-13 20:15:29 +0000916 }
paulcf795c52003-06-19 02:13:25 +0000917 else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
paul718e3742002-12-13 20:15:29 +0000918 {
919 ospf_external_info_delete (api.type, p);
paul7021c422003-07-15 12:52:22 +0000920 if (is_prefix_default (&p))
paulcf795c52003-06-19 02:13:25 +0000921 ospf_external_lsa_refresh_default (ospf);
paul7021c422003-07-15 12:52:22 +0000922 else
ajs5339cfd2005-09-19 13:28:05 +0000923 ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */);
paul718e3742002-12-13 20:15:29 +0000924 }
925
926 return 0;
927}
David Lamparter6b0655a2014-06-04 06:53:35 +0200928
paulcf795c52003-06-19 02:13:25 +0000929
paul718e3742002-12-13 20:15:29 +0000930int
paul6c835672004-10-11 11:00:30 +0000931ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000932{
933 /* Lookup access-list for distribute-list. */
paul020709f2003-04-04 02:44:16 +0000934 DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
paul718e3742002-12-13 20:15:29 +0000935
936 /* Clear previous distribute-name. */
paul020709f2003-04-04 02:44:16 +0000937 if (DISTRIBUTE_NAME (ospf, type))
938 free (DISTRIBUTE_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000939
940 /* Set distribute-name. */
paul020709f2003-04-04 02:44:16 +0000941 DISTRIBUTE_NAME (ospf, type) = strdup (name);
paul718e3742002-12-13 20:15:29 +0000942
943 /* If access-list have been set, schedule update timer. */
paul020709f2003-04-04 02:44:16 +0000944 if (DISTRIBUTE_LIST (ospf, type))
paul68980082003-03-25 05:07:42 +0000945 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000946
947 return CMD_SUCCESS;
948}
949
950int
paul6c835672004-10-11 11:00:30 +0000951ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000952{
953 /* Schedule update timer. */
paul020709f2003-04-04 02:44:16 +0000954 if (DISTRIBUTE_LIST (ospf, type))
paul68980082003-03-25 05:07:42 +0000955 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000956
957 /* Unset distribute-list. */
paul020709f2003-04-04 02:44:16 +0000958 DISTRIBUTE_LIST (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000959
960 /* Clear distribute-name. */
paul020709f2003-04-04 02:44:16 +0000961 if (DISTRIBUTE_NAME (ospf, type))
962 free (DISTRIBUTE_NAME (ospf, type));
paulcf795c52003-06-19 02:13:25 +0000963
paul020709f2003-04-04 02:44:16 +0000964 DISTRIBUTE_NAME (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000965
966 return CMD_SUCCESS;
967}
968
969/* distribute-list update timer. */
paul4dadc292005-05-06 21:37:42 +0000970static int
paul718e3742002-12-13 20:15:29 +0000971ospf_distribute_list_update_timer (struct thread *thread)
972{
973 struct route_node *rn;
974 struct external_info *ei;
975 struct route_table *rt;
976 struct ospf_lsa *lsa;
Joakim Tjernlund46154fe2010-04-14 16:01:25 +0200977 int type, default_refresh = 0;
paul020709f2003-04-04 02:44:16 +0000978 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000979
paul020709f2003-04-04 02:44:16 +0000980 ospf = ospf_lookup ();
981 if (ospf == NULL)
982 return 0;
983
paul68980082003-03-25 05:07:42 +0000984 ospf->t_distribute_update = NULL;
paul718e3742002-12-13 20:15:29 +0000985
986 zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
987
988 /* foreach all external info. */
Joakim Tjernlund274d3f02010-04-14 11:05:27 +0200989 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
990 {
991 rt = EXTERNAL_INFO (type);
992 if (!rt)
993 continue;
994 for (rn = route_top (rt); rn; rn = route_next (rn))
995 if ((ei = rn->info) != NULL)
996 {
997 if (is_prefix_default (&ei->p))
Joakim Tjernlund46154fe2010-04-14 16:01:25 +0200998 default_refresh = 1;
Joakim Tjernlund274d3f02010-04-14 11:05:27 +0200999 else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
1000 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
1001 else
1002 ospf_external_lsa_originate (ospf, ei);
1003 }
1004 }
Joakim Tjernlund46154fe2010-04-14 16:01:25 +02001005 if (default_refresh)
1006 ospf_external_lsa_refresh_default (ospf);
paul718e3742002-12-13 20:15:29 +00001007 return 0;
1008}
1009
paul718e3742002-12-13 20:15:29 +00001010/* Update distribute-list and set timer to apply access-list. */
1011void
Andrew Certain0798cee2012-12-04 13:43:42 -08001012ospf_distribute_list_update (struct ospf *ospf, uintptr_t type)
paul718e3742002-12-13 20:15:29 +00001013{
1014 struct route_table *rt;
paulcf795c52003-06-19 02:13:25 +00001015
paul718e3742002-12-13 20:15:29 +00001016 /* External info does not exist. */
1017 if (!(rt = EXTERNAL_INFO (type)))
1018 return;
1019
Joakim Tjernlund45acaa02010-04-14 11:05:28 +02001020 /* If exists previously invoked thread, then let it continue. */
paul68980082003-03-25 05:07:42 +00001021 if (ospf->t_distribute_update)
Joakim Tjernlund45acaa02010-04-14 11:05:28 +02001022 return;
paul718e3742002-12-13 20:15:29 +00001023
1024 /* Set timer. */
paul68980082003-03-25 05:07:42 +00001025 ospf->t_distribute_update =
Michael Rossberg2ef762e2015-07-27 07:56:25 +02001026 thread_add_timer_msec (master, ospf_distribute_list_update_timer,
1027 (void *) type, ospf->min_ls_interval);
paul718e3742002-12-13 20:15:29 +00001028}
1029
1030/* If access-list is updated, apply some check. */
paul4dadc292005-05-06 21:37:42 +00001031static void
paul718e3742002-12-13 20:15:29 +00001032ospf_filter_update (struct access_list *access)
1033{
paul020709f2003-04-04 02:44:16 +00001034 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001035 int type;
1036 int abr_inv = 0;
1037 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +00001038 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001039
1040 /* If OSPF instatnce does not exist, return right now. */
paul020709f2003-04-04 02:44:16 +00001041 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001042 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001043 return;
1044
paul718e3742002-12-13 20:15:29 +00001045 /* Update distribute-list, and apply filter. */
hasso01018ce2005-08-05 07:40:15 +00001046 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +00001047 {
paul020709f2003-04-04 02:44:16 +00001048 if (ROUTEMAP (ospf, type) != NULL)
paulcf795c52003-06-19 02:13:25 +00001049 {
1050 /* if route-map is not NULL it may be using this access list */
1051 ospf_distribute_list_update (ospf, type);
1052 continue;
1053 }
1054
hasso01018ce2005-08-05 07:40:15 +00001055 /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX),
1056 * but no distribute list. */
1057 if (type == ZEBRA_ROUTE_MAX)
1058 break;
paul718e3742002-12-13 20:15:29 +00001059
paul020709f2003-04-04 02:44:16 +00001060 if (DISTRIBUTE_NAME (ospf, type))
paulcf795c52003-06-19 02:13:25 +00001061 {
1062 /* Keep old access-list for distribute-list. */
1063 struct access_list *old = DISTRIBUTE_LIST (ospf, type);
1064
1065 /* Update access-list for distribute-list. */
1066 DISTRIBUTE_LIST (ospf, type) =
1067 access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type));
1068
1069 /* No update for this distribute type. */
1070 if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL)
1071 continue;
1072
1073 /* Schedule distribute-list update timer. */
1074 if (DISTRIBUTE_LIST (ospf, type) == NULL ||
1075 strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
1076 ospf_distribute_list_update (ospf, type);
1077 }
paul718e3742002-12-13 20:15:29 +00001078 }
1079
1080 /* Update Area access-list. */
paul1eb8ef22005-04-07 07:30:20 +00001081 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1082 {
1083 if (EXPORT_NAME (area))
1084 {
1085 EXPORT_LIST (area) = NULL;
1086 abr_inv++;
1087 }
paul718e3742002-12-13 20:15:29 +00001088
paul1eb8ef22005-04-07 07:30:20 +00001089 if (IMPORT_NAME (area))
1090 {
1091 IMPORT_LIST (area) = NULL;
1092 abr_inv++;
1093 }
1094 }
paul718e3742002-12-13 20:15:29 +00001095
1096 /* Schedule ABR tasks -- this will be changed -- takada. */
paul020709f2003-04-04 02:44:16 +00001097 if (IS_OSPF_ABR (ospf) && abr_inv)
paul68980082003-03-25 05:07:42 +00001098 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001099}
hassodd669bb2004-05-10 07:43:59 +00001100
1101/* If prefix-list is updated, do some updates. */
1102void
1103ospf_prefix_list_update (struct prefix_list *plist)
1104{
1105 struct ospf *ospf;
1106 int type;
1107 int abr_inv = 0;
1108 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +00001109 struct listnode *node;
hassodd669bb2004-05-10 07:43:59 +00001110
1111 /* If OSPF instatnce does not exist, return right now. */
1112 ospf = ospf_lookup ();
1113 if (ospf == NULL)
1114 return;
1115
1116 /* Update all route-maps which are used as redistribution filters.
1117 * They might use prefix-list.
1118 */
hasso01018ce2005-08-05 07:40:15 +00001119 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
hassodd669bb2004-05-10 07:43:59 +00001120 {
1121 if (ROUTEMAP (ospf, type) != NULL)
1122 {
1123 /* If route-map is not NULL it may be using this prefix list */
1124 ospf_distribute_list_update (ospf, type);
1125 continue;
1126 }
1127 }
1128
1129 /* Update area filter-lists. */
paul1eb8ef22005-04-07 07:30:20 +00001130 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1131 {
1132 /* Update filter-list in. */
1133 if (PREFIX_NAME_IN (area))
David Lampartere66cbd12015-04-13 10:21:34 +02001134 if (strcmp (PREFIX_NAME_IN (area), prefix_list_name (plist)) == 0)
paul1eb8ef22005-04-07 07:30:20 +00001135 {
1136 PREFIX_LIST_IN (area) =
1137 prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
1138 abr_inv++;
1139 }
hassodd669bb2004-05-10 07:43:59 +00001140
paul1eb8ef22005-04-07 07:30:20 +00001141 /* Update filter-list out. */
1142 if (PREFIX_NAME_OUT (area))
David Lampartere66cbd12015-04-13 10:21:34 +02001143 if (strcmp (PREFIX_NAME_OUT (area), prefix_list_name (plist)) == 0)
paul1eb8ef22005-04-07 07:30:20 +00001144 {
1145 PREFIX_LIST_IN (area) =
1146 prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
1147 abr_inv++;
1148 }
1149 }
hassodd669bb2004-05-10 07:43:59 +00001150
1151 /* Schedule ABR task. */
1152 if (IS_OSPF_ABR (ospf) && abr_inv)
1153 ospf_schedule_abr_task (ospf);
1154}
paulcf795c52003-06-19 02:13:25 +00001155
paul4dadc292005-05-06 21:37:42 +00001156static struct ospf_distance *
1157ospf_distance_new (void)
paul718e3742002-12-13 20:15:29 +00001158{
Stephen Hemminger393deb92008-08-18 14:13:29 -07001159 return XCALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
paul718e3742002-12-13 20:15:29 +00001160}
1161
paul4dadc292005-05-06 21:37:42 +00001162static void
paul718e3742002-12-13 20:15:29 +00001163ospf_distance_free (struct ospf_distance *odistance)
1164{
1165 XFREE (MTYPE_OSPF_DISTANCE, odistance);
1166}
1167
1168int
paul6c835672004-10-11 11:00:30 +00001169ospf_distance_set (struct vty *vty, struct ospf *ospf,
1170 const char *distance_str,
1171 const char *ip_str,
1172 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00001173{
1174 int ret;
1175 struct prefix_ipv4 p;
1176 u_char distance;
1177 struct route_node *rn;
1178 struct ospf_distance *odistance;
1179
1180 ret = str2prefix_ipv4 (ip_str, &p);
1181 if (ret == 0)
1182 {
1183 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1184 return CMD_WARNING;
1185 }
1186
1187 distance = atoi (distance_str);
1188
1189 /* Get OSPF distance node. */
paul68980082003-03-25 05:07:42 +00001190 rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +00001191 if (rn->info)
1192 {
1193 odistance = rn->info;
1194 route_unlock_node (rn);
1195 }
1196 else
1197 {
1198 odistance = ospf_distance_new ();
1199 rn->info = odistance;
1200 }
1201
1202 /* Set distance value. */
1203 odistance->distance = distance;
1204
1205 /* Reset access-list configuration. */
1206 if (odistance->access_list)
1207 {
1208 free (odistance->access_list);
1209 odistance->access_list = NULL;
1210 }
1211 if (access_list_str)
1212 odistance->access_list = strdup (access_list_str);
1213
1214 return CMD_SUCCESS;
1215}
1216
1217int
paul6c835672004-10-11 11:00:30 +00001218ospf_distance_unset (struct vty *vty, struct ospf *ospf,
1219 const char *distance_str,
1220 const char *ip_str, char
1221 const *access_list_str)
paul718e3742002-12-13 20:15:29 +00001222{
1223 int ret;
1224 struct prefix_ipv4 p;
paul718e3742002-12-13 20:15:29 +00001225 struct route_node *rn;
1226 struct ospf_distance *odistance;
1227
1228 ret = str2prefix_ipv4 (ip_str, &p);
1229 if (ret == 0)
1230 {
1231 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1232 return CMD_WARNING;
1233 }
1234
paulcf795c52003-06-19 02:13:25 +00001235 rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p);
1236 if (!rn)
paul718e3742002-12-13 20:15:29 +00001237 {
1238 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
1239 return CMD_WARNING;
1240 }
1241
1242 odistance = rn->info;
1243
1244 if (odistance->access_list)
1245 free (odistance->access_list);
1246 ospf_distance_free (odistance);
1247
1248 rn->info = NULL;
1249 route_unlock_node (rn);
1250 route_unlock_node (rn);
1251
1252 return CMD_SUCCESS;
1253}
1254
1255void
paul68980082003-03-25 05:07:42 +00001256ospf_distance_reset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001257{
1258 struct route_node *rn;
1259 struct ospf_distance *odistance;
1260
paul68980082003-03-25 05:07:42 +00001261 for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001262 if ((odistance = rn->info) != NULL)
1263 {
paulcf795c52003-06-19 02:13:25 +00001264 if (odistance->access_list)
1265 free (odistance->access_list);
1266 ospf_distance_free (odistance);
1267 rn->info = NULL;
1268 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001269 }
1270}
1271
1272u_char
1273ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
1274{
paul020709f2003-04-04 02:44:16 +00001275 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001276
paul020709f2003-04-04 02:44:16 +00001277 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001278 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001279 return 0;
1280
paul68980082003-03-25 05:07:42 +00001281 if (ospf->distance_intra)
paul718e3742002-12-13 20:15:29 +00001282 if (or->path_type == OSPF_PATH_INTRA_AREA)
paul68980082003-03-25 05:07:42 +00001283 return ospf->distance_intra;
paul718e3742002-12-13 20:15:29 +00001284
paul68980082003-03-25 05:07:42 +00001285 if (ospf->distance_inter)
paul718e3742002-12-13 20:15:29 +00001286 if (or->path_type == OSPF_PATH_INTER_AREA)
paul68980082003-03-25 05:07:42 +00001287 return ospf->distance_inter;
paul718e3742002-12-13 20:15:29 +00001288
paul68980082003-03-25 05:07:42 +00001289 if (ospf->distance_external)
paul718e3742002-12-13 20:15:29 +00001290 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
paulcf795c52003-06-19 02:13:25 +00001291 || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
paul68980082003-03-25 05:07:42 +00001292 return ospf->distance_external;
paulcf795c52003-06-19 02:13:25 +00001293
paul68980082003-03-25 05:07:42 +00001294 if (ospf->distance_all)
1295 return ospf->distance_all;
paul718e3742002-12-13 20:15:29 +00001296
1297 return 0;
1298}
1299
Feng Luc99f3482014-10-16 09:52:36 +08001300static void
1301ospf_zebra_connected (struct zclient *zclient)
1302{
1303 zclient_send_requests (zclient, VRF_DEFAULT);
1304}
1305
paul718e3742002-12-13 20:15:29 +00001306void
1307ospf_zebra_init ()
1308{
1309 /* Allocate zebra structure. */
1310 zclient = zclient_new ();
1311 zclient_init (zclient, ZEBRA_ROUTE_OSPF);
Feng Luc99f3482014-10-16 09:52:36 +08001312 zclient->zebra_connected = ospf_zebra_connected;
hasso18a6dce2004-10-03 18:18:34 +00001313 zclient->router_id_update = ospf_router_id_update_zebra;
paul718e3742002-12-13 20:15:29 +00001314 zclient->interface_add = ospf_interface_add;
1315 zclient->interface_delete = ospf_interface_delete;
1316 zclient->interface_up = ospf_interface_state_up;
1317 zclient->interface_down = ospf_interface_state_down;
1318 zclient->interface_address_add = ospf_interface_address_add;
1319 zclient->interface_address_delete = ospf_interface_address_delete;
1320 zclient->ipv4_route_add = ospf_zebra_read_ipv4;
1321 zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
1322
1323 access_list_add_hook (ospf_filter_update);
1324 access_list_delete_hook (ospf_filter_update);
hassodd669bb2004-05-10 07:43:59 +00001325 prefix_list_add_hook (ospf_prefix_list_update);
1326 prefix_list_delete_hook (ospf_prefix_list_update);
paul718e3742002-12-13 20:15:29 +00001327}