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