blob: f302d28d60827d026f378db046d511278a008b2b [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,
62 zebra_size_t length)
63{
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
paul718e3742002-12-13 20:15:29 +000087ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
88{
89 struct interface *ifp;
paul020709f2003-04-04 02:44:16 +000090 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +000091
92 ifp = zebra_interface_add_read (zclient->ibuf);
93
94 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +000095 zlog_debug ("Zebra: interface add %s index %d flags %ld metric %d mtu %d",
paulcf795c52003-06-19 02:13:25 +000096 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
paul718e3742002-12-13 20:15:29 +000097
paulcf795c52003-06-19 02:13:25 +000098 assert (ifp->info);
paulf2c80652002-12-13 21:44:27 +000099
paul718e3742002-12-13 20:15:29 +0000100 if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
101 {
102 SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
ajsbc18d612004-12-15 15:07:19 +0000103 IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp);
paul718e3742002-12-13 20:15:29 +0000104 }
105
paul020709f2003-04-04 02:44:16 +0000106 ospf = ospf_lookup ();
107 if (ospf != NULL)
108 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000109
110#ifdef HAVE_SNMP
111 ospf_snmp_if_update (ifp);
112#endif /* HAVE_SNMP */
113
114 return 0;
115}
116
paul4dadc292005-05-06 21:37:42 +0000117static int
paul718e3742002-12-13 20:15:29 +0000118ospf_interface_delete (int command, struct zclient *zclient,
paulcf795c52003-06-19 02:13:25 +0000119 zebra_size_t length)
paul718e3742002-12-13 20:15:29 +0000120{
121 struct interface *ifp;
122 struct stream *s;
123 struct route_node *rn;
124
paulcf795c52003-06-19 02:13:25 +0000125 s = zclient->ibuf;
paul718e3742002-12-13 20:15:29 +0000126 /* zebra_interface_state_read() updates interface structure in iflist */
127 ifp = zebra_interface_state_read (s);
128
129 if (ifp == NULL)
130 return 0;
131
132 if (if_is_up (ifp))
133 zlog_warn ("Zebra: got delete of %s, but interface is still up",
paulcf795c52003-06-19 02:13:25 +0000134 ifp->name);
135
paul718e3742002-12-13 20:15:29 +0000136 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000137 zlog_debug
paulcf795c52003-06-19 02:13:25 +0000138 ("Zebra: interface delete %s index %d flags %ld metric %d mtu %d",
139 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
paul718e3742002-12-13 20:15:29 +0000140
141#ifdef HAVE_SNMP
142 ospf_snmp_if_delete (ifp);
143#endif /* HAVE_SNMP */
144
145 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
146 if (rn->info)
147 ospf_if_free ((struct ospf_interface *) rn->info);
148
ajsd2fc8892005-04-02 18:38:43 +0000149 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000150 return 0;
151}
152
ajsd2fc8892005-04-02 18:38:43 +0000153static struct interface *
paul718e3742002-12-13 20:15:29 +0000154zebra_interface_if_lookup (struct stream *s)
155{
ajs21fefa92005-04-02 23:16:41 +0000156 char ifname_tmp[INTERFACE_NAMSIZ];
paul718e3742002-12-13 20:15:29 +0000157
158 /* Read interface name. */
159 stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
160
ajsd2fc8892005-04-02 18:38:43 +0000161 /* And look it up. */
ajs21fefa92005-04-02 23:16:41 +0000162 return if_lookup_by_name_len(ifname_tmp,
163 strnlen(ifname_tmp, INTERFACE_NAMSIZ));
paul718e3742002-12-13 20:15:29 +0000164}
165
paul4dadc292005-05-06 21:37:42 +0000166static int
paul718e3742002-12-13 20:15:29 +0000167ospf_interface_state_up (int command, struct zclient *zclient,
paulcf795c52003-06-19 02:13:25 +0000168 zebra_size_t length)
paul718e3742002-12-13 20:15:29 +0000169{
170 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +0000171 struct ospf_interface *oi;
172 struct route_node *rn;
paulcf795c52003-06-19 02:13:25 +0000173
paul718e3742002-12-13 20:15:29 +0000174 ifp = zebra_interface_if_lookup (zclient->ibuf);
175
176 if (ifp == NULL)
177 return 0;
178
179 /* Interface is already up. */
paul2e3b2e42002-12-13 21:03:13 +0000180 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000181 {
182 /* Temporarily keep ifp values. */
ajsa608bbf2005-03-29 17:03:49 +0000183 struct interface if_tmp;
paul718e3742002-12-13 20:15:29 +0000184 memcpy (&if_tmp, ifp, sizeof (struct interface));
185
186 zebra_interface_if_set_value (zclient->ibuf, ifp);
187
188 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000189 zlog_debug ("Zebra: Interface[%s] state update.", ifp->name);
paul718e3742002-12-13 20:15:29 +0000190
191 if (if_tmp.bandwidth != ifp->bandwidth)
paulcf795c52003-06-19 02:13:25 +0000192 {
193 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000194 zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.",
paulcf795c52003-06-19 02:13:25 +0000195 ifp->name, if_tmp.bandwidth, ifp->bandwidth);
paul718e3742002-12-13 20:15:29 +0000196
paulcf795c52003-06-19 02:13:25 +0000197 ospf_if_recalculate_output_cost (ifp);
198 }
ajsa608bbf2005-03-29 17:03:49 +0000199
200 if (if_tmp.mtu != ifp->mtu)
201 {
202 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
203 zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.",
204 ifp->name, if_tmp.mtu, ifp->mtu);
205
206 /* Must reset the interface (simulate down/up) when MTU changes. */
207 ospf_if_reset(ifp);
208 }
paul718e3742002-12-13 20:15:29 +0000209 return 0;
210 }
paulcf795c52003-06-19 02:13:25 +0000211
paul718e3742002-12-13 20:15:29 +0000212 zebra_interface_if_set_value (zclient->ibuf, ifp);
paulcf795c52003-06-19 02:13:25 +0000213
paul718e3742002-12-13 20:15:29 +0000214 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000215 zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name);
paulcf795c52003-06-19 02:13:25 +0000216
217 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000218 {
paulcf795c52003-06-19 02:13:25 +0000219 if ((oi = rn->info) == NULL)
220 continue;
221
paul718e3742002-12-13 20:15:29 +0000222 ospf_if_up (oi);
223 }
paulcf795c52003-06-19 02:13:25 +0000224
paul718e3742002-12-13 20:15:29 +0000225 return 0;
226}
227
paul4dadc292005-05-06 21:37:42 +0000228static int
paul718e3742002-12-13 20:15:29 +0000229ospf_interface_state_down (int command, struct zclient *zclient,
paulcf795c52003-06-19 02:13:25 +0000230 zebra_size_t length)
paul718e3742002-12-13 20:15:29 +0000231{
232 struct interface *ifp;
233 struct ospf_interface *oi;
234 struct route_node *node;
235
236 ifp = zebra_interface_state_read (zclient->ibuf);
237
238 if (ifp == NULL)
239 return 0;
240
241 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
ajs9b0e25c2004-12-08 19:06:51 +0000242 zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name);
paul718e3742002-12-13 20:15:29 +0000243
paulcf795c52003-06-19 02:13:25 +0000244 for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
paul718e3742002-12-13 20:15:29 +0000245 {
paulcf795c52003-06-19 02:13:25 +0000246 if ((oi = node->info) == NULL)
247 continue;
paul718e3742002-12-13 20:15:29 +0000248 ospf_if_down (oi);
249 }
250
251 return 0;
252}
253
paul4dadc292005-05-06 21:37:42 +0000254static int
paul718e3742002-12-13 20:15:29 +0000255ospf_interface_address_add (int command, struct zclient *zclient,
paulcf795c52003-06-19 02:13:25 +0000256 zebra_size_t length)
paul718e3742002-12-13 20:15:29 +0000257{
paul020709f2003-04-04 02:44:16 +0000258 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000259 struct connected *c;
260
paul0a589352004-05-08 11:48:26 +0000261 c = zebra_interface_address_read (command, zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000262
263 if (c == NULL)
264 return 0;
265
Andrew J. Schorr7f643eb2006-11-30 16:17:02 +0000266 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
267 {
268 char buf[128];
269 prefix2str(c->address, buf, sizeof(buf));
270 zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
271 }
272
paul020709f2003-04-04 02:44:16 +0000273 ospf = ospf_lookup ();
274 if (ospf != NULL)
275 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000276
277#ifdef HAVE_SNMP
278 ospf_snmp_if_update (c->ifp);
279#endif /* HAVE_SNMP */
280
281 return 0;
282}
283
paul4dadc292005-05-06 21:37:42 +0000284static int
paul718e3742002-12-13 20:15:29 +0000285ospf_interface_address_delete (int command, struct zclient *zclient,
paulcf795c52003-06-19 02:13:25 +0000286 zebra_size_t length)
paul718e3742002-12-13 20:15:29 +0000287{
paul020709f2003-04-04 02:44:16 +0000288 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000289 struct connected *c;
290 struct interface *ifp;
291 struct ospf_interface *oi;
292 struct route_node *rn;
293 struct prefix p;
294
paul0a589352004-05-08 11:48:26 +0000295 c = zebra_interface_address_read (command, zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000296
297 if (c == NULL)
298 return 0;
299
Andrew J. Schorr7f643eb2006-11-30 16:17:02 +0000300 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
301 {
302 char buf[128];
303 prefix2str(c->address, buf, sizeof(buf));
304 zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf);
305 }
306
paul718e3742002-12-13 20:15:29 +0000307 ifp = c->ifp;
308 p = *c->address;
309 p.prefixlen = IPV4_MAX_PREFIXLEN;
310
311 rn = route_node_lookup (IF_OIFS (ifp), &p);
paulcf795c52003-06-19 02:13:25 +0000312 if (!rn)
paul98429f62006-01-10 22:11:54 +0000313 {
314 connected_free (c);
315 return 0;
316 }
paul718e3742002-12-13 20:15:29 +0000317
318 assert (rn->info);
319 oi = rn->info;
paulcf795c52003-06-19 02:13:25 +0000320
paul718e3742002-12-13 20:15:29 +0000321 /* Call interface hook functions to clean up */
322 ospf_if_free (oi);
paulcf795c52003-06-19 02:13:25 +0000323
paul718e3742002-12-13 20:15:29 +0000324#ifdef HAVE_SNMP
325 ospf_snmp_if_update (c->ifp);
326#endif /* HAVE_SNMP */
327
328 connected_free (c);
329
paul020709f2003-04-04 02:44:16 +0000330 ospf = ospf_lookup ();
331 if (ospf != NULL)
332 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000333
334 return 0;
335}
paul72357f22003-06-19 02:11:23 +0000336
paul718e3742002-12-13 20:15:29 +0000337void
338ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
339{
340 u_char message;
341 u_char distance;
342 u_char flags;
343 int psize;
344 struct stream *s;
345 struct ospf_path *path;
hasso52dc7ee2004-09-23 19:18:23 +0000346 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000347
348 if (zclient->redist[ZEBRA_ROUTE_OSPF])
349 {
350 message = 0;
351 flags = 0;
352
353 /* OSPF pass nexthop and metric */
354 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
355 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
356
357 /* Distance value. */
358 distance = ospf_distance_apply (p, or);
359 if (distance)
paul72357f22003-06-19 02:11:23 +0000360 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
paul718e3742002-12-13 20:15:29 +0000361
362 /* Make packet. */
363 s = zclient->obuf;
364 stream_reset (s);
365
paul718e3742002-12-13 20:15:29 +0000366 /* Put command, type, flags, message. */
paulc6371712006-01-17 17:49:53 +0000367 zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD);
paul718e3742002-12-13 20:15:29 +0000368 stream_putc (s, ZEBRA_ROUTE_OSPF);
369 stream_putc (s, flags);
370 stream_putc (s, message);
paulcf795c52003-06-19 02:13:25 +0000371
paul718e3742002-12-13 20:15:29 +0000372 /* Put prefix information. */
373 psize = PSIZE (p->prefixlen);
374 stream_putc (s, p->prefixlen);
paulcf795c52003-06-19 02:13:25 +0000375 stream_write (s, (u_char *) & p->prefix, psize);
paul718e3742002-12-13 20:15:29 +0000376
377 /* Nexthop count. */
paul96735ee2003-08-10 02:51:22 +0000378 stream_putc (s, or->paths->count);
paul718e3742002-12-13 20:15:29 +0000379
380 /* Nexthop, ifindex, distance and metric information. */
paul1eb8ef22005-04-07 07:30:20 +0000381 for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
paul72357f22003-06-19 02:11:23 +0000382 {
paulcf795c52003-06-19 02:13:25 +0000383 if (path->nexthop.s_addr != INADDR_ANY)
384 {
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);
391 if (path->oi)
392 stream_putl (s, path->oi->ifp->ifindex);
393 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{
430 struct zapi_ipv4 api;
paul72357f22003-06-19 02:11:23 +0000431 struct ospf_path *path;
432 struct in_addr *nexthop;
paul1eb8ef22005-04-07 07:30:20 +0000433 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000434
435 if (zclient->redist[ZEBRA_ROUTE_OSPF])
436 {
437 api.type = ZEBRA_ROUTE_OSPF;
438 api.flags = 0;
439 api.message = 0;
paul72357f22003-06-19 02:11:23 +0000440 api.ifindex_num = 0;
441 api.nexthop_num = 0;
paul718e3742002-12-13 20:15:29 +0000442
paul1eb8ef22005-04-07 07:30:20 +0000443 for (ALL_LIST_ELEMENTS (or->paths, node, nnode, path))
paulcf795c52003-06-19 02:13:25 +0000444 {
paulcf795c52003-06-19 02:13:25 +0000445 if (path->nexthop.s_addr != INADDR_ANY)
446 {
pauld8e1d6b2003-08-10 04:04:41 +0000447 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
paulcf795c52003-06-19 02:13:25 +0000448 api.nexthop_num = 1;
449 nexthop = &path->nexthop;
450 api.nexthop = &nexthop;
451 }
hasso2db3d052004-02-11 21:52:13 +0000452 else if (ospf_if_exists(path->oi) && (path->oi->ifp))
paulbb8ff1e2003-08-12 06:00:30 +0000453 {
454 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
455 api.ifindex_num = 1;
456 api.ifindex = &path->oi->ifp->ifindex;
457 }
458 else if ( IS_DEBUG_OSPF(zebra,ZEBRA_REDISTRIBUTE) )
459 {
ajs9b0e25c2004-12-08 19:06:51 +0000460 zlog_debug("Zebra: no ifp %s %d",
paulbb8ff1e2003-08-12 06:00:30 +0000461 inet_ntoa(p->prefix),
462 p->prefixlen);
463 }
paul72357f22003-06-19 02:11:23 +0000464
paul0a589352004-05-08 11:48:26 +0000465 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
paul72357f22003-06-19 02:11:23 +0000466
467 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.nexthop_num)
paulcf795c52003-06-19 02:13:25 +0000468 {
Andrew J. Schorr56b3ea02007-03-14 20:21:43 +0000469 char buf[2][INET_ADDRSTRLEN];
470 zlog_debug("Zebra: Route delete %s/%d nexthop %s",
471 inet_ntop(AF_INET, &p->prefix, buf[0], sizeof(buf[0])),
472 p->prefixlen,
473 inet_ntop(AF_INET, *api.nexthop,
474 buf[1], sizeof(buf[1])));
paulcf795c52003-06-19 02:13:25 +0000475 }
paulbb8ff1e2003-08-12 06:00:30 +0000476 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.ifindex_num)
477 {
ajs9b0e25c2004-12-08 19:06:51 +0000478 zlog_debug ("Zebra: Route delete %s/%d ifindex %d",
paulbb8ff1e2003-08-12 06:00:30 +0000479 inet_ntoa (p->prefix),
480 p->prefixlen, *api.ifindex);
481 }
paulcf795c52003-06-19 02:13:25 +0000482 }
paul718e3742002-12-13 20:15:29 +0000483 }
484}
485
486void
487ospf_zebra_add_discard (struct prefix_ipv4 *p)
488{
489 struct zapi_ipv4 api;
490
491 if (zclient->redist[ZEBRA_ROUTE_OSPF])
492 {
493 api.type = ZEBRA_ROUTE_OSPF;
494 api.flags = ZEBRA_FLAG_BLACKHOLE;
495 api.message = 0;
496 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
497 api.nexthop_num = 0;
498 api.ifindex_num = 0;
499
paul0a589352004-05-08 11:48:26 +0000500 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
Andrew J. Schorr7f643eb2006-11-30 16:17:02 +0000501
502 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
503 zlog_debug ("Zebra: Route add discard %s/%d",
504 inet_ntoa (p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +0000505 }
506}
507
508void
509ospf_zebra_delete_discard (struct prefix_ipv4 *p)
510{
511 struct zapi_ipv4 api;
512
513 if (zclient->redist[ZEBRA_ROUTE_OSPF])
514 {
515 api.type = ZEBRA_ROUTE_OSPF;
516 api.flags = ZEBRA_FLAG_BLACKHOLE;
517 api.message = 0;
518 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
519 api.nexthop_num = 0;
520 api.ifindex_num = 0;
521
paul0a589352004-05-08 11:48:26 +0000522 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
paul72357f22003-06-19 02:11:23 +0000523
524 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000525 zlog_debug ("Zebra: Route delete discard %s/%d",
paulcf795c52003-06-19 02:13:25 +0000526 inet_ntoa (p->prefix), p->prefixlen);
paul72357f22003-06-19 02:11:23 +0000527
paul718e3742002-12-13 20:15:29 +0000528 }
529}
530
531int
532ospf_is_type_redistributed (int type)
533{
534 return (DEFAULT_ROUTE_TYPE (type)) ?
535 zclient->default_information : zclient->redist[type];
536}
537
538int
paul020709f2003-04-04 02:44:16 +0000539ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue)
paul718e3742002-12-13 20:15:29 +0000540{
541 int force = 0;
paulcf795c52003-06-19 02:13:25 +0000542
paul718e3742002-12-13 20:15:29 +0000543 if (ospf_is_type_redistributed (type))
544 {
paul68980082003-03-25 05:07:42 +0000545 if (mtype != ospf->dmetric[type].type)
paulcf795c52003-06-19 02:13:25 +0000546 {
547 ospf->dmetric[type].type = mtype;
548 force = LSA_REFRESH_FORCE;
549 }
paul68980082003-03-25 05:07:42 +0000550 if (mvalue != ospf->dmetric[type].value)
paulcf795c52003-06-19 02:13:25 +0000551 {
552 ospf->dmetric[type].value = mvalue;
553 force = LSA_REFRESH_FORCE;
554 }
555
paul68980082003-03-25 05:07:42 +0000556 ospf_external_lsa_refresh_type (ospf, type, force);
paulcf795c52003-06-19 02:13:25 +0000557
paul718e3742002-12-13 20:15:29 +0000558 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000559 zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000560 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000561 metric_type (ospf, type), metric_value (ospf, type));
562
paul718e3742002-12-13 20:15:29 +0000563 return CMD_SUCCESS;
564 }
565
paul68980082003-03-25 05:07:42 +0000566 ospf->dmetric[type].type = mtype;
567 ospf->dmetric[type].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000568
paul0a589352004-05-08 11:48:26 +0000569 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
paul718e3742002-12-13 20:15:29 +0000570
571 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000572 zlog_debug ("Redistribute[%s]: Start Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000573 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000574 metric_type (ospf, type), metric_value (ospf, type));
575
paul68980082003-03-25 05:07:42 +0000576 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000577
578 return CMD_SUCCESS;
579}
580
581int
paul020709f2003-04-04 02:44:16 +0000582ospf_redistribute_unset (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000583{
584 if (type == zclient->redist_default)
585 return CMD_SUCCESS;
586
paulcf795c52003-06-19 02:13:25 +0000587 if (!ospf_is_type_redistributed (type))
paul718e3742002-12-13 20:15:29 +0000588 return CMD_SUCCESS;
589
paul0a589352004-05-08 11:48:26 +0000590 zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
paulcf795c52003-06-19 02:13:25 +0000591
paul718e3742002-12-13 20:15:29 +0000592 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000593 zlog_debug ("Redistribute[%s]: Stop",
ajsf52d13c2005-10-01 17:38:06 +0000594 ospf_redist_string(type));
paul718e3742002-12-13 20:15:29 +0000595
paul68980082003-03-25 05:07:42 +0000596 ospf->dmetric[type].type = -1;
597 ospf->dmetric[type].value = -1;
paul718e3742002-12-13 20:15:29 +0000598
599 /* Remove the routes from OSPF table. */
Paul Jakma6db3a6f2006-05-12 23:02:46 +0000600 ospf_redistribute_withdraw (ospf, type);
paul718e3742002-12-13 20:15:29 +0000601
paul68980082003-03-25 05:07:42 +0000602 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000603
604 return CMD_SUCCESS;
605}
606
607int
paul020709f2003-04-04 02:44:16 +0000608ospf_redistribute_default_set (struct ospf *ospf, int originate,
paulcf795c52003-06-19 02:13:25 +0000609 int mtype, int mvalue)
paul718e3742002-12-13 20:15:29 +0000610{
Andrew J. Schorr8fb8a502006-10-24 19:04:26 +0000611 ospf->default_originate = originate;
612 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
613 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
paul020709f2003-04-04 02:44:16 +0000614
paul718e3742002-12-13 20:15:29 +0000615 if (ospf_is_type_redistributed (DEFAULT_ROUTE))
616 {
Andrew J. Schorr8fb8a502006-10-24 19:04:26 +0000617 /* if ospf->default_originate changes value, is calling
618 ospf_external_lsa_refresh_default sufficient to implement
619 the change? */
paul68980082003-03-25 05:07:42 +0000620 ospf_external_lsa_refresh_default (ospf);
paulcf795c52003-06-19 02:13:25 +0000621
paul718e3742002-12-13 20:15:29 +0000622 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000623 zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
ajsf52d13c2005-10-01 17:38:06 +0000624 ospf_redist_string(DEFAULT_ROUTE),
paulcf795c52003-06-19 02:13:25 +0000625 metric_type (ospf, DEFAULT_ROUTE),
626 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000627 return CMD_SUCCESS;
628 }
629
paul0a589352004-05-08 11:48:26 +0000630 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient);
paulcf795c52003-06-19 02:13:25 +0000631
paul718e3742002-12-13 20:15:29 +0000632 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000633 zlog_debug ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
paulcf795c52003-06-19 02:13:25 +0000634 metric_type (ospf, DEFAULT_ROUTE),
635 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000636
paul68980082003-03-25 05:07:42 +0000637 if (ospf->router_id.s_addr == 0)
638 ospf->external_origin |= (1 << DEFAULT_ROUTE);
paul718e3742002-12-13 20:15:29 +0000639 else
Paul Jakma4021b602006-05-12 22:55:41 +0000640 thread_add_timer (master, ospf_default_originate_timer, ospf, 1);
paul718e3742002-12-13 20:15:29 +0000641
paul68980082003-03-25 05:07:42 +0000642 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000643
644 return CMD_SUCCESS;
645}
646
647int
paul020709f2003-04-04 02:44:16 +0000648ospf_redistribute_default_unset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000649{
650 if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
651 return CMD_SUCCESS;
652
paul68980082003-03-25 05:07:42 +0000653 ospf->default_originate = DEFAULT_ORIGINATE_NONE;
654 ospf->dmetric[DEFAULT_ROUTE].type = -1;
655 ospf->dmetric[DEFAULT_ROUTE].value = -1;
paul718e3742002-12-13 20:15:29 +0000656
paul0a589352004-05-08 11:48:26 +0000657 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient);
paul718e3742002-12-13 20:15:29 +0000658
659 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000660 zlog_debug ("Redistribute[DEFAULT]: Stop");
paulcf795c52003-06-19 02:13:25 +0000661
paul68980082003-03-25 05:07:42 +0000662 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000663
664 return CMD_SUCCESS;
665}
666
paul4dadc292005-05-06 21:37:42 +0000667static int
paul020709f2003-04-04 02:44:16 +0000668ospf_external_lsa_originate_check (struct ospf *ospf,
paulcf795c52003-06-19 02:13:25 +0000669 struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000670{
671 /* If prefix is multicast, then do not originate LSA. */
672 if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
673 {
674 zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
paulcf795c52003-06-19 02:13:25 +0000675 "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
paul718e3742002-12-13 20:15:29 +0000676 return 0;
677 }
678
679 /* Take care of default-originate. */
680 if (is_prefix_default (&ei->p))
paul68980082003-03-25 05:07:42 +0000681 if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
paul718e3742002-12-13 20:15:29 +0000682 {
paulcf795c52003-06-19 02:13:25 +0000683 zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-exntenal-LSA "
684 "for default");
685 return 0;
paul718e3742002-12-13 20:15:29 +0000686 }
687
688 return 1;
689}
690
691/* If connected prefix is OSPF enable interface, then do not announce. */
692int
paulcf795c52003-06-19 02:13:25 +0000693ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000694{
695 struct route_node *rn;
696
paul68980082003-03-25 05:07:42 +0000697 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000698 if (rn->info != NULL)
paulcf795c52003-06-19 02:13:25 +0000699 if (prefix_match (&rn->p, (struct prefix *) &ei->p))
700 {
701 route_unlock_node (rn);
702 return 0;
703 }
paul718e3742002-12-13 20:15:29 +0000704
705 return 1;
706}
707
708/* return 1 if external LSA must be originated, 0 otherwise */
709int
paul68980082003-03-25 05:07:42 +0000710ospf_redistribute_check (struct ospf *ospf,
paulcf795c52003-06-19 02:13:25 +0000711 struct external_info *ei, int *changed)
paul718e3742002-12-13 20:15:29 +0000712{
713 struct route_map_set_values save_values;
714 struct prefix_ipv4 *p = &ei->p;
715 u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
paulcf795c52003-06-19 02:13:25 +0000716
paul718e3742002-12-13 20:15:29 +0000717 if (changed)
718 *changed = 0;
719
paul020709f2003-04-04 02:44:16 +0000720 if (!ospf_external_lsa_originate_check (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000721 return 0;
722
723 /* Take care connected route. */
paul68980082003-03-25 05:07:42 +0000724 if (type == ZEBRA_ROUTE_CONNECT &&
725 !ospf_distribute_check_connected (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000726 return 0;
727
paul020709f2003-04-04 02:44:16 +0000728 if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000729 /* distirbute-list exists, but access-list may not? */
paul020709f2003-04-04 02:44:16 +0000730 if (DISTRIBUTE_LIST (ospf, type))
731 if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
paulcf795c52003-06-19 02:13:25 +0000732 {
733 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000734 zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
ajsf52d13c2005-10-01 17:38:06 +0000735 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000736 inet_ntoa (p->prefix), p->prefixlen);
737 return 0;
738 }
paul718e3742002-12-13 20:15:29 +0000739
740 save_values = ei->route_map_set;
741 ospf_reset_route_map_set_values (&ei->route_map_set);
paulcf795c52003-06-19 02:13:25 +0000742
paul718e3742002-12-13 20:15:29 +0000743 /* apply route-map if needed */
paul020709f2003-04-04 02:44:16 +0000744 if (ROUTEMAP_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000745 {
746 int ret;
747
paulcf795c52003-06-19 02:13:25 +0000748 ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p,
749 RMAP_OSPF, ei);
paul718e3742002-12-13 20:15:29 +0000750
751 if (ret == RMAP_DENYMATCH)
paulcf795c52003-06-19 02:13:25 +0000752 {
753 ei->route_map_set = save_values;
754 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
ajs9b0e25c2004-12-08 19:06:51 +0000755 zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.",
ajsf52d13c2005-10-01 17:38:06 +0000756 ospf_redist_string(type),
paulcf795c52003-06-19 02:13:25 +0000757 inet_ntoa (p->prefix), p->prefixlen);
758 return 0;
759 }
760
paul718e3742002-12-13 20:15:29 +0000761 /* check if 'route-map set' changed something */
762 if (changed)
paulcf795c52003-06-19 02:13:25 +0000763 *changed = !ospf_route_map_set_compare (&ei->route_map_set,
764 &save_values);
paul718e3742002-12-13 20:15:29 +0000765 }
766
767 return 1;
768}
769
770/* OSPF route-map set for redistribution */
771void
paul6c835672004-10-11 11:00:30 +0000772ospf_routemap_set (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000773{
paul020709f2003-04-04 02:44:16 +0000774 if (ROUTEMAP_NAME (ospf, type))
775 free (ROUTEMAP_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000776
paul020709f2003-04-04 02:44:16 +0000777 ROUTEMAP_NAME (ospf, type) = strdup (name);
778 ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);
paul718e3742002-12-13 20:15:29 +0000779}
780
781void
paul020709f2003-04-04 02:44:16 +0000782ospf_routemap_unset (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000783{
paul020709f2003-04-04 02:44:16 +0000784 if (ROUTEMAP_NAME (ospf, type))
785 free (ROUTEMAP_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000786
paul020709f2003-04-04 02:44:16 +0000787 ROUTEMAP_NAME (ospf, type) = NULL;
788 ROUTEMAP (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000789}
790
791/* Zebra route add and delete treatment. */
paul4dadc292005-05-06 21:37:42 +0000792static int
paul718e3742002-12-13 20:15:29 +0000793ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
paulcf795c52003-06-19 02:13:25 +0000794 zebra_size_t length)
paul718e3742002-12-13 20:15:29 +0000795{
796 struct stream *s;
797 struct zapi_ipv4 api;
798 unsigned long ifindex;
799 struct in_addr nexthop;
800 struct prefix_ipv4 p;
801 struct external_info *ei;
paul020709f2003-04-04 02:44:16 +0000802 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000803
804 s = zclient->ibuf;
805 ifindex = 0;
806 nexthop.s_addr = 0;
807
808 /* Type, flags, message. */
809 api.type = stream_getc (s);
810 api.flags = stream_getc (s);
811 api.message = stream_getc (s);
812
813 /* IPv4 prefix. */
814 memset (&p, 0, sizeof (struct prefix_ipv4));
815 p.family = AF_INET;
816 p.prefixlen = stream_getc (s);
817 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
818
hasso8585d4e2004-04-20 17:25:12 +0000819 if (IPV4_NET127(ntohl(p.prefix.s_addr)))
820 return 0;
821
paul718e3742002-12-13 20:15:29 +0000822 /* Nexthop, ifindex, distance, metric. */
823 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
824 {
825 api.nexthop_num = stream_getc (s);
826 nexthop.s_addr = stream_get_ipv4 (s);
827 }
828 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
829 {
830 api.ifindex_num = stream_getc (s);
gdt6a8da852004-02-13 17:40:51 +0000831 /* XXX assert(api.ifindex_num == 1); */
paul718e3742002-12-13 20:15:29 +0000832 ifindex = stream_getl (s);
833 }
834 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
835 api.distance = stream_getc (s);
836 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
837 api.metric = stream_getl (s);
838
paul020709f2003-04-04 02:44:16 +0000839 ospf = ospf_lookup ();
840 if (ospf == NULL)
841 return 0;
842
paul718e3742002-12-13 20:15:29 +0000843 if (command == ZEBRA_IPV4_ROUTE_ADD)
844 {
paul7021c422003-07-15 12:52:22 +0000845 /* XXX|HACK|TODO|FIXME:
hassoa0a39762004-04-23 08:51:10 +0000846 * Maybe we should ignore reject/blackhole routes? Testing shows that
847 * there is no problems though and this is only way to "summarize"
848 * routes in ASBR at the moment. Maybe we need just a better generalised
849 * solution for these types?
850 *
851 * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE)
852 * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
853 * return 0;
paul7021c422003-07-15 12:52:22 +0000854 */
paul7021c422003-07-15 12:52:22 +0000855
paul718e3742002-12-13 20:15:29 +0000856 ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
857
paul68980082003-03-25 05:07:42 +0000858 if (ospf->router_id.s_addr == 0)
paulcf795c52003-06-19 02:13:25 +0000859 /* Set flags to generate AS-external-LSA originate event
860 for each redistributed protocols later. */
861 ospf->external_origin |= (1 << api.type);
paul718e3742002-12-13 20:15:29 +0000862 else
paulcf795c52003-06-19 02:13:25 +0000863 {
864 if (ei)
865 {
866 if (is_prefix_default (&p))
867 ospf_external_lsa_refresh_default (ospf);
868 else
869 {
870 struct ospf_lsa *current;
paul718e3742002-12-13 20:15:29 +0000871
paulcf795c52003-06-19 02:13:25 +0000872 current = ospf_external_info_find_lsa (ospf, &ei->p);
873 if (!current)
874 ospf_external_lsa_originate (ospf, ei);
875 else if (IS_LSA_MAXAGE (current))
876 ospf_external_lsa_refresh (ospf, current,
877 ei, LSA_REFRESH_FORCE);
878 else
879 zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
880 inet_ntoa (p.prefix));
881 }
882 }
883 }
paul718e3742002-12-13 20:15:29 +0000884 }
paulcf795c52003-06-19 02:13:25 +0000885 else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
paul718e3742002-12-13 20:15:29 +0000886 {
887 ospf_external_info_delete (api.type, p);
paul7021c422003-07-15 12:52:22 +0000888 if (is_prefix_default (&p))
paulcf795c52003-06-19 02:13:25 +0000889 ospf_external_lsa_refresh_default (ospf);
paul7021c422003-07-15 12:52:22 +0000890 else
ajs5339cfd2005-09-19 13:28:05 +0000891 ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */);
paul718e3742002-12-13 20:15:29 +0000892 }
893
894 return 0;
895}
paul718e3742002-12-13 20:15:29 +0000896
paulcf795c52003-06-19 02:13:25 +0000897
paul718e3742002-12-13 20:15:29 +0000898int
paul6c835672004-10-11 11:00:30 +0000899ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000900{
901 /* Lookup access-list for distribute-list. */
paul020709f2003-04-04 02:44:16 +0000902 DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
paul718e3742002-12-13 20:15:29 +0000903
904 /* Clear previous distribute-name. */
paul020709f2003-04-04 02:44:16 +0000905 if (DISTRIBUTE_NAME (ospf, type))
906 free (DISTRIBUTE_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000907
908 /* Set distribute-name. */
paul020709f2003-04-04 02:44:16 +0000909 DISTRIBUTE_NAME (ospf, type) = strdup (name);
paul718e3742002-12-13 20:15:29 +0000910
911 /* If access-list have been set, schedule update timer. */
paul020709f2003-04-04 02:44:16 +0000912 if (DISTRIBUTE_LIST (ospf, type))
paul68980082003-03-25 05:07:42 +0000913 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000914
915 return CMD_SUCCESS;
916}
917
918int
paul6c835672004-10-11 11:00:30 +0000919ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name)
paul718e3742002-12-13 20:15:29 +0000920{
921 /* Schedule update timer. */
paul020709f2003-04-04 02:44:16 +0000922 if (DISTRIBUTE_LIST (ospf, type))
paul68980082003-03-25 05:07:42 +0000923 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000924
925 /* Unset distribute-list. */
paul020709f2003-04-04 02:44:16 +0000926 DISTRIBUTE_LIST (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000927
928 /* Clear distribute-name. */
paul020709f2003-04-04 02:44:16 +0000929 if (DISTRIBUTE_NAME (ospf, type))
930 free (DISTRIBUTE_NAME (ospf, type));
paulcf795c52003-06-19 02:13:25 +0000931
paul020709f2003-04-04 02:44:16 +0000932 DISTRIBUTE_NAME (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000933
934 return CMD_SUCCESS;
935}
936
937/* distribute-list update timer. */
paul4dadc292005-05-06 21:37:42 +0000938static int
paul718e3742002-12-13 20:15:29 +0000939ospf_distribute_list_update_timer (struct thread *thread)
940{
941 struct route_node *rn;
942 struct external_info *ei;
943 struct route_table *rt;
944 struct ospf_lsa *lsa;
paul4dadc292005-05-06 21:37:42 +0000945 intptr_t type;
paul020709f2003-04-04 02:44:16 +0000946 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000947
paul4dadc292005-05-06 21:37:42 +0000948 type = (intptr_t)THREAD_ARG (thread);
hasso01018ce2005-08-05 07:40:15 +0000949 assert (type <= ZEBRA_ROUTE_MAX);
paul64511f32004-10-31 18:01:13 +0000950
paul718e3742002-12-13 20:15:29 +0000951 rt = EXTERNAL_INFO (type);
952
paul020709f2003-04-04 02:44:16 +0000953 ospf = ospf_lookup ();
954 if (ospf == NULL)
955 return 0;
956
paul68980082003-03-25 05:07:42 +0000957 ospf->t_distribute_update = NULL;
paul718e3742002-12-13 20:15:29 +0000958
959 zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
960
961 /* foreach all external info. */
962 if (rt)
963 for (rn = route_top (rt); rn; rn = route_next (rn))
964 if ((ei = rn->info) != NULL)
paulcf795c52003-06-19 02:13:25 +0000965 {
966 if (is_prefix_default (&ei->p))
967 ospf_external_lsa_refresh_default (ospf);
968 else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
969 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
970 else
971 ospf_external_lsa_originate (ospf, ei);
972 }
paul718e3742002-12-13 20:15:29 +0000973 return 0;
974}
975
976#define OSPF_DISTRIBUTE_UPDATE_DELAY 5
977
978/* Update distribute-list and set timer to apply access-list. */
979void
paul68980082003-03-25 05:07:42 +0000980ospf_distribute_list_update (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000981{
982 struct route_table *rt;
paulcf795c52003-06-19 02:13:25 +0000983
paul718e3742002-12-13 20:15:29 +0000984 /* External info does not exist. */
985 if (!(rt = EXTERNAL_INFO (type)))
986 return;
987
988 /* If exists previously invoked thread, then cancel it. */
paul68980082003-03-25 05:07:42 +0000989 if (ospf->t_distribute_update)
990 OSPF_TIMER_OFF (ospf->t_distribute_update);
paul718e3742002-12-13 20:15:29 +0000991
992 /* Set timer. */
paul68980082003-03-25 05:07:42 +0000993 ospf->t_distribute_update =
paul718e3742002-12-13 20:15:29 +0000994 thread_add_timer (master, ospf_distribute_list_update_timer,
paulcf795c52003-06-19 02:13:25 +0000995 (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000996}
997
998/* If access-list is updated, apply some check. */
paul4dadc292005-05-06 21:37:42 +0000999static void
paul718e3742002-12-13 20:15:29 +00001000ospf_filter_update (struct access_list *access)
1001{
paul020709f2003-04-04 02:44:16 +00001002 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001003 int type;
1004 int abr_inv = 0;
1005 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +00001006 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001007
1008 /* If OSPF instatnce does not exist, return right now. */
paul020709f2003-04-04 02:44:16 +00001009 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001010 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001011 return;
1012
paul718e3742002-12-13 20:15:29 +00001013 /* Update distribute-list, and apply filter. */
hasso01018ce2005-08-05 07:40:15 +00001014 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +00001015 {
paul020709f2003-04-04 02:44:16 +00001016 if (ROUTEMAP (ospf, type) != NULL)
paulcf795c52003-06-19 02:13:25 +00001017 {
1018 /* if route-map is not NULL it may be using this access list */
1019 ospf_distribute_list_update (ospf, type);
1020 continue;
1021 }
1022
hasso01018ce2005-08-05 07:40:15 +00001023 /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX),
1024 * but no distribute list. */
1025 if (type == ZEBRA_ROUTE_MAX)
1026 break;
paul718e3742002-12-13 20:15:29 +00001027
paul020709f2003-04-04 02:44:16 +00001028 if (DISTRIBUTE_NAME (ospf, type))
paulcf795c52003-06-19 02:13:25 +00001029 {
1030 /* Keep old access-list for distribute-list. */
1031 struct access_list *old = DISTRIBUTE_LIST (ospf, type);
1032
1033 /* Update access-list for distribute-list. */
1034 DISTRIBUTE_LIST (ospf, type) =
1035 access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type));
1036
1037 /* No update for this distribute type. */
1038 if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL)
1039 continue;
1040
1041 /* Schedule distribute-list update timer. */
1042 if (DISTRIBUTE_LIST (ospf, type) == NULL ||
1043 strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
1044 ospf_distribute_list_update (ospf, type);
1045 }
paul718e3742002-12-13 20:15:29 +00001046 }
1047
1048 /* Update Area access-list. */
paul1eb8ef22005-04-07 07:30:20 +00001049 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1050 {
1051 if (EXPORT_NAME (area))
1052 {
1053 EXPORT_LIST (area) = NULL;
1054 abr_inv++;
1055 }
paul718e3742002-12-13 20:15:29 +00001056
paul1eb8ef22005-04-07 07:30:20 +00001057 if (IMPORT_NAME (area))
1058 {
1059 IMPORT_LIST (area) = NULL;
1060 abr_inv++;
1061 }
1062 }
paul718e3742002-12-13 20:15:29 +00001063
1064 /* Schedule ABR tasks -- this will be changed -- takada. */
paul020709f2003-04-04 02:44:16 +00001065 if (IS_OSPF_ABR (ospf) && abr_inv)
paul68980082003-03-25 05:07:42 +00001066 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001067}
hassodd669bb2004-05-10 07:43:59 +00001068
1069/* If prefix-list is updated, do some updates. */
1070void
1071ospf_prefix_list_update (struct prefix_list *plist)
1072{
1073 struct ospf *ospf;
1074 int type;
1075 int abr_inv = 0;
1076 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +00001077 struct listnode *node;
hassodd669bb2004-05-10 07:43:59 +00001078
1079 /* If OSPF instatnce does not exist, return right now. */
1080 ospf = ospf_lookup ();
1081 if (ospf == NULL)
1082 return;
1083
1084 /* Update all route-maps which are used as redistribution filters.
1085 * They might use prefix-list.
1086 */
hasso01018ce2005-08-05 07:40:15 +00001087 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
hassodd669bb2004-05-10 07:43:59 +00001088 {
1089 if (ROUTEMAP (ospf, type) != NULL)
1090 {
1091 /* If route-map is not NULL it may be using this prefix list */
1092 ospf_distribute_list_update (ospf, type);
1093 continue;
1094 }
1095 }
1096
1097 /* Update area filter-lists. */
paul1eb8ef22005-04-07 07:30:20 +00001098 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1099 {
1100 /* Update filter-list in. */
1101 if (PREFIX_NAME_IN (area))
1102 if (strcmp (PREFIX_NAME_IN (area), plist->name) == 0)
1103 {
1104 PREFIX_LIST_IN (area) =
1105 prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
1106 abr_inv++;
1107 }
hassodd669bb2004-05-10 07:43:59 +00001108
paul1eb8ef22005-04-07 07:30:20 +00001109 /* Update filter-list out. */
1110 if (PREFIX_NAME_OUT (area))
1111 if (strcmp (PREFIX_NAME_OUT (area), plist->name) == 0)
1112 {
1113 PREFIX_LIST_IN (area) =
1114 prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
1115 abr_inv++;
1116 }
1117 }
hassodd669bb2004-05-10 07:43:59 +00001118
1119 /* Schedule ABR task. */
1120 if (IS_OSPF_ABR (ospf) && abr_inv)
1121 ospf_schedule_abr_task (ospf);
1122}
paulcf795c52003-06-19 02:13:25 +00001123
paul4dadc292005-05-06 21:37:42 +00001124static struct ospf_distance *
1125ospf_distance_new (void)
paul718e3742002-12-13 20:15:29 +00001126{
1127 struct ospf_distance *new;
1128 new = XMALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
1129 memset (new, 0, sizeof (struct ospf_distance));
1130 return new;
1131}
1132
paul4dadc292005-05-06 21:37:42 +00001133static void
paul718e3742002-12-13 20:15:29 +00001134ospf_distance_free (struct ospf_distance *odistance)
1135{
1136 XFREE (MTYPE_OSPF_DISTANCE, odistance);
1137}
1138
1139int
paul6c835672004-10-11 11:00:30 +00001140ospf_distance_set (struct vty *vty, struct ospf *ospf,
1141 const char *distance_str,
1142 const char *ip_str,
1143 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00001144{
1145 int ret;
1146 struct prefix_ipv4 p;
1147 u_char distance;
1148 struct route_node *rn;
1149 struct ospf_distance *odistance;
1150
1151 ret = str2prefix_ipv4 (ip_str, &p);
1152 if (ret == 0)
1153 {
1154 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1155 return CMD_WARNING;
1156 }
1157
1158 distance = atoi (distance_str);
1159
1160 /* Get OSPF distance node. */
paul68980082003-03-25 05:07:42 +00001161 rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +00001162 if (rn->info)
1163 {
1164 odistance = rn->info;
1165 route_unlock_node (rn);
1166 }
1167 else
1168 {
1169 odistance = ospf_distance_new ();
1170 rn->info = odistance;
1171 }
1172
1173 /* Set distance value. */
1174 odistance->distance = distance;
1175
1176 /* Reset access-list configuration. */
1177 if (odistance->access_list)
1178 {
1179 free (odistance->access_list);
1180 odistance->access_list = NULL;
1181 }
1182 if (access_list_str)
1183 odistance->access_list = strdup (access_list_str);
1184
1185 return CMD_SUCCESS;
1186}
1187
1188int
paul6c835672004-10-11 11:00:30 +00001189ospf_distance_unset (struct vty *vty, struct ospf *ospf,
1190 const char *distance_str,
1191 const char *ip_str, char
1192 const *access_list_str)
paul718e3742002-12-13 20:15:29 +00001193{
1194 int ret;
1195 struct prefix_ipv4 p;
1196 u_char distance;
1197 struct route_node *rn;
1198 struct ospf_distance *odistance;
1199
1200 ret = str2prefix_ipv4 (ip_str, &p);
1201 if (ret == 0)
1202 {
1203 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1204 return CMD_WARNING;
1205 }
1206
1207 distance = atoi (distance_str);
1208
paulcf795c52003-06-19 02:13:25 +00001209 rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p);
1210 if (!rn)
paul718e3742002-12-13 20:15:29 +00001211 {
1212 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
1213 return CMD_WARNING;
1214 }
1215
1216 odistance = rn->info;
1217
1218 if (odistance->access_list)
1219 free (odistance->access_list);
1220 ospf_distance_free (odistance);
1221
1222 rn->info = NULL;
1223 route_unlock_node (rn);
1224 route_unlock_node (rn);
1225
1226 return CMD_SUCCESS;
1227}
1228
1229void
paul68980082003-03-25 05:07:42 +00001230ospf_distance_reset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001231{
1232 struct route_node *rn;
1233 struct ospf_distance *odistance;
1234
paul68980082003-03-25 05:07:42 +00001235 for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001236 if ((odistance = rn->info) != NULL)
1237 {
paulcf795c52003-06-19 02:13:25 +00001238 if (odistance->access_list)
1239 free (odistance->access_list);
1240 ospf_distance_free (odistance);
1241 rn->info = NULL;
1242 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001243 }
1244}
1245
1246u_char
1247ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
1248{
paul020709f2003-04-04 02:44:16 +00001249 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001250
paul020709f2003-04-04 02:44:16 +00001251 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001252 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001253 return 0;
1254
paul68980082003-03-25 05:07:42 +00001255 if (ospf->distance_intra)
paul718e3742002-12-13 20:15:29 +00001256 if (or->path_type == OSPF_PATH_INTRA_AREA)
paul68980082003-03-25 05:07:42 +00001257 return ospf->distance_intra;
paul718e3742002-12-13 20:15:29 +00001258
paul68980082003-03-25 05:07:42 +00001259 if (ospf->distance_inter)
paul718e3742002-12-13 20:15:29 +00001260 if (or->path_type == OSPF_PATH_INTER_AREA)
paul68980082003-03-25 05:07:42 +00001261 return ospf->distance_inter;
paul718e3742002-12-13 20:15:29 +00001262
paul68980082003-03-25 05:07:42 +00001263 if (ospf->distance_external)
paul718e3742002-12-13 20:15:29 +00001264 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
paulcf795c52003-06-19 02:13:25 +00001265 || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
paul68980082003-03-25 05:07:42 +00001266 return ospf->distance_external;
paulcf795c52003-06-19 02:13:25 +00001267
paul68980082003-03-25 05:07:42 +00001268 if (ospf->distance_all)
1269 return ospf->distance_all;
paul718e3742002-12-13 20:15:29 +00001270
1271 return 0;
1272}
1273
1274void
1275ospf_zebra_init ()
1276{
1277 /* Allocate zebra structure. */
1278 zclient = zclient_new ();
1279 zclient_init (zclient, ZEBRA_ROUTE_OSPF);
hasso18a6dce2004-10-03 18:18:34 +00001280 zclient->router_id_update = ospf_router_id_update_zebra;
paul718e3742002-12-13 20:15:29 +00001281 zclient->interface_add = ospf_interface_add;
1282 zclient->interface_delete = ospf_interface_delete;
1283 zclient->interface_up = ospf_interface_state_up;
1284 zclient->interface_down = ospf_interface_state_down;
1285 zclient->interface_address_add = ospf_interface_address_add;
1286 zclient->interface_address_delete = ospf_interface_address_delete;
1287 zclient->ipv4_route_add = ospf_zebra_read_ipv4;
1288 zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
1289
1290 access_list_add_hook (ospf_filter_update);
1291 access_list_delete_hook (ospf_filter_update);
hassodd669bb2004-05-10 07:43:59 +00001292 prefix_list_add_hook (ospf_prefix_list_update);
1293 prefix_list_delete_hook (ospf_prefix_list_update);
paul718e3742002-12-13 20:15:29 +00001294}