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