]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_zebra.c
zebra: Export zclient_socket_un().
[mirror_frr.git] / ospfd / ospf_zebra.c
CommitLineData
718e3744 1/*
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"
dd669bb0 35#include "plist.h"
718e3744 36#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"
d5a5c8f0
DS
47#include "ospfd/ospf_lsdb.h"
48#include "ospfd/ospf_neighbor.h"
49#include "ospfd/ospf_nsm.h"
718e3744 50#include "ospfd/ospf_zebra.h"
51#ifdef HAVE_SNMP
52#include "ospfd/ospf_snmp.h"
53#endif /* HAVE_SNMP */
54
55/* Zebra structure to hold current status. */
56struct zclient *zclient = NULL;
57
58/* For registering threads. */
59extern struct thread_master *master;
18a6dce6 60struct in_addr router_id_zebra;
61
62/* Router-id update message from zebra. */
4dadc291 63static int
18a6dce6 64ospf_router_id_update_zebra (int command, struct zclient *zclient,
7076bb2f 65 zebra_size_t length, vrf_id_t vrf_id)
18a6dce6 66{
67 struct ospf *ospf;
68 struct prefix router_id;
69 zebra_router_id_update_read(zclient->ibuf,&router_id);
70
7f643ebf
AS
71 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
72 {
4690c7d7 73 char buf[PREFIX2STR_BUFFER];
7f643ebf
AS
74 prefix2str(&router_id, buf, sizeof(buf));
75 zlog_debug("Zebra rcvd: router id update %s", buf);
76 }
77
18a6dce6 78 router_id_zebra = router_id.u.prefix4;
79
80 ospf = ospf_lookup ();
b29800a6 81
18a6dce6 82 if (ospf != NULL)
b29800a6 83 ospf_router_id_update (ospf);
84
18a6dce6 85 return 0;
86}
718e3744 87
88/* Inteface addition message from zebra. */
4dadc291 89static int
7076bb2f
FL
90ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length,
91 vrf_id_t vrf_id)
718e3744 92{
93 struct interface *ifp;
94
7076bb2f 95 ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
718e3744 96
97 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
4fe51714
DS
98 zlog_debug ("Zebra: interface add %s[%u] index %d flags %llx metric %d mtu %d",
99 ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags,
30d20590 100 ifp->metric, ifp->mtu);
718e3744 101
cf795c5d 102 assert (ifp->info);
f2c80652 103
718e3744 104 if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
105 {
106 SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
bc18d616 107 IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp);
718e3744 108 }
109
a49eb30a 110 ospf_if_update (NULL, ifp);
718e3744 111
112#ifdef HAVE_SNMP
113 ospf_snmp_if_update (ifp);
114#endif /* HAVE_SNMP */
115
116 return 0;
117}
118
4dadc291 119static int
718e3744 120ospf_interface_delete (int command, struct zclient *zclient,
7076bb2f 121 zebra_size_t length, vrf_id_t vrf_id)
718e3744 122{
123 struct interface *ifp;
124 struct stream *s;
125 struct route_node *rn;
126
cf795c5d 127 s = zclient->ibuf;
718e3744 128 /* zebra_interface_state_read() updates interface structure in iflist */
7076bb2f 129 ifp = zebra_interface_state_read (s, vrf_id);
718e3744 130
131 if (ifp == NULL)
132 return 0;
133
134 if (if_is_up (ifp))
135 zlog_warn ("Zebra: got delete of %s, but interface is still up",
cf795c5d 136 ifp->name);
137
718e3744 138 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
9b0e25c0 139 zlog_debug
4fe51714
DS
140 ("Zebra: interface delete %s[%u] index %d flags %llx metric %d mtu %d",
141 ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
718e3744 142
143#ifdef HAVE_SNMP
144 ospf_snmp_if_delete (ifp);
145#endif /* HAVE_SNMP */
146
147 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
148 if (rn->info)
149 ospf_if_free ((struct ospf_interface *) rn->info);
150
84361d61 151 ifp->ifindex = IFINDEX_DELETED;
718e3744 152 return 0;
153}
154
d2fc8896 155static struct interface *
7076bb2f 156zebra_interface_if_lookup (struct stream *s, vrf_id_t vrf_id)
718e3744 157{
21fefa98 158 char ifname_tmp[INTERFACE_NAMSIZ];
718e3744 159
160 /* Read interface name. */
161 stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
162
d2fc8896 163 /* And look it up. */
21fefa98 164 return if_lookup_by_name_len(ifname_tmp,
165 strnlen(ifname_tmp, INTERFACE_NAMSIZ));
718e3744 166}
167
4dadc291 168static int
718e3744 169ospf_interface_state_up (int command, struct zclient *zclient,
7076bb2f 170 zebra_size_t length, vrf_id_t vrf_id)
718e3744 171{
172 struct interface *ifp;
718e3744 173 struct ospf_interface *oi;
174 struct route_node *rn;
cf795c5d 175
7076bb2f 176 ifp = zebra_interface_if_lookup (zclient->ibuf, vrf_id);
718e3744 177
178 if (ifp == NULL)
179 return 0;
180
181 /* Interface is already up. */
2e3b2e47 182 if (if_is_operative (ifp))
718e3744 183 {
184 /* Temporarily keep ifp values. */
a608bbf2 185 struct interface if_tmp;
718e3744 186 memcpy (&if_tmp, ifp, sizeof (struct interface));
187
188 zebra_interface_if_set_value (zclient->ibuf, ifp);
189
190 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
9b0e25c0 191 zlog_debug ("Zebra: Interface[%s] state update.", ifp->name);
718e3744 192
193 if (if_tmp.bandwidth != ifp->bandwidth)
cf795c5d 194 {
195 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
9b0e25c0 196 zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.",
cf795c5d 197 ifp->name, if_tmp.bandwidth, ifp->bandwidth);
718e3744 198
cf795c5d 199 ospf_if_recalculate_output_cost (ifp);
200 }
a608bbf2 201
202 if (if_tmp.mtu != ifp->mtu)
203 {
204 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
205 zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.",
206 ifp->name, if_tmp.mtu, ifp->mtu);
207
208 /* Must reset the interface (simulate down/up) when MTU changes. */
209 ospf_if_reset(ifp);
210 }
718e3744 211 return 0;
212 }
cf795c5d 213
718e3744 214 zebra_interface_if_set_value (zclient->ibuf, ifp);
cf795c5d 215
718e3744 216 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
9b0e25c0 217 zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name);
cf795c5d 218
219 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
718e3744 220 {
cf795c5d 221 if ((oi = rn->info) == NULL)
222 continue;
223
718e3744 224 ospf_if_up (oi);
225 }
cf795c5d 226
718e3744 227 return 0;
228}
229
4dadc291 230static int
718e3744 231ospf_interface_state_down (int command, struct zclient *zclient,
7076bb2f 232 zebra_size_t length, vrf_id_t vrf_id)
718e3744 233{
234 struct interface *ifp;
235 struct ospf_interface *oi;
236 struct route_node *node;
237
7076bb2f 238 ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
718e3744 239
240 if (ifp == NULL)
241 return 0;
242
243 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
9b0e25c0 244 zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name);
718e3744 245
cf795c5d 246 for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
718e3744 247 {
cf795c5d 248 if ((oi = node->info) == NULL)
249 continue;
718e3744 250 ospf_if_down (oi);
251 }
252
253 return 0;
254}
255
4dadc291 256static int
718e3744 257ospf_interface_address_add (int command, struct zclient *zclient,
7076bb2f 258 zebra_size_t length, vrf_id_t vrf_id)
718e3744 259{
260 struct connected *c;
261
7076bb2f 262 c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
718e3744 263
264 if (c == NULL)
265 return 0;
266
7f643ebf
AS
267 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
268 {
4690c7d7 269 char buf[PREFIX2STR_BUFFER];
7f643ebf
AS
270 prefix2str(c->address, buf, sizeof(buf));
271 zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
272 }
273
a49eb30a 274 ospf_if_update (NULL, c->ifp);
718e3744 275
276#ifdef HAVE_SNMP
277 ospf_snmp_if_update (c->ifp);
278#endif /* HAVE_SNMP */
279
280 return 0;
281}
282
4dadc291 283static int
718e3744 284ospf_interface_address_delete (int command, struct zclient *zclient,
7076bb2f 285 zebra_size_t length, vrf_id_t vrf_id)
718e3744 286{
287 struct connected *c;
288 struct interface *ifp;
289 struct ospf_interface *oi;
290 struct route_node *rn;
291 struct prefix p;
292
7076bb2f 293 c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
718e3744 294
295 if (c == NULL)
296 return 0;
297
7f643ebf
AS
298 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
299 {
4690c7d7 300 char buf[PREFIX2STR_BUFFER];
7f643ebf
AS
301 prefix2str(c->address, buf, sizeof(buf));
302 zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf);
303 }
304
718e3744 305 ifp = c->ifp;
306 p = *c->address;
307 p.prefixlen = IPV4_MAX_PREFIXLEN;
308
309 rn = route_node_lookup (IF_OIFS (ifp), &p);
cf795c5d 310 if (!rn)
98429f6d 311 {
312 connected_free (c);
313 return 0;
314 }
718e3744 315
316 assert (rn->info);
317 oi = rn->info;
f4936b2a 318 route_unlock_node (rn);
cf795c5d 319
718e3744 320 /* Call interface hook functions to clean up */
321 ospf_if_free (oi);
cf795c5d 322
718e3744 323#ifdef HAVE_SNMP
324 ospf_snmp_if_update (c->ifp);
325#endif /* HAVE_SNMP */
326
327 connected_free (c);
328
718e3744 329 return 0;
330}
72357f2b 331
718e3744 332void
333ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
334{
335 u_char message;
336 u_char distance;
337 u_char flags;
338 int psize;
339 struct stream *s;
340 struct ospf_path *path;
52dc7ee6 341 struct listnode *node;
7c8ff89e 342 struct ospf *ospf = ospf_lookup ();
718e3744 343
7076bb2f
FL
344 if ((ospf->instance &&
345 redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance))
346 ||
347 vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
718e3744 348 {
349 message = 0;
350 flags = 0;
351
352 /* OSPF pass nexthop and metric */
353 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
354 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
355
356 /* Distance value. */
357 distance = ospf_distance_apply (p, or);
358 if (distance)
72357f2b 359 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
718e3744 360
0d9551dc
DS
361 /* Check if path type is ASE and use only 16bit tags */
362 if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) ||
363 (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) &&
364 (or->u.ext.tag > 0) && (or->u.ext.tag < UINT16_MAX))
365 SET_FLAG (message, ZAPI_MESSAGE_TAG);
366
718e3744 367 /* Make packet. */
368 s = zclient->obuf;
369 stream_reset (s);
370
718e3744 371 /* Put command, type, flags, message. */
7076bb2f 372 zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
718e3744 373 stream_putc (s, ZEBRA_ROUTE_OSPF);
7c8ff89e 374 stream_putw (s, ospf->instance);
718e3744 375 stream_putc (s, flags);
376 stream_putc (s, message);
b4e45f67 377 stream_putw (s, SAFI_UNICAST);
cf795c5d 378
718e3744 379 /* Put prefix information. */
380 psize = PSIZE (p->prefixlen);
381 stream_putc (s, p->prefixlen);
cf795c5d 382 stream_write (s, (u_char *) & p->prefix, psize);
718e3744 383
384 /* Nexthop count. */
96735eea 385 stream_putc (s, or->paths->count);
718e3744 386
387 /* Nexthop, ifindex, distance and metric information. */
1eb8ef25 388 for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
72357f2b 389 {
525c1839 390#ifdef HAVE_NETLINK
d44ca835
DS
391 if (path->unnumbered ||
392 (path->nexthop.s_addr != INADDR_ANY &&
393 path->ifindex != 0))
394 {
395 stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
396 stream_put_in_addr (s, &path->nexthop);
397 stream_putl (s, path->ifindex);
398 }
399 else if (path->nexthop.s_addr != INADDR_ANY)
400 {
401 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
402 stream_put_in_addr (s, &path->nexthop);
403 }
404 else
405 {
406 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
407 if (path->ifindex)
408 stream_putl (s, path->ifindex);
409 else
410 stream_putl (s, 0);
411 }
525c1839 412#else /* HAVE_NETLINK */
ba281d3d
JT
413 if (path->nexthop.s_addr != INADDR_ANY &&
414 path->ifindex != 0)
415 {
416 stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
417 stream_put_in_addr (s, &path->nexthop);
418 stream_putl (s, path->ifindex);
419 }
420 else if (path->nexthop.s_addr != INADDR_ANY)
cf795c5d 421 {
422 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
423 stream_put_in_addr (s, &path->nexthop);
424 }
425 else
426 {
427 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
a8ba847f
JT
428 if (path->ifindex)
429 stream_putl (s, path->ifindex);
cf795c5d 430 else
431 stream_putl (s, 0);
432 }
525c1839 433#endif /* HAVE_NETLINK */
72357f2b 434
435 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
436 {
56b3ea09 437 char buf[2][INET_ADDRSTRLEN];
525c1839 438 zlog_debug("Zebra: Route add %s/%d nexthop %s, ifindex=%d",
56b3ea09
AS
439 inet_ntop(AF_INET, &p->prefix,
440 buf[0], sizeof(buf[0])),
441 p->prefixlen,
442 inet_ntop(AF_INET, &path->nexthop,
525c1839
DS
443 buf[1], sizeof(buf[1])),
444 path->ifindex);
cf795c5d 445 }
446 }
718e3744 447
448 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
cf795c5d 449 stream_putc (s, distance);
718e3744 450 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
cf795c5d 451 {
452 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
453 stream_putl (s, or->cost + or->u.ext.type2_cost);
454 else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
455 stream_putl (s, or->u.ext.type2_cost);
456 else
457 stream_putl (s, or->cost);
458 }
718e3744 459
0d9551dc
DS
460 if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG))
461 stream_putw (s, (u_short)or->u.ext.tag);
462
718e3744 463 stream_putw_at (s, 0, stream_get_endp (s));
464
634f9ea2 465 zclient_send_message(zclient);
718e3744 466 }
467}
468
469void
470ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
471{
ba281d3d
JT
472 u_char message;
473 u_char distance;
474 u_char flags;
475 int psize;
476 struct stream *s;
72357f2b 477 struct ospf_path *path;
ba281d3d 478 struct listnode *node;
7c8ff89e 479 struct ospf *ospf = ospf_lookup ();
718e3744 480
7076bb2f
FL
481 if ((ospf->instance &&
482 redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance))
483 ||
484 vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
718e3744 485 {
ba281d3d
JT
486 message = 0;
487 flags = 0;
488 /* Distance value. */
489 distance = ospf_distance_apply (p, or);
490 /* Make packet. */
491 s = zclient->obuf;
492 stream_reset (s);
718e3744 493
ba281d3d 494 /* Put command, type, flags, message. */
7076bb2f 495 zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT);
ba281d3d 496 stream_putc (s, ZEBRA_ROUTE_OSPF);
7c8ff89e 497 stream_putw (s, ospf->instance);
ba281d3d
JT
498 stream_putc (s, flags);
499 stream_putc (s, message);
500 stream_putw (s, SAFI_UNICAST);
72357f2b 501
ba281d3d
JT
502 /* Put prefix information. */
503 psize = PSIZE (p->prefixlen);
504 stream_putc (s, p->prefixlen);
505 stream_write (s, (u_char *) & p->prefix, psize);
72357f2b 506
ba281d3d
JT
507 /* Nexthop count. */
508 stream_putc (s, or->paths->count);
509
510 /* Nexthop, ifindex, distance and metric information. */
511 for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
512 {
513 if (path->nexthop.s_addr != INADDR_ANY &&
514 path->ifindex != 0)
515 {
516 stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
517 stream_put_in_addr (s, &path->nexthop);
518 stream_putl (s, path->ifindex);
519 }
520 else if (path->nexthop.s_addr != INADDR_ANY)
521 {
522 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
523 stream_put_in_addr (s, &path->nexthop);
524 }
525 else
526 {
527 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
528 stream_putl (s, path->ifindex);
529 }
530
531 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
532 {
56b3ea09 533 char buf[2][INET_ADDRSTRLEN];
a25a1264 534 zlog_debug("Zebra: Route delete %s/%d nexthop %s",
ba281d3d
JT
535 inet_ntop(AF_INET, &p->prefix,
536 buf[0], sizeof(buf[0])),
56b3ea09 537 p->prefixlen,
ba281d3d 538 inet_ntop(AF_INET, &path->nexthop,
56b3ea09 539 buf[1], sizeof(buf[1])));
ba281d3d
JT
540 }
541 }
542
543 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
544 stream_putc (s, distance);
545 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
546 {
547 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
548 stream_putl (s, or->cost + or->u.ext.type2_cost);
549 else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
550 stream_putl (s, or->u.ext.type2_cost);
551 else
552 stream_putl (s, or->cost);
553 }
554
555 stream_putw_at (s, 0, stream_get_endp (s));
556
557 zclient_send_message(zclient);
718e3744 558 }
559}
560
561void
562ospf_zebra_add_discard (struct prefix_ipv4 *p)
563{
564 struct zapi_ipv4 api;
7c8ff89e 565 struct ospf *ospf = ospf_lookup ();
718e3744 566
7076bb2f
FL
567 if ((ospf->instance &&
568 redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance))
569 ||
570 vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
718e3744 571 {
7076bb2f 572 api.vrf_id = VRF_DEFAULT;
718e3744 573 api.type = ZEBRA_ROUTE_OSPF;
7c8ff89e 574 api.instance = ospf->instance;
718e3744 575 api.flags = ZEBRA_FLAG_BLACKHOLE;
576 api.message = 0;
b4e45f67 577 api.safi = SAFI_UNICAST;
718e3744 578 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
579 api.nexthop_num = 0;
580 api.ifindex_num = 0;
0d9551dc 581 api.tag = 0;
718e3744 582
0a589359 583 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
7f643ebf
AS
584
585 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
586 zlog_debug ("Zebra: Route add discard %s/%d",
587 inet_ntoa (p->prefix), p->prefixlen);
718e3744 588 }
589}
590
591void
592ospf_zebra_delete_discard (struct prefix_ipv4 *p)
593{
594 struct zapi_ipv4 api;
7c8ff89e 595 struct ospf *ospf = ospf_lookup ();
718e3744 596
7076bb2f
FL
597 if ((ospf->instance &&
598 redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance))
599 ||
600 vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
718e3744 601 {
7076bb2f 602 api.vrf_id = VRF_DEFAULT;
718e3744 603 api.type = ZEBRA_ROUTE_OSPF;
7c8ff89e 604 api.instance = ospf->instance;
718e3744 605 api.flags = ZEBRA_FLAG_BLACKHOLE;
606 api.message = 0;
b4e45f67 607 api.safi = SAFI_UNICAST;
718e3744 608 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
609 api.nexthop_num = 0;
610 api.ifindex_num = 0;
0d9551dc 611 api.tag = 0;
718e3744 612
0a589359 613 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
72357f2b 614
615 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
9b0e25c0 616 zlog_debug ("Zebra: Route delete discard %s/%d",
cf795c5d 617 inet_ntoa (p->prefix), p->prefixlen);
72357f2b 618
718e3744 619 }
620}
621
7c8ff89e
DS
622struct ospf_external *
623ospf_external_lookup (u_char type, u_short instance)
624{
625 struct list *ext_list;
626 struct listnode *node;
627 struct ospf_external *ext;
628
629 ext_list = om->external[type];
630 if (!ext_list)
631 return(NULL);
632
633 for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext))
634 if (ext->instance == instance)
635 return ext;
636
637 return NULL;
638}
639
640struct ospf_external *
641ospf_external_add (u_char type, u_short instance)
642{
643 struct list *ext_list;
644 struct ospf_external *ext;
645
646 ext = ospf_external_lookup(type, instance);
647 if (ext)
648 return ext;
649
650 if (!om->external[type])
651 om->external[type] = list_new();
652
653 ext_list = om->external[type];
654 ext = (struct ospf_external *)calloc (1, sizeof(struct ospf_external));
655 ext->instance = instance;
656 EXTERNAL_INFO (ext) = route_table_init ();
657
658 listnode_add(ext_list, ext);
659
660 return ext;
661}
662
663void
664ospf_external_del (u_char type, u_short instance)
665{
666 struct ospf_external *ext;
667
668 ext = ospf_external_lookup(type, instance);
669
670 if (ext)
671 {
672 if (EXTERNAL_INFO (ext))
673 route_table_finish(EXTERNAL_INFO (ext));
674
675 listnode_delete(om->external[type], ext);
676 if (!om->external[type]->count)
677 {
678 list_free(om->external[type]);
679 om->external[type] = NULL;
680 }
681 }
682}
683
684struct ospf_redist *
685ospf_redist_lookup (struct ospf *ospf, u_char type, u_short instance)
686{
687 struct list *red_list;
688 struct listnode *node;
689 struct ospf_redist *red;
690
691 red_list = ospf->redist[type];
692 if (!red_list)
693 return(NULL);
694
695 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
696 if (red->instance == instance)
697 return red;
698
699 return NULL;
700}
701
702struct ospf_redist *
703ospf_redist_add (struct ospf *ospf, u_char type, u_short instance)
704{
705 struct list *red_list;
706 struct ospf_redist *red;
707
708 red = ospf_redist_lookup(ospf, type, instance);
709 if (red)
710 return red;
711
712 if (!ospf->redist[type])
713 ospf->redist[type] = list_new();
714
715 red_list = ospf->redist[type];
716 red = (struct ospf_redist *)calloc (1, sizeof(struct ospf_redist));
717 red->instance = instance;
718 red->dmetric.type = -1;
719 red->dmetric.value = -1;
720
721 listnode_add(red_list, red);
722
723 return red;
724}
725
726void
727ospf_redist_del (struct ospf *ospf, u_char type, u_short instance)
728{
729 struct ospf_redist *red;
730
731 red = ospf_redist_lookup(ospf, type, instance);
732
733 if (red)
734 {
735 listnode_delete(ospf->redist[type], red);
736 if (!ospf->redist[type]->count)
737 {
738 list_free(ospf->redist[type]);
739 ospf->redist[type] = NULL;
740 }
741 }
742}
743
744
718e3744 745int
7c8ff89e 746ospf_is_type_redistributed (int type, u_short instance)
718e3744 747{
7c8ff89e 748 return (DEFAULT_ROUTE_TYPE (type) ?
7076bb2f
FL
749 vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) :
750 ((instance && redist_check_instance(&zclient->mi_redist[AFI_IP][type], instance))
53785cfd 751 || (!instance && vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT))));
718e3744 752}
753
754int
7c8ff89e
DS
755ospf_redistribute_set (struct ospf *ospf, int type, u_short instance, int mtype,
756 int mvalue)
718e3744 757{
758 int force = 0;
7c8ff89e 759 struct ospf_redist *red;
cf795c5d 760
7c8ff89e
DS
761 red = ospf_redist_lookup(ospf, type, instance);
762 if (ospf_is_type_redistributed (type, instance))
718e3744 763 {
7c8ff89e 764 if (mtype != red->dmetric.type)
cf795c5d 765 {
7c8ff89e 766 red->dmetric.type = mtype;
cf795c5d 767 force = LSA_REFRESH_FORCE;
768 }
7c8ff89e 769 if (mvalue != red->dmetric.value)
cf795c5d 770 {
7c8ff89e 771 red->dmetric.value = mvalue;
cf795c5d 772 force = LSA_REFRESH_FORCE;
773 }
774
7c8ff89e 775 ospf_external_lsa_refresh_type (ospf, type, instance, force);
cf795c5d 776
718e3744 777 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
7c8ff89e
DS
778 zlog_debug ("Redistribute[%s][%d]: Refresh Type[%d], Metric[%d]",
779 ospf_redist_string(type), instance,
780 metric_type (ospf, type, instance),
781 metric_value (ospf, type, instance));
cf795c5d 782
718e3744 783 return CMD_SUCCESS;
784 }
785
7c8ff89e
DS
786 red->dmetric.type = mtype;
787 red->dmetric.value = mvalue;
718e3744 788
7c8ff89e
DS
789 ospf_external_add(type, instance);
790
7076bb2f
FL
791 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
792 instance, VRF_DEFAULT);
718e3744 793
794 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
7c8ff89e
DS
795 zlog_debug ("Redistribute[%s][%d]: Start Type[%d], Metric[%d]",
796 ospf_redist_string(type), instance,
797 metric_type (ospf, type, instance), metric_value (ospf, type, instance));
cf795c5d 798
68980084 799 ospf_asbr_status_update (ospf, ++ospf->redistribute);
718e3744 800
801 return CMD_SUCCESS;
802}
803
804int
7c8ff89e 805ospf_redistribute_unset (struct ospf *ospf, int type, u_short instance)
718e3744 806{
7c8ff89e 807 if (type == zclient->redist_default && instance == zclient->instance)
718e3744 808 return CMD_SUCCESS;
809
7c8ff89e 810 if (!ospf_is_type_redistributed (type, instance))
718e3744 811 return CMD_SUCCESS;
812
7076bb2f
FL
813 zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type,
814 instance, VRF_DEFAULT);
cf795c5d 815
718e3744 816 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
7c8ff89e
DS
817 zlog_debug ("Redistribute[%s][%d]: Stop",
818 ospf_redist_string(type), instance);
718e3744 819
7c8ff89e 820 ospf_redist_del (ospf, type, instance);
718e3744 821
822 /* Remove the routes from OSPF table. */
7c8ff89e
DS
823 ospf_redistribute_withdraw (ospf, type, instance);
824
825 ospf_external_del(type, instance);
718e3744 826
68980084 827 ospf_asbr_status_update (ospf, --ospf->redistribute);
718e3744 828
829 return CMD_SUCCESS;
830}
831
832int
020709f9 833ospf_redistribute_default_set (struct ospf *ospf, int originate,
cf795c5d 834 int mtype, int mvalue)
718e3744 835{
7c8ff89e
DS
836 struct ospf_redist *red;
837
8fb8a504 838 ospf->default_originate = originate;
020709f9 839
7c8ff89e
DS
840 red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0);
841 red->dmetric.type = mtype;
842 red->dmetric.value = mvalue;
843
844 ospf_external_add(DEFAULT_ROUTE, 0);
845
846 if (ospf_is_type_redistributed (DEFAULT_ROUTE, 0))
718e3744 847 {
8fb8a504
AS
848 /* if ospf->default_originate changes value, is calling
849 ospf_external_lsa_refresh_default sufficient to implement
850 the change? */
68980084 851 ospf_external_lsa_refresh_default (ospf);
cf795c5d 852
718e3744 853 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
9b0e25c0 854 zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
f52d13cb 855 ospf_redist_string(DEFAULT_ROUTE),
7c8ff89e
DS
856 metric_type (ospf, DEFAULT_ROUTE, 0),
857 metric_value (ospf, DEFAULT_ROUTE, 0));
718e3744 858 return CMD_SUCCESS;
859 }
860
7076bb2f
FL
861 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
862 VRF_DEFAULT);
cf795c5d 863
718e3744 864 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
9b0e25c0 865 zlog_debug ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
7c8ff89e
DS
866 metric_type (ospf, DEFAULT_ROUTE, 0),
867 metric_value (ospf, DEFAULT_ROUTE, 0));
718e3744 868
68980084 869 if (ospf->router_id.s_addr == 0)
870 ospf->external_origin |= (1 << DEFAULT_ROUTE);
718e3744 871 else
4021b60a 872 thread_add_timer (master, ospf_default_originate_timer, ospf, 1);
718e3744 873
68980084 874 ospf_asbr_status_update (ospf, ++ospf->redistribute);
718e3744 875
876 return CMD_SUCCESS;
877}
878
879int
020709f9 880ospf_redistribute_default_unset (struct ospf *ospf)
718e3744 881{
7c8ff89e 882 if (!ospf_is_type_redistributed (DEFAULT_ROUTE, 0))
718e3744 883 return CMD_SUCCESS;
884
68980084 885 ospf->default_originate = DEFAULT_ORIGINATE_NONE;
7c8ff89e 886 ospf_redist_del(ospf, DEFAULT_ROUTE, 0);
718e3744 887
7076bb2f
FL
888 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient,
889 VRF_DEFAULT);
718e3744 890
891 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
9b0e25c0 892 zlog_debug ("Redistribute[DEFAULT]: Stop");
cf795c5d 893
7c8ff89e
DS
894 //Pending: how does the external_info cleanup work in this case?
895
68980084 896 ospf_asbr_status_update (ospf, --ospf->redistribute);
718e3744 897
898 return CMD_SUCCESS;
899}
900
4dadc291 901static int
020709f9 902ospf_external_lsa_originate_check (struct ospf *ospf,
cf795c5d 903 struct external_info *ei)
718e3744 904{
905 /* If prefix is multicast, then do not originate LSA. */
906 if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
907 {
908 zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
cf795c5d 909 "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
718e3744 910 return 0;
911 }
912
913 /* Take care of default-originate. */
914 if (is_prefix_default (&ei->p))
68980084 915 if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
718e3744 916 {
bcc6c59a 917 zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA "
cf795c5d 918 "for default");
919 return 0;
718e3744 920 }
921
922 return 1;
923}
924
925/* If connected prefix is OSPF enable interface, then do not announce. */
926int
cf795c5d 927ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei)
718e3744 928{
5d8de93a
JT
929 struct listnode *node;
930 struct ospf_interface *oi;
718e3744 931
718e3744 932
5d8de93a
JT
933 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
934 if (prefix_match (oi->address, (struct prefix *) &ei->p))
935 return 0;
718e3744 936 return 1;
937}
938
939/* return 1 if external LSA must be originated, 0 otherwise */
940int
68980084 941ospf_redistribute_check (struct ospf *ospf,
cf795c5d 942 struct external_info *ei, int *changed)
718e3744 943{
944 struct route_map_set_values save_values;
945 struct prefix_ipv4 *p = &ei->p;
7c8ff89e 946 struct ospf_redist *red;
718e3744 947 u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
7c8ff89e 948 u_short instance = is_prefix_default (&ei->p) ? 0 : ei->instance;
cf795c5d 949
718e3744 950 if (changed)
951 *changed = 0;
952
020709f9 953 if (!ospf_external_lsa_originate_check (ospf, ei))
718e3744 954 return 0;
955
956 /* Take care connected route. */
68980084 957 if (type == ZEBRA_ROUTE_CONNECT &&
958 !ospf_distribute_check_connected (ospf, ei))
718e3744 959 return 0;
960
020709f9 961 if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type))
718e3744 962 /* distirbute-list exists, but access-list may not? */
020709f9 963 if (DISTRIBUTE_LIST (ospf, type))
964 if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
cf795c5d 965 {
966 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
9b0e25c0 967 zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
f52d13cb 968 ospf_redist_string(type),
cf795c5d 969 inet_ntoa (p->prefix), p->prefixlen);
970 return 0;
971 }
718e3744 972
973 save_values = ei->route_map_set;
974 ospf_reset_route_map_set_values (&ei->route_map_set);
cf795c5d 975
718e3744 976 /* apply route-map if needed */
7c8ff89e
DS
977 red = ospf_redist_lookup (ospf, type, instance);
978 if (red && ROUTEMAP_NAME(red))
718e3744 979 {
980 int ret;
981
7c8ff89e 982 ret = route_map_apply (ROUTEMAP (red), (struct prefix *) p,
cf795c5d 983 RMAP_OSPF, ei);
718e3744 984
985 if (ret == RMAP_DENYMATCH)
cf795c5d 986 {
987 ei->route_map_set = save_values;
988 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
9b0e25c0 989 zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.",
f52d13cb 990 ospf_redist_string(type),
cf795c5d 991 inet_ntoa (p->prefix), p->prefixlen);
992 return 0;
993 }
994
718e3744 995 /* check if 'route-map set' changed something */
996 if (changed)
cf795c5d 997 *changed = !ospf_route_map_set_compare (&ei->route_map_set,
998 &save_values);
718e3744 999 }
1000
1001 return 1;
1002}
1003
1004/* OSPF route-map set for redistribution */
1005void
7c8ff89e 1006ospf_routemap_set (struct ospf_redist *red, const char *name)
718e3744 1007{
7c8ff89e
DS
1008 if (ROUTEMAP_NAME (red))
1009 free (ROUTEMAP_NAME (red));
718e3744 1010
7c8ff89e
DS
1011 ROUTEMAP_NAME (red) = strdup (name);
1012 ROUTEMAP (red) = route_map_lookup_by_name (name);
718e3744 1013}
1014
1015void
7c8ff89e 1016ospf_routemap_unset (struct ospf_redist *red)
718e3744 1017{
7c8ff89e
DS
1018 if (ROUTEMAP_NAME (red))
1019 free (ROUTEMAP_NAME (red));
718e3744 1020
7c8ff89e
DS
1021 ROUTEMAP_NAME (red) = NULL;
1022 ROUTEMAP (red) = NULL;
718e3744 1023}
1024
1025/* Zebra route add and delete treatment. */
4dadc291 1026static int
718e3744 1027ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
7076bb2f 1028 zebra_size_t length, vrf_id_t vrf_id)
718e3744 1029{
1030 struct stream *s;
1031 struct zapi_ipv4 api;
1032 unsigned long ifindex;
1033 struct in_addr nexthop;
1034 struct prefix_ipv4 p;
1035 struct external_info *ei;
020709f9 1036 struct ospf *ospf;
9a89518f 1037 int i;
718e3744 1038
1039 s = zclient->ibuf;
1040 ifindex = 0;
1041 nexthop.s_addr = 0;
1042
1043 /* Type, flags, message. */
1044 api.type = stream_getc (s);
7c8ff89e 1045 api.instance = stream_getw (s);
718e3744 1046 api.flags = stream_getc (s);
1047 api.message = stream_getc (s);
1048
1049 /* IPv4 prefix. */
1050 memset (&p, 0, sizeof (struct prefix_ipv4));
1051 p.family = AF_INET;
1052 p.prefixlen = stream_getc (s);
1053 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
1054
8585d4e5 1055 if (IPV4_NET127(ntohl(p.prefix.s_addr)))
1056 return 0;
1057
718e3744 1058 /* Nexthop, ifindex, distance, metric. */
1059 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
1060 {
1061 api.nexthop_num = stream_getc (s);
1062 nexthop.s_addr = stream_get_ipv4 (s);
1063 }
1064 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
1065 {
1066 api.ifindex_num = stream_getc (s);
6a8da852 1067 /* XXX assert(api.ifindex_num == 1); */
718e3744 1068 ifindex = stream_getl (s);
1069 }
1070 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
1071 api.distance = stream_getc (s);
1072 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
1073 api.metric = stream_getl (s);
0d9551dc
DS
1074 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
1075 api.tag = stream_getw (s);
1076 else
1077 api.tag = 0;
718e3744 1078
020709f9 1079 ospf = ospf_lookup ();
1080 if (ospf == NULL)
1081 return 0;
1082
5048fe14 1083 if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
718e3744 1084 {
7021c425 1085 /* XXX|HACK|TODO|FIXME:
a0a39761 1086 * Maybe we should ignore reject/blackhole routes? Testing shows that
1087 * there is no problems though and this is only way to "summarize"
1088 * routes in ASBR at the moment. Maybe we need just a better generalised
1089 * solution for these types?
1090 *
1091 * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE)
1092 * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
1093 * return 0;
7021c425 1094 */
0d9551dc
DS
1095
1096 /* Protocol tag overwrites all other tag value send by zebra */
1097 if (ospf->dtag[api.type] > 0)
1098 api.tag = ospf->dtag[api.type];
1099
9a89518f
VK
1100 /*
1101 * Given zebra sends update for a prefix via ADD message, it should
1102 * be considered as an implicit DEL for that prefix with other source
1103 * types.
1104 */
1105 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1106 if (i != api.type)
1107 ospf_external_info_delete(i, api.instance, p);
1108
7c8ff89e
DS
1109 ei = ospf_external_info_add (api.type, api.instance, p, ifindex,
1110 nexthop, api.tag);
5048fe14 1111 if (ei == NULL)
1112 {
1113 /* Nothing has changed, so nothing to do; return */
1114 return 0;
1115 }
68980084 1116 if (ospf->router_id.s_addr == 0)
cf795c5d 1117 /* Set flags to generate AS-external-LSA originate event
1118 for each redistributed protocols later. */
1119 ospf->external_origin |= (1 << api.type);
718e3744 1120 else
cf795c5d 1121 {
1122 if (ei)
1123 {
1124 if (is_prefix_default (&p))
1125 ospf_external_lsa_refresh_default (ospf);
1126 else
1127 {
1128 struct ospf_lsa *current;
1129
1130 current = ospf_external_info_find_lsa (ospf, &ei->p);
1131 if (!current)
1132 ospf_external_lsa_originate (ospf, ei);
cf795c5d 1133 else
5048fe14 1134 {
1135 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
1136 zlog_debug ("ospf_zebra_read_ipv4() : %s refreshing LSA",
1137 inet_ntoa (p.prefix));
1138 ospf_external_lsa_refresh (ospf, current,
1139 ei, LSA_REFRESH_FORCE);
1140 }
cf795c5d 1141 }
1142 }
1143 }
718e3744 1144 }
5048fe14 1145 else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */
718e3744 1146 {
7c8ff89e 1147 ospf_external_info_delete (api.type, api.instance, p);
7021c425 1148 if (is_prefix_default (&p))
cf795c5d 1149 ospf_external_lsa_refresh_default (ospf);
7021c425 1150 else
5339cfdb 1151 ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */);
718e3744 1152 }
1153
1154 return 0;
1155}
6b0655a2 1156
cf795c5d 1157
718e3744 1158int
6c835671 1159ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name)
718e3744 1160{
1161 /* Lookup access-list for distribute-list. */
020709f9 1162 DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
718e3744 1163
1164 /* Clear previous distribute-name. */
020709f9 1165 if (DISTRIBUTE_NAME (ospf, type))
1166 free (DISTRIBUTE_NAME (ospf, type));
718e3744 1167
1168 /* Set distribute-name. */
020709f9 1169 DISTRIBUTE_NAME (ospf, type) = strdup (name);
718e3744 1170
1171 /* If access-list have been set, schedule update timer. */
020709f9 1172 if (DISTRIBUTE_LIST (ospf, type))
7c8ff89e 1173 ospf_distribute_list_update (ospf, type, 0);
718e3744 1174
1175 return CMD_SUCCESS;
1176}
1177
1178int
6c835671 1179ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name)
718e3744 1180{
1181 /* Schedule update timer. */
020709f9 1182 if (DISTRIBUTE_LIST (ospf, type))
7c8ff89e 1183 ospf_distribute_list_update (ospf, type, 0);
718e3744 1184
1185 /* Unset distribute-list. */
020709f9 1186 DISTRIBUTE_LIST (ospf, type) = NULL;
718e3744 1187
1188 /* Clear distribute-name. */
020709f9 1189 if (DISTRIBUTE_NAME (ospf, type))
1190 free (DISTRIBUTE_NAME (ospf, type));
cf795c5d 1191
020709f9 1192 DISTRIBUTE_NAME (ospf, type) = NULL;
718e3744 1193
1194 return CMD_SUCCESS;
1195}
1196
1197/* distribute-list update timer. */
4dadc291 1198static int
718e3744 1199ospf_distribute_list_update_timer (struct thread *thread)
1200{
1201 struct route_node *rn;
1202 struct external_info *ei;
1203 struct route_table *rt;
1204 struct ospf_lsa *lsa;
46154fe3 1205 int type, default_refresh = 0;
020709f9 1206 struct ospf *ospf;
718e3744 1207
020709f9 1208 ospf = ospf_lookup ();
1209 if (ospf == NULL)
1210 return 0;
1211
68980084 1212 ospf->t_distribute_update = NULL;
718e3744 1213
1214 zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
1215
1216 /* foreach all external info. */
274d3f09
JT
1217 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
1218 {
7c8ff89e
DS
1219 struct list *ext_list;
1220 struct listnode *node;
1221 struct ospf_external *ext;
1222
1223 ext_list = om->external[type];
1224 if (!ext_list)
1225 continue;
1226
1227 for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext))
1228 {
1229 rt = ext->external_info;
1230 if (!rt)
1231 continue;
1232 for (rn = route_top (rt); rn; rn = route_next (rn))
1233 if ((ei = rn->info) != NULL)
1234 {
1235 if (is_prefix_default (&ei->p))
1236 default_refresh = 1;
1237 else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
1238 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
1239 else
1240 ospf_external_lsa_originate (ospf, ei);
1241 }
1242 }
274d3f09 1243 }
46154fe3
JT
1244 if (default_refresh)
1245 ospf_external_lsa_refresh_default (ospf);
718e3744 1246 return 0;
1247}
1248
718e3744 1249/* Update distribute-list and set timer to apply access-list. */
1250void
7c8ff89e
DS
1251ospf_distribute_list_update (struct ospf *ospf, uintptr_t type,
1252 u_short instance)
718e3744 1253{
1254 struct route_table *rt;
7c8ff89e 1255 struct ospf_external *ext;
cf795c5d 1256
718e3744 1257 /* External info does not exist. */
7c8ff89e
DS
1258 ext = ospf_external_lookup(type, instance);
1259 if (!ext || !(rt = EXTERNAL_INFO (ext)))
718e3744 1260 return;
1261
45acaa0a 1262 /* If exists previously invoked thread, then let it continue. */
68980084 1263 if (ospf->t_distribute_update)
45acaa0a 1264 return;
718e3744 1265
1266 /* Set timer. */
68980084 1267 ospf->t_distribute_update =
3dfc79c2
DW
1268 thread_add_timer_msec (master, ospf_distribute_list_update_timer,
1269 (void *) type, ospf->min_ls_interval);
718e3744 1270}
1271
1272/* If access-list is updated, apply some check. */
4dadc291 1273static void
718e3744 1274ospf_filter_update (struct access_list *access)
1275{
020709f9 1276 struct ospf *ospf;
718e3744 1277 int type;
1278 int abr_inv = 0;
1279 struct ospf_area *area;
52dc7ee6 1280 struct listnode *node;
718e3744 1281
7c8ff89e 1282 /* If OSPF instance does not exist, return right now. */
020709f9 1283 ospf = ospf_lookup ();
68980084 1284 if (ospf == NULL)
718e3744 1285 return;
1286
718e3744 1287 /* Update distribute-list, and apply filter. */
01018ce4 1288 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
718e3744 1289 {
7c8ff89e
DS
1290 struct list *red_list;
1291 struct listnode *node;
1292 struct ospf_redist *red;
1293
1294 red_list = ospf->redist[type];
1295 if (red_list)
1296 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
1297 {
1298 if (ROUTEMAP (red))
1299 {
1300 /* if route-map is not NULL it may be using this access list */
1301 ospf_distribute_list_update (ospf, type, red->instance);
1302 }
1303 }
cf795c5d 1304
01018ce4 1305 /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX),
1306 * but no distribute list. */
1307 if (type == ZEBRA_ROUTE_MAX)
1308 break;
718e3744 1309
020709f9 1310 if (DISTRIBUTE_NAME (ospf, type))
cf795c5d 1311 {
1312 /* Keep old access-list for distribute-list. */
1313 struct access_list *old = DISTRIBUTE_LIST (ospf, type);
1314
1315 /* Update access-list for distribute-list. */
1316 DISTRIBUTE_LIST (ospf, type) =
1317 access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type));
1318
1319 /* No update for this distribute type. */
1320 if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL)
1321 continue;
1322
1323 /* Schedule distribute-list update timer. */
1324 if (DISTRIBUTE_LIST (ospf, type) == NULL ||
1325 strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
7c8ff89e 1326 ospf_distribute_list_update (ospf, type, 0);
cf795c5d 1327 }
718e3744 1328 }
1329
1330 /* Update Area access-list. */
1eb8ef25 1331 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1332 {
1333 if (EXPORT_NAME (area))
1334 {
1335 EXPORT_LIST (area) = NULL;
1336 abr_inv++;
1337 }
cf795c5d 1338
1eb8ef25 1339 if (IMPORT_NAME (area))
1340 {
1341 IMPORT_LIST (area) = NULL;
1342 abr_inv++;
1343 }
1344 }
718e3744 1345
1346 /* Schedule ABR tasks -- this will be changed -- takada. */
020709f9 1347 if (IS_OSPF_ABR (ospf) && abr_inv)
68980084 1348 ospf_schedule_abr_task (ospf);
718e3744 1349}
dd669bb0 1350
1351/* If prefix-list is updated, do some updates. */
1352void
1353ospf_prefix_list_update (struct prefix_list *plist)
1354{
1355 struct ospf *ospf;
1356 int type;
1357 int abr_inv = 0;
1358 struct ospf_area *area;
52dc7ee6 1359 struct listnode *node;
dd669bb0 1360
1361 /* If OSPF instatnce does not exist, return right now. */
1362 ospf = ospf_lookup ();
1363 if (ospf == NULL)
1364 return;
1365
1366 /* Update all route-maps which are used as redistribution filters.
1367 * They might use prefix-list.
1368 */
01018ce4 1369 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
dd669bb0 1370 {
7c8ff89e
DS
1371 struct list *red_list;
1372 struct listnode *node;
1373 struct ospf_redist *red;
1374
1375 red_list = ospf->redist[type];
1376 if (red_list)
1377 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
1378 {
1379 if (ROUTEMAP (red))
1380 {
1381 /* if route-map is not NULL it may be using this prefix list */
1382 ospf_distribute_list_update (ospf, type, red->instance);
1383 }
1384 }
dd669bb0 1385 }
1386
1387 /* Update area filter-lists. */
1eb8ef25 1388 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1389 {
1390 /* Update filter-list in. */
1391 if (PREFIX_NAME_IN (area))
a38401b6 1392 if (strcmp (PREFIX_NAME_IN (area), prefix_list_name (plist)) == 0)
1eb8ef25 1393 {
1394 PREFIX_LIST_IN (area) =
1395 prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
1396 abr_inv++;
1397 }
dd669bb0 1398
1eb8ef25 1399 /* Update filter-list out. */
1400 if (PREFIX_NAME_OUT (area))
a38401b6 1401 if (strcmp (PREFIX_NAME_OUT (area), prefix_list_name (plist)) == 0)
1eb8ef25 1402 {
1403 PREFIX_LIST_IN (area) =
1404 prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
1405 abr_inv++;
1406 }
1407 }
dd669bb0 1408
1409 /* Schedule ABR task. */
1410 if (IS_OSPF_ABR (ospf) && abr_inv)
1411 ospf_schedule_abr_task (ospf);
1412}
cf795c5d 1413
4dadc291 1414static struct ospf_distance *
1415ospf_distance_new (void)
718e3744 1416{
393deb9b 1417 return XCALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
718e3744 1418}
1419
4dadc291 1420static void
718e3744 1421ospf_distance_free (struct ospf_distance *odistance)
1422{
1423 XFREE (MTYPE_OSPF_DISTANCE, odistance);
1424}
1425
1426int
6c835671 1427ospf_distance_set (struct vty *vty, struct ospf *ospf,
1428 const char *distance_str,
1429 const char *ip_str,
1430 const char *access_list_str)
718e3744 1431{
1432 int ret;
1433 struct prefix_ipv4 p;
1434 u_char distance;
1435 struct route_node *rn;
1436 struct ospf_distance *odistance;
1437
1438 ret = str2prefix_ipv4 (ip_str, &p);
1439 if (ret == 0)
1440 {
1441 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1442 return CMD_WARNING;
1443 }
1444
1445 distance = atoi (distance_str);
1446
1447 /* Get OSPF distance node. */
68980084 1448 rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
718e3744 1449 if (rn->info)
1450 {
1451 odistance = rn->info;
1452 route_unlock_node (rn);
1453 }
1454 else
1455 {
1456 odistance = ospf_distance_new ();
1457 rn->info = odistance;
1458 }
1459
1460 /* Set distance value. */
1461 odistance->distance = distance;
1462
1463 /* Reset access-list configuration. */
1464 if (odistance->access_list)
1465 {
1466 free (odistance->access_list);
1467 odistance->access_list = NULL;
1468 }
1469 if (access_list_str)
1470 odistance->access_list = strdup (access_list_str);
1471
1472 return CMD_SUCCESS;
1473}
1474
1475int
6c835671 1476ospf_distance_unset (struct vty *vty, struct ospf *ospf,
1477 const char *distance_str,
1478 const char *ip_str, char
1479 const *access_list_str)
718e3744 1480{
1481 int ret;
1482 struct prefix_ipv4 p;
718e3744 1483 struct route_node *rn;
1484 struct ospf_distance *odistance;
1485
1486 ret = str2prefix_ipv4 (ip_str, &p);
1487 if (ret == 0)
1488 {
1489 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1490 return CMD_WARNING;
1491 }
1492
cf795c5d 1493 rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p);
1494 if (!rn)
718e3744 1495 {
1496 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
1497 return CMD_WARNING;
1498 }
1499
1500 odistance = rn->info;
1501
1502 if (odistance->access_list)
1503 free (odistance->access_list);
1504 ospf_distance_free (odistance);
1505
1506 rn->info = NULL;
1507 route_unlock_node (rn);
1508 route_unlock_node (rn);
1509
1510 return CMD_SUCCESS;
1511}
1512
1513void
68980084 1514ospf_distance_reset (struct ospf *ospf)
718e3744 1515{
1516 struct route_node *rn;
1517 struct ospf_distance *odistance;
1518
68980084 1519 for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
718e3744 1520 if ((odistance = rn->info) != NULL)
1521 {
cf795c5d 1522 if (odistance->access_list)
1523 free (odistance->access_list);
1524 ospf_distance_free (odistance);
1525 rn->info = NULL;
1526 route_unlock_node (rn);
718e3744 1527 }
1528}
1529
1530u_char
1531ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
1532{
020709f9 1533 struct ospf *ospf;
718e3744 1534
020709f9 1535 ospf = ospf_lookup ();
68980084 1536 if (ospf == NULL)
718e3744 1537 return 0;
1538
68980084 1539 if (ospf->distance_intra)
718e3744 1540 if (or->path_type == OSPF_PATH_INTRA_AREA)
68980084 1541 return ospf->distance_intra;
718e3744 1542
68980084 1543 if (ospf->distance_inter)
718e3744 1544 if (or->path_type == OSPF_PATH_INTER_AREA)
68980084 1545 return ospf->distance_inter;
718e3744 1546
68980084 1547 if (ospf->distance_external)
718e3744 1548 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
cf795c5d 1549 || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
68980084 1550 return ospf->distance_external;
cf795c5d 1551
68980084 1552 if (ospf->distance_all)
1553 return ospf->distance_all;
718e3744 1554
1555 return 0;
1556}
1557
7076bb2f
FL
1558static void
1559ospf_zebra_connected (struct zclient *zclient)
1560{
0e5223e7 1561 zclient_send_reg_requests (zclient, VRF_DEFAULT);
7076bb2f
FL
1562}
1563
718e3744 1564void
4140ca4d 1565ospf_zebra_init (struct thread_master *master, u_short instance)
718e3744 1566{
1567 /* Allocate zebra structure. */
4140ca4d 1568 zclient = zclient_new(master);
7c8ff89e 1569 zclient_init (zclient, ZEBRA_ROUTE_OSPF, instance);
7076bb2f 1570 zclient->zebra_connected = ospf_zebra_connected;
18a6dce6 1571 zclient->router_id_update = ospf_router_id_update_zebra;
718e3744 1572 zclient->interface_add = ospf_interface_add;
1573 zclient->interface_delete = ospf_interface_delete;
1574 zclient->interface_up = ospf_interface_state_up;
1575 zclient->interface_down = ospf_interface_state_down;
1576 zclient->interface_address_add = ospf_interface_address_add;
1577 zclient->interface_address_delete = ospf_interface_address_delete;
1578 zclient->ipv4_route_add = ospf_zebra_read_ipv4;
1579 zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
5048fe14 1580 zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4;
1581 zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4;
718e3744 1582
1583 access_list_add_hook (ospf_filter_update);
1584 access_list_delete_hook (ospf_filter_update);
dd669bb0 1585 prefix_list_add_hook (ospf_prefix_list_update);
1586 prefix_list_delete_hook (ospf_prefix_list_update);
718e3744 1587}