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