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