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