]>
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" | |
47 | #include "ospfd/ospf_zebra.h" | |
48 | #ifdef HAVE_SNMP | |
49 | #include "ospfd/ospf_snmp.h" | |
50 | #endif /* HAVE_SNMP */ | |
51 | ||
52 | /* Zebra structure to hold current status. */ | |
53 | struct zclient *zclient = NULL; | |
54 | ||
55 | /* For registering threads. */ | |
56 | extern struct thread_master *master; | |
18a6dce6 | 57 | struct in_addr router_id_zebra; |
58 | ||
59 | /* Router-id update message from zebra. */ | |
60 | int | |
61 | ospf_router_id_update_zebra (int command, struct zclient *zclient, | |
62 | zebra_size_t length) | |
63 | { | |
64 | struct ospf *ospf; | |
65 | struct prefix router_id; | |
66 | zebra_router_id_update_read(zclient->ibuf,&router_id); | |
67 | ||
68 | router_id_zebra = router_id.u.prefix4; | |
69 | ||
70 | ospf = ospf_lookup (); | |
71 | if (ospf != NULL) | |
72 | { | |
73 | if (ospf->t_router_id_update == NULL) | |
74 | OSPF_TIMER_ON (ospf->t_router_id_update, ospf_router_id_update_timer, | |
75 | OSPF_ROUTER_ID_UPDATE_DELAY); | |
76 | } | |
77 | return 0; | |
78 | } | |
718e3744 | 79 | |
80 | /* Inteface addition message from zebra. */ | |
81 | int | |
82 | ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length) | |
83 | { | |
84 | struct interface *ifp; | |
020709f9 | 85 | struct ospf *ospf; |
718e3744 | 86 | |
87 | ifp = zebra_interface_add_read (zclient->ibuf); | |
88 | ||
89 | if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) | |
90 | zlog_info ("Zebra: interface add %s index %d flags %ld metric %d mtu %d", | |
cf795c5d | 91 | ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); |
718e3744 | 92 | |
cf795c5d | 93 | assert (ifp->info); |
f2c80652 | 94 | |
718e3744 | 95 | if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type)) |
96 | { | |
97 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), type); | |
98 | IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST; | |
cf795c5d | 99 | |
718e3744 | 100 | if (if_is_broadcast (ifp)) |
cf795c5d | 101 | IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST; |
718e3744 | 102 | else if (if_is_pointopoint (ifp)) |
cf795c5d | 103 | IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOPOINT; |
718e3744 | 104 | else if (if_is_loopback (ifp)) |
cf795c5d | 105 | IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_LOOPBACK; |
718e3744 | 106 | } |
107 | ||
020709f9 | 108 | ospf = ospf_lookup (); |
109 | if (ospf != NULL) | |
110 | ospf_if_update (ospf); | |
718e3744 | 111 | |
112 | #ifdef HAVE_SNMP | |
113 | ospf_snmp_if_update (ifp); | |
114 | #endif /* HAVE_SNMP */ | |
115 | ||
116 | return 0; | |
117 | } | |
118 | ||
119 | int | |
120 | ospf_interface_delete (int command, struct zclient *zclient, | |
cf795c5d | 121 | zebra_size_t length) |
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 */ |
129 | ifp = zebra_interface_state_read (s); | |
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)) |
cf795c5d | 139 | zlog_info |
140 | ("Zebra: interface delete %s index %d flags %ld metric %d mtu %d", | |
141 | ifp->name, ifp->ifindex, 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 | ||
718e3744 | 151 | return 0; |
152 | } | |
153 | ||
154 | struct interface * | |
155 | zebra_interface_if_lookup (struct stream *s) | |
156 | { | |
157 | struct interface *ifp; | |
158 | u_char ifname_tmp[INTERFACE_NAMSIZ]; | |
159 | ||
160 | /* Read interface name. */ | |
161 | stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); | |
162 | ||
163 | /* Lookup this by interface index. */ | |
c9e52be3 | 164 | ifp = if_lookup_by_name ((char *) ifname_tmp); |
718e3744 | 165 | |
166 | /* If such interface does not exist, indicate an error */ | |
167 | if (!ifp) | |
168 | return NULL; | |
169 | ||
170 | return ifp; | |
171 | } | |
172 | ||
718e3744 | 173 | int |
174 | ospf_interface_state_up (int command, struct zclient *zclient, | |
cf795c5d | 175 | zebra_size_t length) |
718e3744 | 176 | { |
177 | struct interface *ifp; | |
178 | struct interface if_tmp; | |
179 | struct ospf_interface *oi; | |
180 | struct route_node *rn; | |
cf795c5d | 181 | |
718e3744 | 182 | ifp = zebra_interface_if_lookup (zclient->ibuf); |
183 | ||
184 | if (ifp == NULL) | |
185 | return 0; | |
186 | ||
187 | /* Interface is already up. */ | |
2e3b2e47 | 188 | if (if_is_operative (ifp)) |
718e3744 | 189 | { |
190 | /* Temporarily keep ifp values. */ | |
191 | memcpy (&if_tmp, ifp, sizeof (struct interface)); | |
192 | ||
193 | zebra_interface_if_set_value (zclient->ibuf, ifp); | |
194 | ||
195 | if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) | |
cf795c5d | 196 | zlog_info ("Zebra: Interface[%s] state update.", ifp->name); |
718e3744 | 197 | |
198 | if (if_tmp.bandwidth != ifp->bandwidth) | |
cf795c5d | 199 | { |
200 | if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) | |
201 | zlog_info ("Zebra: Interface[%s] bandwidth change %d -> %d.", | |
202 | ifp->name, if_tmp.bandwidth, ifp->bandwidth); | |
718e3744 | 203 | |
cf795c5d | 204 | ospf_if_recalculate_output_cost (ifp); |
205 | } | |
718e3744 | 206 | return 0; |
207 | } | |
cf795c5d | 208 | |
718e3744 | 209 | zebra_interface_if_set_value (zclient->ibuf, ifp); |
cf795c5d | 210 | |
718e3744 | 211 | if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) |
212 | zlog_info ("Zebra: Interface[%s] state change to up.", ifp->name); | |
cf795c5d | 213 | |
214 | for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) | |
718e3744 | 215 | { |
cf795c5d | 216 | if ((oi = rn->info) == NULL) |
217 | continue; | |
218 | ||
718e3744 | 219 | ospf_if_up (oi); |
220 | } | |
cf795c5d | 221 | |
718e3744 | 222 | return 0; |
223 | } | |
224 | ||
225 | int | |
226 | ospf_interface_state_down (int command, struct zclient *zclient, | |
cf795c5d | 227 | zebra_size_t length) |
718e3744 | 228 | { |
229 | struct interface *ifp; | |
230 | struct ospf_interface *oi; | |
231 | struct route_node *node; | |
232 | ||
233 | ifp = zebra_interface_state_read (zclient->ibuf); | |
234 | ||
235 | if (ifp == NULL) | |
236 | return 0; | |
237 | ||
238 | if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) | |
239 | zlog_info ("Zebra: Interface[%s] state change to down.", ifp->name); | |
240 | ||
cf795c5d | 241 | for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node)) |
718e3744 | 242 | { |
cf795c5d | 243 | if ((oi = node->info) == NULL) |
244 | continue; | |
718e3744 | 245 | ospf_if_down (oi); |
246 | } | |
247 | ||
248 | return 0; | |
249 | } | |
250 | ||
251 | int | |
252 | ospf_interface_address_add (int command, struct zclient *zclient, | |
cf795c5d | 253 | zebra_size_t length) |
718e3744 | 254 | { |
020709f9 | 255 | struct ospf *ospf; |
718e3744 | 256 | struct connected *c; |
257 | ||
0a589359 | 258 | c = zebra_interface_address_read (command, zclient->ibuf); |
718e3744 | 259 | |
260 | if (c == NULL) | |
261 | return 0; | |
262 | ||
020709f9 | 263 | ospf = ospf_lookup (); |
264 | if (ospf != NULL) | |
265 | ospf_if_update (ospf); | |
718e3744 | 266 | |
267 | #ifdef HAVE_SNMP | |
268 | ospf_snmp_if_update (c->ifp); | |
269 | #endif /* HAVE_SNMP */ | |
270 | ||
271 | return 0; | |
272 | } | |
273 | ||
274 | int | |
275 | ospf_interface_address_delete (int command, struct zclient *zclient, | |
cf795c5d | 276 | zebra_size_t length) |
718e3744 | 277 | { |
020709f9 | 278 | struct ospf *ospf; |
718e3744 | 279 | struct connected *c; |
280 | struct interface *ifp; | |
281 | struct ospf_interface *oi; | |
282 | struct route_node *rn; | |
283 | struct prefix p; | |
284 | ||
0a589359 | 285 | c = zebra_interface_address_read (command, zclient->ibuf); |
718e3744 | 286 | |
287 | if (c == NULL) | |
288 | return 0; | |
289 | ||
290 | ifp = c->ifp; | |
291 | p = *c->address; | |
292 | p.prefixlen = IPV4_MAX_PREFIXLEN; | |
293 | ||
294 | rn = route_node_lookup (IF_OIFS (ifp), &p); | |
cf795c5d | 295 | if (!rn) |
718e3744 | 296 | return 0; |
297 | ||
298 | assert (rn->info); | |
299 | oi = rn->info; | |
cf795c5d | 300 | |
718e3744 | 301 | /* Call interface hook functions to clean up */ |
302 | ospf_if_free (oi); | |
cf795c5d | 303 | |
718e3744 | 304 | #ifdef HAVE_SNMP |
305 | ospf_snmp_if_update (c->ifp); | |
306 | #endif /* HAVE_SNMP */ | |
307 | ||
308 | connected_free (c); | |
309 | ||
020709f9 | 310 | ospf = ospf_lookup (); |
311 | if (ospf != NULL) | |
312 | ospf_if_update (ospf); | |
718e3744 | 313 | |
314 | return 0; | |
315 | } | |
72357f2b | 316 | |
718e3744 | 317 | void |
318 | ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) | |
319 | { | |
320 | u_char message; | |
321 | u_char distance; | |
322 | u_char flags; | |
323 | int psize; | |
324 | struct stream *s; | |
325 | struct ospf_path *path; | |
52dc7ee6 | 326 | struct listnode *node; |
718e3744 | 327 | |
328 | if (zclient->redist[ZEBRA_ROUTE_OSPF]) | |
329 | { | |
330 | message = 0; | |
331 | flags = 0; | |
332 | ||
333 | /* OSPF pass nexthop and metric */ | |
334 | SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); | |
335 | SET_FLAG (message, ZAPI_MESSAGE_METRIC); | |
336 | ||
337 | /* Distance value. */ | |
338 | distance = ospf_distance_apply (p, or); | |
339 | if (distance) | |
72357f2b | 340 | SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); |
718e3744 | 341 | |
342 | /* Make packet. */ | |
343 | s = zclient->obuf; | |
344 | stream_reset (s); | |
345 | ||
346 | /* Length place holder. */ | |
347 | stream_putw (s, 0); | |
348 | ||
349 | /* Put command, type, flags, message. */ | |
350 | stream_putc (s, ZEBRA_IPV4_ROUTE_ADD); | |
351 | stream_putc (s, ZEBRA_ROUTE_OSPF); | |
352 | stream_putc (s, flags); | |
353 | stream_putc (s, message); | |
cf795c5d | 354 | |
718e3744 | 355 | /* Put prefix information. */ |
356 | psize = PSIZE (p->prefixlen); | |
357 | stream_putc (s, p->prefixlen); | |
cf795c5d | 358 | stream_write (s, (u_char *) & p->prefix, psize); |
718e3744 | 359 | |
360 | /* Nexthop count. */ | |
96735eea | 361 | stream_putc (s, or->paths->count); |
718e3744 | 362 | |
363 | /* Nexthop, ifindex, distance and metric information. */ | |
96735eea | 364 | for (node = listhead (or->paths); node; nextnode (node)) |
72357f2b | 365 | { |
cf795c5d | 366 | path = getdata (node); |
367 | ||
368 | if (path->nexthop.s_addr != INADDR_ANY) | |
369 | { | |
370 | stream_putc (s, ZEBRA_NEXTHOP_IPV4); | |
371 | stream_put_in_addr (s, &path->nexthop); | |
372 | } | |
373 | else | |
374 | { | |
375 | stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); | |
376 | if (path->oi) | |
377 | stream_putl (s, path->oi->ifp->ifindex); | |
378 | else | |
379 | stream_putl (s, 0); | |
380 | } | |
72357f2b | 381 | |
382 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) | |
383 | { | |
384 | zlog_info ("Zebra: Route add %s/%d nexthop %s", | |
cf795c5d | 385 | inet_ntoa (p->prefix), |
386 | p->prefixlen, inet_ntoa (path->nexthop)); | |
387 | } | |
388 | } | |
718e3744 | 389 | |
390 | if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) | |
cf795c5d | 391 | stream_putc (s, distance); |
718e3744 | 392 | if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) |
cf795c5d | 393 | { |
394 | if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) | |
395 | stream_putl (s, or->cost + or->u.ext.type2_cost); | |
396 | else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) | |
397 | stream_putl (s, or->u.ext.type2_cost); | |
398 | else | |
399 | stream_putl (s, or->cost); | |
400 | } | |
718e3744 | 401 | |
402 | stream_putw_at (s, 0, stream_get_endp (s)); | |
403 | ||
404 | writen (zclient->sock, s->data, stream_get_endp (s)); | |
718e3744 | 405 | } |
406 | } | |
407 | ||
408 | void | |
409 | ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or) | |
410 | { | |
411 | struct zapi_ipv4 api; | |
72357f2b | 412 | struct ospf_path *path; |
413 | struct in_addr *nexthop; | |
52dc7ee6 | 414 | struct listnode *node; |
718e3744 | 415 | |
416 | if (zclient->redist[ZEBRA_ROUTE_OSPF]) | |
417 | { | |
418 | api.type = ZEBRA_ROUTE_OSPF; | |
419 | api.flags = 0; | |
420 | api.message = 0; | |
72357f2b | 421 | api.ifindex_num = 0; |
422 | api.nexthop_num = 0; | |
718e3744 | 423 | |
96735eea | 424 | for (node = listhead (or->paths); node; nextnode (node)) |
cf795c5d | 425 | { |
426 | path = getdata (node); | |
427 | ||
428 | if (path->nexthop.s_addr != INADDR_ANY) | |
429 | { | |
d8e1d6bc | 430 | SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); |
cf795c5d | 431 | api.nexthop_num = 1; |
432 | nexthop = &path->nexthop; | |
433 | api.nexthop = &nexthop; | |
434 | } | |
2db3d05d | 435 | else if (ospf_if_exists(path->oi) && (path->oi->ifp)) |
bb8ff1e7 | 436 | { |
437 | SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); | |
438 | api.ifindex_num = 1; | |
439 | api.ifindex = &path->oi->ifp->ifindex; | |
440 | } | |
441 | else if ( IS_DEBUG_OSPF(zebra,ZEBRA_REDISTRIBUTE) ) | |
442 | { | |
443 | zlog_info("Zebra: no ifp %s %d", | |
444 | inet_ntoa(p->prefix), | |
445 | p->prefixlen); | |
446 | } | |
72357f2b | 447 | |
0a589359 | 448 | zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); |
72357f2b | 449 | |
450 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.nexthop_num) | |
cf795c5d | 451 | { |
452 | zlog_info ("Zebra: Route delete %s/%d nexthop %s", | |
453 | inet_ntoa (p->prefix), | |
454 | p->prefixlen, inet_ntoa (**api.nexthop)); | |
455 | } | |
bb8ff1e7 | 456 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.ifindex_num) |
457 | { | |
458 | zlog_info ("Zebra: Route delete %s/%d ifindex %d", | |
459 | inet_ntoa (p->prefix), | |
460 | p->prefixlen, *api.ifindex); | |
461 | } | |
cf795c5d | 462 | } |
718e3744 | 463 | } |
464 | } | |
465 | ||
466 | void | |
467 | ospf_zebra_add_discard (struct prefix_ipv4 *p) | |
468 | { | |
469 | struct zapi_ipv4 api; | |
470 | ||
471 | if (zclient->redist[ZEBRA_ROUTE_OSPF]) | |
472 | { | |
473 | api.type = ZEBRA_ROUTE_OSPF; | |
474 | api.flags = ZEBRA_FLAG_BLACKHOLE; | |
475 | api.message = 0; | |
476 | SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); | |
477 | api.nexthop_num = 0; | |
478 | api.ifindex_num = 0; | |
479 | ||
0a589359 | 480 | zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); |
718e3744 | 481 | } |
482 | } | |
483 | ||
484 | void | |
485 | ospf_zebra_delete_discard (struct prefix_ipv4 *p) | |
486 | { | |
487 | struct zapi_ipv4 api; | |
488 | ||
489 | if (zclient->redist[ZEBRA_ROUTE_OSPF]) | |
490 | { | |
491 | api.type = ZEBRA_ROUTE_OSPF; | |
492 | api.flags = ZEBRA_FLAG_BLACKHOLE; | |
493 | api.message = 0; | |
494 | SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); | |
495 | api.nexthop_num = 0; | |
496 | api.ifindex_num = 0; | |
497 | ||
0a589359 | 498 | zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); |
72357f2b | 499 | |
500 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) | |
cf795c5d | 501 | zlog_info ("Zebra: Route delete discard %s/%d", |
502 | inet_ntoa (p->prefix), p->prefixlen); | |
72357f2b | 503 | |
718e3744 | 504 | } |
505 | } | |
506 | ||
507 | int | |
508 | ospf_is_type_redistributed (int type) | |
509 | { | |
510 | return (DEFAULT_ROUTE_TYPE (type)) ? | |
511 | zclient->default_information : zclient->redist[type]; | |
512 | } | |
513 | ||
514 | int | |
020709f9 | 515 | ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue) |
718e3744 | 516 | { |
517 | int force = 0; | |
cf795c5d | 518 | |
718e3744 | 519 | if (ospf_is_type_redistributed (type)) |
520 | { | |
68980084 | 521 | if (mtype != ospf->dmetric[type].type) |
cf795c5d | 522 | { |
523 | ospf->dmetric[type].type = mtype; | |
524 | force = LSA_REFRESH_FORCE; | |
525 | } | |
68980084 | 526 | if (mvalue != ospf->dmetric[type].value) |
cf795c5d | 527 | { |
528 | ospf->dmetric[type].value = mvalue; | |
529 | force = LSA_REFRESH_FORCE; | |
530 | } | |
531 | ||
68980084 | 532 | ospf_external_lsa_refresh_type (ospf, type, force); |
cf795c5d | 533 | |
718e3744 | 534 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) |
cf795c5d | 535 | zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]", |
536 | LOOKUP (ospf_redistributed_proto, type), | |
537 | metric_type (ospf, type), metric_value (ospf, type)); | |
538 | ||
718e3744 | 539 | return CMD_SUCCESS; |
540 | } | |
541 | ||
68980084 | 542 | ospf->dmetric[type].type = mtype; |
543 | ospf->dmetric[type].value = mvalue; | |
718e3744 | 544 | |
0a589359 | 545 | zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type); |
718e3744 | 546 | |
547 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) | |
548 | zlog_info ("Redistribute[%s]: Start Type[%d], Metric[%d]", | |
cf795c5d | 549 | LOOKUP (ospf_redistributed_proto, type), |
550 | metric_type (ospf, type), metric_value (ospf, type)); | |
551 | ||
68980084 | 552 | ospf_asbr_status_update (ospf, ++ospf->redistribute); |
718e3744 | 553 | |
554 | return CMD_SUCCESS; | |
555 | } | |
556 | ||
557 | int | |
020709f9 | 558 | ospf_redistribute_unset (struct ospf *ospf, int type) |
718e3744 | 559 | { |
560 | if (type == zclient->redist_default) | |
561 | return CMD_SUCCESS; | |
562 | ||
cf795c5d | 563 | if (!ospf_is_type_redistributed (type)) |
718e3744 | 564 | return CMD_SUCCESS; |
565 | ||
0a589359 | 566 | zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type); |
cf795c5d | 567 | |
718e3744 | 568 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) |
569 | zlog_info ("Redistribute[%s]: Stop", | |
cf795c5d | 570 | LOOKUP (ospf_redistributed_proto, type)); |
718e3744 | 571 | |
68980084 | 572 | ospf->dmetric[type].type = -1; |
573 | ospf->dmetric[type].value = -1; | |
718e3744 | 574 | |
575 | /* Remove the routes from OSPF table. */ | |
576 | ospf_redistribute_withdraw (type); | |
577 | ||
68980084 | 578 | ospf_asbr_status_update (ospf, --ospf->redistribute); |
718e3744 | 579 | |
580 | return CMD_SUCCESS; | |
581 | } | |
582 | ||
583 | int | |
020709f9 | 584 | ospf_redistribute_default_set (struct ospf *ospf, int originate, |
cf795c5d | 585 | int mtype, int mvalue) |
718e3744 | 586 | { |
587 | int force = 0; | |
020709f9 | 588 | |
718e3744 | 589 | if (ospf_is_type_redistributed (DEFAULT_ROUTE)) |
590 | { | |
68980084 | 591 | if (mtype != ospf->dmetric[DEFAULT_ROUTE].type) |
cf795c5d | 592 | { |
593 | ospf->dmetric[DEFAULT_ROUTE].type = mtype; | |
594 | force = 1; | |
595 | } | |
68980084 | 596 | if (mvalue != ospf->dmetric[DEFAULT_ROUTE].value) |
cf795c5d | 597 | { |
598 | force = 1; | |
599 | ospf->dmetric[DEFAULT_ROUTE].value = mvalue; | |
600 | } | |
601 | ||
68980084 | 602 | ospf_external_lsa_refresh_default (ospf); |
cf795c5d | 603 | |
718e3744 | 604 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) |
cf795c5d | 605 | zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]", |
606 | LOOKUP (ospf_redistributed_proto, DEFAULT_ROUTE), | |
607 | metric_type (ospf, DEFAULT_ROUTE), | |
608 | metric_value (ospf, DEFAULT_ROUTE)); | |
718e3744 | 609 | return CMD_SUCCESS; |
610 | } | |
611 | ||
68980084 | 612 | ospf->default_originate = originate; |
613 | ospf->dmetric[DEFAULT_ROUTE].type = mtype; | |
614 | ospf->dmetric[DEFAULT_ROUTE].value = mvalue; | |
718e3744 | 615 | |
0a589359 | 616 | zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient); |
cf795c5d | 617 | |
718e3744 | 618 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) |
619 | zlog_info ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]", | |
cf795c5d | 620 | metric_type (ospf, DEFAULT_ROUTE), |
621 | metric_value (ospf, DEFAULT_ROUTE)); | |
718e3744 | 622 | |
68980084 | 623 | if (ospf->router_id.s_addr == 0) |
624 | ospf->external_origin |= (1 << DEFAULT_ROUTE); | |
718e3744 | 625 | else |
626 | thread_add_timer (master, ospf_default_originate_timer, | |
cf795c5d | 627 | &ospf->default_originate, 1); |
718e3744 | 628 | |
68980084 | 629 | ospf_asbr_status_update (ospf, ++ospf->redistribute); |
718e3744 | 630 | |
631 | return CMD_SUCCESS; | |
632 | } | |
633 | ||
634 | int | |
020709f9 | 635 | ospf_redistribute_default_unset (struct ospf *ospf) |
718e3744 | 636 | { |
637 | if (!ospf_is_type_redistributed (DEFAULT_ROUTE)) | |
638 | return CMD_SUCCESS; | |
639 | ||
68980084 | 640 | ospf->default_originate = DEFAULT_ORIGINATE_NONE; |
641 | ospf->dmetric[DEFAULT_ROUTE].type = -1; | |
642 | ospf->dmetric[DEFAULT_ROUTE].value = -1; | |
718e3744 | 643 | |
0a589359 | 644 | zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient); |
718e3744 | 645 | |
646 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) | |
647 | zlog_info ("Redistribute[DEFAULT]: Stop"); | |
cf795c5d | 648 | |
68980084 | 649 | ospf_asbr_status_update (ospf, --ospf->redistribute); |
718e3744 | 650 | |
651 | return CMD_SUCCESS; | |
652 | } | |
653 | ||
654 | int | |
020709f9 | 655 | ospf_external_lsa_originate_check (struct ospf *ospf, |
cf795c5d | 656 | struct external_info *ei) |
718e3744 | 657 | { |
658 | /* If prefix is multicast, then do not originate LSA. */ | |
659 | if (IN_MULTICAST (htonl (ei->p.prefix.s_addr))) | |
660 | { | |
661 | zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, " | |
cf795c5d | 662 | "Prefix belongs multicast", inet_ntoa (ei->p.prefix)); |
718e3744 | 663 | return 0; |
664 | } | |
665 | ||
666 | /* Take care of default-originate. */ | |
667 | if (is_prefix_default (&ei->p)) | |
68980084 | 668 | if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) |
718e3744 | 669 | { |
cf795c5d | 670 | zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-exntenal-LSA " |
671 | "for default"); | |
672 | return 0; | |
718e3744 | 673 | } |
674 | ||
675 | return 1; | |
676 | } | |
677 | ||
678 | /* If connected prefix is OSPF enable interface, then do not announce. */ | |
679 | int | |
cf795c5d | 680 | ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei) |
718e3744 | 681 | { |
682 | struct route_node *rn; | |
683 | ||
68980084 | 684 | for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) |
718e3744 | 685 | if (rn->info != NULL) |
cf795c5d | 686 | if (prefix_match (&rn->p, (struct prefix *) &ei->p)) |
687 | { | |
688 | route_unlock_node (rn); | |
689 | return 0; | |
690 | } | |
718e3744 | 691 | |
692 | return 1; | |
693 | } | |
694 | ||
695 | /* return 1 if external LSA must be originated, 0 otherwise */ | |
696 | int | |
68980084 | 697 | ospf_redistribute_check (struct ospf *ospf, |
cf795c5d | 698 | struct external_info *ei, int *changed) |
718e3744 | 699 | { |
700 | struct route_map_set_values save_values; | |
701 | struct prefix_ipv4 *p = &ei->p; | |
702 | u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type; | |
cf795c5d | 703 | |
718e3744 | 704 | if (changed) |
705 | *changed = 0; | |
706 | ||
020709f9 | 707 | if (!ospf_external_lsa_originate_check (ospf, ei)) |
718e3744 | 708 | return 0; |
709 | ||
710 | /* Take care connected route. */ | |
68980084 | 711 | if (type == ZEBRA_ROUTE_CONNECT && |
712 | !ospf_distribute_check_connected (ospf, ei)) | |
718e3744 | 713 | return 0; |
714 | ||
020709f9 | 715 | if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type)) |
718e3744 | 716 | /* distirbute-list exists, but access-list may not? */ |
020709f9 | 717 | if (DISTRIBUTE_LIST (ospf, type)) |
718 | if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY) | |
cf795c5d | 719 | { |
720 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) | |
721 | zlog_info ("Redistribute[%s]: %s/%d filtered by ditribute-list.", | |
722 | LOOKUP (ospf_redistributed_proto, type), | |
723 | inet_ntoa (p->prefix), p->prefixlen); | |
724 | return 0; | |
725 | } | |
718e3744 | 726 | |
727 | save_values = ei->route_map_set; | |
728 | ospf_reset_route_map_set_values (&ei->route_map_set); | |
cf795c5d | 729 | |
718e3744 | 730 | /* apply route-map if needed */ |
020709f9 | 731 | if (ROUTEMAP_NAME (ospf, type)) |
718e3744 | 732 | { |
733 | int ret; | |
734 | ||
cf795c5d | 735 | ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p, |
736 | RMAP_OSPF, ei); | |
718e3744 | 737 | |
738 | if (ret == RMAP_DENYMATCH) | |
cf795c5d | 739 | { |
740 | ei->route_map_set = save_values; | |
741 | if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) | |
742 | zlog_info ("Redistribute[%s]: %s/%d filtered by route-map.", | |
743 | LOOKUP (ospf_redistributed_proto, type), | |
744 | inet_ntoa (p->prefix), p->prefixlen); | |
745 | return 0; | |
746 | } | |
747 | ||
718e3744 | 748 | /* check if 'route-map set' changed something */ |
749 | if (changed) | |
cf795c5d | 750 | *changed = !ospf_route_map_set_compare (&ei->route_map_set, |
751 | &save_values); | |
718e3744 | 752 | } |
753 | ||
754 | return 1; | |
755 | } | |
756 | ||
757 | /* OSPF route-map set for redistribution */ | |
758 | void | |
6c835671 | 759 | ospf_routemap_set (struct ospf *ospf, int type, const char *name) |
718e3744 | 760 | { |
020709f9 | 761 | if (ROUTEMAP_NAME (ospf, type)) |
762 | free (ROUTEMAP_NAME (ospf, type)); | |
718e3744 | 763 | |
020709f9 | 764 | ROUTEMAP_NAME (ospf, type) = strdup (name); |
765 | ROUTEMAP (ospf, type) = route_map_lookup_by_name (name); | |
718e3744 | 766 | } |
767 | ||
768 | void | |
020709f9 | 769 | ospf_routemap_unset (struct ospf *ospf, int type) |
718e3744 | 770 | { |
020709f9 | 771 | if (ROUTEMAP_NAME (ospf, type)) |
772 | free (ROUTEMAP_NAME (ospf, type)); | |
718e3744 | 773 | |
020709f9 | 774 | ROUTEMAP_NAME (ospf, type) = NULL; |
775 | ROUTEMAP (ospf, type) = NULL; | |
718e3744 | 776 | } |
777 | ||
778 | /* Zebra route add and delete treatment. */ | |
779 | int | |
780 | ospf_zebra_read_ipv4 (int command, struct zclient *zclient, | |
cf795c5d | 781 | zebra_size_t length) |
718e3744 | 782 | { |
783 | struct stream *s; | |
784 | struct zapi_ipv4 api; | |
785 | unsigned long ifindex; | |
786 | struct in_addr nexthop; | |
787 | struct prefix_ipv4 p; | |
788 | struct external_info *ei; | |
020709f9 | 789 | struct ospf *ospf; |
718e3744 | 790 | |
791 | s = zclient->ibuf; | |
792 | ifindex = 0; | |
793 | nexthop.s_addr = 0; | |
794 | ||
795 | /* Type, flags, message. */ | |
796 | api.type = stream_getc (s); | |
797 | api.flags = stream_getc (s); | |
798 | api.message = stream_getc (s); | |
799 | ||
800 | /* IPv4 prefix. */ | |
801 | memset (&p, 0, sizeof (struct prefix_ipv4)); | |
802 | p.family = AF_INET; | |
803 | p.prefixlen = stream_getc (s); | |
804 | stream_get (&p.prefix, s, PSIZE (p.prefixlen)); | |
805 | ||
8585d4e5 | 806 | if (IPV4_NET127(ntohl(p.prefix.s_addr))) |
807 | return 0; | |
808 | ||
718e3744 | 809 | /* Nexthop, ifindex, distance, metric. */ |
810 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) | |
811 | { | |
812 | api.nexthop_num = stream_getc (s); | |
813 | nexthop.s_addr = stream_get_ipv4 (s); | |
814 | } | |
815 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) | |
816 | { | |
817 | api.ifindex_num = stream_getc (s); | |
6a8da852 | 818 | /* XXX assert(api.ifindex_num == 1); */ |
718e3744 | 819 | ifindex = stream_getl (s); |
820 | } | |
821 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) | |
822 | api.distance = stream_getc (s); | |
823 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) | |
824 | api.metric = stream_getl (s); | |
825 | ||
020709f9 | 826 | ospf = ospf_lookup (); |
827 | if (ospf == NULL) | |
828 | return 0; | |
829 | ||
718e3744 | 830 | if (command == ZEBRA_IPV4_ROUTE_ADD) |
831 | { | |
7021c425 | 832 | /* XXX|HACK|TODO|FIXME: |
a0a39761 | 833 | * Maybe we should ignore reject/blackhole routes? Testing shows that |
834 | * there is no problems though and this is only way to "summarize" | |
835 | * routes in ASBR at the moment. Maybe we need just a better generalised | |
836 | * solution for these types? | |
837 | * | |
838 | * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE) | |
839 | * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT)) | |
840 | * return 0; | |
7021c425 | 841 | */ |
7021c425 | 842 | |
718e3744 | 843 | ei = ospf_external_info_add (api.type, p, ifindex, nexthop); |
844 | ||
68980084 | 845 | if (ospf->router_id.s_addr == 0) |
cf795c5d | 846 | /* Set flags to generate AS-external-LSA originate event |
847 | for each redistributed protocols later. */ | |
848 | ospf->external_origin |= (1 << api.type); | |
718e3744 | 849 | else |
cf795c5d | 850 | { |
851 | if (ei) | |
852 | { | |
853 | if (is_prefix_default (&p)) | |
854 | ospf_external_lsa_refresh_default (ospf); | |
855 | else | |
856 | { | |
857 | struct ospf_lsa *current; | |
858 | ||
859 | current = ospf_external_info_find_lsa (ospf, &ei->p); | |
860 | if (!current) | |
861 | ospf_external_lsa_originate (ospf, ei); | |
862 | else if (IS_LSA_MAXAGE (current)) | |
863 | ospf_external_lsa_refresh (ospf, current, | |
864 | ei, LSA_REFRESH_FORCE); | |
865 | else | |
866 | zlog_warn ("ospf_zebra_read_ipv4() : %s already exists", | |
867 | inet_ntoa (p.prefix)); | |
868 | } | |
869 | } | |
870 | } | |
718e3744 | 871 | } |
cf795c5d | 872 | else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ |
718e3744 | 873 | { |
874 | ospf_external_info_delete (api.type, p); | |
7021c425 | 875 | if (is_prefix_default (&p)) |
cf795c5d | 876 | ospf_external_lsa_refresh_default (ospf); |
7021c425 | 877 | else |
878 | ospf_external_lsa_flush (ospf, api.type, &p, ifindex, nexthop); | |
718e3744 | 879 | } |
880 | ||
881 | return 0; | |
882 | } | |
718e3744 | 883 | \f |
cf795c5d | 884 | |
718e3744 | 885 | int |
6c835671 | 886 | ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name) |
718e3744 | 887 | { |
888 | /* Lookup access-list for distribute-list. */ | |
020709f9 | 889 | DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name); |
718e3744 | 890 | |
891 | /* Clear previous distribute-name. */ | |
020709f9 | 892 | if (DISTRIBUTE_NAME (ospf, type)) |
893 | free (DISTRIBUTE_NAME (ospf, type)); | |
718e3744 | 894 | |
895 | /* Set distribute-name. */ | |
020709f9 | 896 | DISTRIBUTE_NAME (ospf, type) = strdup (name); |
718e3744 | 897 | |
898 | /* If access-list have been set, schedule update timer. */ | |
020709f9 | 899 | if (DISTRIBUTE_LIST (ospf, type)) |
68980084 | 900 | ospf_distribute_list_update (ospf, type); |
718e3744 | 901 | |
902 | return CMD_SUCCESS; | |
903 | } | |
904 | ||
905 | int | |
6c835671 | 906 | ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name) |
718e3744 | 907 | { |
908 | /* Schedule update timer. */ | |
020709f9 | 909 | if (DISTRIBUTE_LIST (ospf, type)) |
68980084 | 910 | ospf_distribute_list_update (ospf, type); |
718e3744 | 911 | |
912 | /* Unset distribute-list. */ | |
020709f9 | 913 | DISTRIBUTE_LIST (ospf, type) = NULL; |
718e3744 | 914 | |
915 | /* Clear distribute-name. */ | |
020709f9 | 916 | if (DISTRIBUTE_NAME (ospf, type)) |
917 | free (DISTRIBUTE_NAME (ospf, type)); | |
cf795c5d | 918 | |
020709f9 | 919 | DISTRIBUTE_NAME (ospf, type) = NULL; |
718e3744 | 920 | |
921 | return CMD_SUCCESS; | |
922 | } | |
923 | ||
924 | /* distribute-list update timer. */ | |
925 | int | |
926 | ospf_distribute_list_update_timer (struct thread *thread) | |
927 | { | |
928 | struct route_node *rn; | |
929 | struct external_info *ei; | |
930 | struct route_table *rt; | |
931 | struct ospf_lsa *lsa; | |
64511f39 | 932 | int type; |
020709f9 | 933 | struct ospf *ospf; |
718e3744 | 934 | |
935 | type = (int) THREAD_ARG (thread); | |
64511f39 | 936 | assert (type < ZEBRA_ROUTE_MAX); |
937 | ||
718e3744 | 938 | rt = EXTERNAL_INFO (type); |
939 | ||
020709f9 | 940 | ospf = ospf_lookup (); |
941 | if (ospf == NULL) | |
942 | return 0; | |
943 | ||
68980084 | 944 | ospf->t_distribute_update = NULL; |
718e3744 | 945 | |
946 | zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!"); | |
947 | ||
948 | /* foreach all external info. */ | |
949 | if (rt) | |
950 | for (rn = route_top (rt); rn; rn = route_next (rn)) | |
951 | if ((ei = rn->info) != NULL) | |
cf795c5d | 952 | { |
953 | if (is_prefix_default (&ei->p)) | |
954 | ospf_external_lsa_refresh_default (ospf); | |
955 | else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p))) | |
956 | ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED); | |
957 | else | |
958 | ospf_external_lsa_originate (ospf, ei); | |
959 | } | |
718e3744 | 960 | return 0; |
961 | } | |
962 | ||
963 | #define OSPF_DISTRIBUTE_UPDATE_DELAY 5 | |
964 | ||
965 | /* Update distribute-list and set timer to apply access-list. */ | |
966 | void | |
68980084 | 967 | ospf_distribute_list_update (struct ospf *ospf, int type) |
718e3744 | 968 | { |
969 | struct route_table *rt; | |
cf795c5d | 970 | |
718e3744 | 971 | /* External info does not exist. */ |
972 | if (!(rt = EXTERNAL_INFO (type))) | |
973 | return; | |
974 | ||
975 | /* If exists previously invoked thread, then cancel it. */ | |
68980084 | 976 | if (ospf->t_distribute_update) |
977 | OSPF_TIMER_OFF (ospf->t_distribute_update); | |
718e3744 | 978 | |
979 | /* Set timer. */ | |
68980084 | 980 | ospf->t_distribute_update = |
718e3744 | 981 | thread_add_timer (master, ospf_distribute_list_update_timer, |
cf795c5d | 982 | (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY); |
718e3744 | 983 | } |
984 | ||
985 | /* If access-list is updated, apply some check. */ | |
986 | void | |
987 | ospf_filter_update (struct access_list *access) | |
988 | { | |
020709f9 | 989 | struct ospf *ospf; |
718e3744 | 990 | int type; |
991 | int abr_inv = 0; | |
992 | struct ospf_area *area; | |
52dc7ee6 | 993 | struct listnode *node; |
718e3744 | 994 | |
995 | /* If OSPF instatnce does not exist, return right now. */ | |
020709f9 | 996 | ospf = ospf_lookup (); |
68980084 | 997 | if (ospf == NULL) |
718e3744 | 998 | return; |
999 | ||
718e3744 | 1000 | /* Update distribute-list, and apply filter. */ |
1001 | for (type = 0; type < ZEBRA_ROUTE_MAX; type++) | |
1002 | { | |
020709f9 | 1003 | if (ROUTEMAP (ospf, type) != NULL) |
cf795c5d | 1004 | { |
1005 | /* if route-map is not NULL it may be using this access list */ | |
1006 | ospf_distribute_list_update (ospf, type); | |
1007 | continue; | |
1008 | } | |
1009 | ||
718e3744 | 1010 | |
020709f9 | 1011 | if (DISTRIBUTE_NAME (ospf, type)) |
cf795c5d | 1012 | { |
1013 | /* Keep old access-list for distribute-list. */ | |
1014 | struct access_list *old = DISTRIBUTE_LIST (ospf, type); | |
1015 | ||
1016 | /* Update access-list for distribute-list. */ | |
1017 | DISTRIBUTE_LIST (ospf, type) = | |
1018 | access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type)); | |
1019 | ||
1020 | /* No update for this distribute type. */ | |
1021 | if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL) | |
1022 | continue; | |
1023 | ||
1024 | /* Schedule distribute-list update timer. */ | |
1025 | if (DISTRIBUTE_LIST (ospf, type) == NULL || | |
1026 | strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0) | |
1027 | ospf_distribute_list_update (ospf, type); | |
1028 | } | |
718e3744 | 1029 | } |
1030 | ||
1031 | /* Update Area access-list. */ | |
68980084 | 1032 | for (node = listhead (ospf->areas); node; nextnode (node)) |
718e3744 | 1033 | if ((area = getdata (node)) != NULL) |
1034 | { | |
cf795c5d | 1035 | if (EXPORT_NAME (area)) |
1036 | { | |
1037 | EXPORT_LIST (area) = NULL; | |
1038 | abr_inv++; | |
1039 | } | |
1040 | ||
1041 | if (IMPORT_NAME (area)) | |
1042 | { | |
1043 | IMPORT_LIST (area) = NULL; | |
1044 | abr_inv++; | |
1045 | } | |
718e3744 | 1046 | } |
1047 | ||
1048 | /* Schedule ABR tasks -- this will be changed -- takada. */ | |
020709f9 | 1049 | if (IS_OSPF_ABR (ospf) && abr_inv) |
68980084 | 1050 | ospf_schedule_abr_task (ospf); |
718e3744 | 1051 | } |
dd669bb0 | 1052 | |
1053 | /* If prefix-list is updated, do some updates. */ | |
1054 | void | |
1055 | ospf_prefix_list_update (struct prefix_list *plist) | |
1056 | { | |
1057 | struct ospf *ospf; | |
1058 | int type; | |
1059 | int abr_inv = 0; | |
1060 | struct ospf_area *area; | |
52dc7ee6 | 1061 | struct listnode *node; |
dd669bb0 | 1062 | |
1063 | /* If OSPF instatnce does not exist, return right now. */ | |
1064 | ospf = ospf_lookup (); | |
1065 | if (ospf == NULL) | |
1066 | return; | |
1067 | ||
1068 | /* Update all route-maps which are used as redistribution filters. | |
1069 | * They might use prefix-list. | |
1070 | */ | |
1071 | for (type = 0; type < ZEBRA_ROUTE_MAX; type++) | |
1072 | { | |
1073 | if (ROUTEMAP (ospf, type) != NULL) | |
1074 | { | |
1075 | /* If route-map is not NULL it may be using this prefix list */ | |
1076 | ospf_distribute_list_update (ospf, type); | |
1077 | continue; | |
1078 | } | |
1079 | } | |
1080 | ||
1081 | /* Update area filter-lists. */ | |
1082 | for (node = listhead (ospf->areas); node; nextnode (node)) | |
1083 | if ((area = getdata (node)) != NULL) | |
1084 | { | |
1085 | /* Update filter-list in. */ | |
1086 | if (PREFIX_NAME_IN (area)) | |
1087 | if (strcmp (PREFIX_NAME_IN (area), plist->name) == 0) | |
1088 | { | |
1089 | PREFIX_LIST_IN (area) = | |
1090 | prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area)); | |
1091 | abr_inv++; | |
1092 | } | |
1093 | ||
1094 | /* Update filter-list out. */ | |
1095 | if (PREFIX_NAME_OUT (area)) | |
1096 | if (strcmp (PREFIX_NAME_OUT (area), plist->name) == 0) | |
1097 | { | |
1098 | PREFIX_LIST_IN (area) = | |
1099 | prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area)); | |
1100 | abr_inv++; | |
1101 | } | |
1102 | } | |
1103 | ||
1104 | /* Schedule ABR task. */ | |
1105 | if (IS_OSPF_ABR (ospf) && abr_inv) | |
1106 | ospf_schedule_abr_task (ospf); | |
1107 | } | |
cf795c5d | 1108 | |
718e3744 | 1109 | struct ospf_distance * |
1110 | ospf_distance_new () | |
1111 | { | |
1112 | struct ospf_distance *new; | |
1113 | new = XMALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance)); | |
1114 | memset (new, 0, sizeof (struct ospf_distance)); | |
1115 | return new; | |
1116 | } | |
1117 | ||
1118 | void | |
1119 | ospf_distance_free (struct ospf_distance *odistance) | |
1120 | { | |
1121 | XFREE (MTYPE_OSPF_DISTANCE, odistance); | |
1122 | } | |
1123 | ||
1124 | int | |
6c835671 | 1125 | ospf_distance_set (struct vty *vty, struct ospf *ospf, |
1126 | const char *distance_str, | |
1127 | const char *ip_str, | |
1128 | const char *access_list_str) | |
718e3744 | 1129 | { |
1130 | int ret; | |
1131 | struct prefix_ipv4 p; | |
1132 | u_char distance; | |
1133 | struct route_node *rn; | |
1134 | struct ospf_distance *odistance; | |
1135 | ||
1136 | ret = str2prefix_ipv4 (ip_str, &p); | |
1137 | if (ret == 0) | |
1138 | { | |
1139 | vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); | |
1140 | return CMD_WARNING; | |
1141 | } | |
1142 | ||
1143 | distance = atoi (distance_str); | |
1144 | ||
1145 | /* Get OSPF distance node. */ | |
68980084 | 1146 | rn = route_node_get (ospf->distance_table, (struct prefix *) &p); |
718e3744 | 1147 | if (rn->info) |
1148 | { | |
1149 | odistance = rn->info; | |
1150 | route_unlock_node (rn); | |
1151 | } | |
1152 | else | |
1153 | { | |
1154 | odistance = ospf_distance_new (); | |
1155 | rn->info = odistance; | |
1156 | } | |
1157 | ||
1158 | /* Set distance value. */ | |
1159 | odistance->distance = distance; | |
1160 | ||
1161 | /* Reset access-list configuration. */ | |
1162 | if (odistance->access_list) | |
1163 | { | |
1164 | free (odistance->access_list); | |
1165 | odistance->access_list = NULL; | |
1166 | } | |
1167 | if (access_list_str) | |
1168 | odistance->access_list = strdup (access_list_str); | |
1169 | ||
1170 | return CMD_SUCCESS; | |
1171 | } | |
1172 | ||
1173 | int | |
6c835671 | 1174 | ospf_distance_unset (struct vty *vty, struct ospf *ospf, |
1175 | const char *distance_str, | |
1176 | const char *ip_str, char | |
1177 | const *access_list_str) | |
718e3744 | 1178 | { |
1179 | int ret; | |
1180 | struct prefix_ipv4 p; | |
1181 | u_char distance; | |
1182 | struct route_node *rn; | |
1183 | struct ospf_distance *odistance; | |
1184 | ||
1185 | ret = str2prefix_ipv4 (ip_str, &p); | |
1186 | if (ret == 0) | |
1187 | { | |
1188 | vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); | |
1189 | return CMD_WARNING; | |
1190 | } | |
1191 | ||
1192 | distance = atoi (distance_str); | |
1193 | ||
cf795c5d | 1194 | rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p); |
1195 | if (!rn) | |
718e3744 | 1196 | { |
1197 | vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE); | |
1198 | return CMD_WARNING; | |
1199 | } | |
1200 | ||
1201 | odistance = rn->info; | |
1202 | ||
1203 | if (odistance->access_list) | |
1204 | free (odistance->access_list); | |
1205 | ospf_distance_free (odistance); | |
1206 | ||
1207 | rn->info = NULL; | |
1208 | route_unlock_node (rn); | |
1209 | route_unlock_node (rn); | |
1210 | ||
1211 | return CMD_SUCCESS; | |
1212 | } | |
1213 | ||
1214 | void | |
68980084 | 1215 | ospf_distance_reset (struct ospf *ospf) |
718e3744 | 1216 | { |
1217 | struct route_node *rn; | |
1218 | struct ospf_distance *odistance; | |
1219 | ||
68980084 | 1220 | for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn)) |
718e3744 | 1221 | if ((odistance = rn->info) != NULL) |
1222 | { | |
cf795c5d | 1223 | if (odistance->access_list) |
1224 | free (odistance->access_list); | |
1225 | ospf_distance_free (odistance); | |
1226 | rn->info = NULL; | |
1227 | route_unlock_node (rn); | |
718e3744 | 1228 | } |
1229 | } | |
1230 | ||
1231 | u_char | |
1232 | ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or) | |
1233 | { | |
020709f9 | 1234 | struct ospf *ospf; |
718e3744 | 1235 | |
020709f9 | 1236 | ospf = ospf_lookup (); |
68980084 | 1237 | if (ospf == NULL) |
718e3744 | 1238 | return 0; |
1239 | ||
68980084 | 1240 | if (ospf->distance_intra) |
718e3744 | 1241 | if (or->path_type == OSPF_PATH_INTRA_AREA) |
68980084 | 1242 | return ospf->distance_intra; |
718e3744 | 1243 | |
68980084 | 1244 | if (ospf->distance_inter) |
718e3744 | 1245 | if (or->path_type == OSPF_PATH_INTER_AREA) |
68980084 | 1246 | return ospf->distance_inter; |
718e3744 | 1247 | |
68980084 | 1248 | if (ospf->distance_external) |
718e3744 | 1249 | if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL |
cf795c5d | 1250 | || or->path_type == OSPF_PATH_TYPE2_EXTERNAL) |
68980084 | 1251 | return ospf->distance_external; |
cf795c5d | 1252 | |
68980084 | 1253 | if (ospf->distance_all) |
1254 | return ospf->distance_all; | |
718e3744 | 1255 | |
1256 | return 0; | |
1257 | } | |
1258 | ||
1259 | void | |
1260 | ospf_zebra_init () | |
1261 | { | |
1262 | /* Allocate zebra structure. */ | |
1263 | zclient = zclient_new (); | |
1264 | zclient_init (zclient, ZEBRA_ROUTE_OSPF); | |
18a6dce6 | 1265 | zclient->router_id_update = ospf_router_id_update_zebra; |
718e3744 | 1266 | zclient->interface_add = ospf_interface_add; |
1267 | zclient->interface_delete = ospf_interface_delete; | |
1268 | zclient->interface_up = ospf_interface_state_up; | |
1269 | zclient->interface_down = ospf_interface_state_down; | |
1270 | zclient->interface_address_add = ospf_interface_address_add; | |
1271 | zclient->interface_address_delete = ospf_interface_address_delete; | |
1272 | zclient->ipv4_route_add = ospf_zebra_read_ipv4; | |
1273 | zclient->ipv4_route_delete = ospf_zebra_read_ipv4; | |
1274 | ||
1275 | access_list_add_hook (ospf_filter_update); | |
1276 | access_list_delete_hook (ospf_filter_update); | |
dd669bb0 | 1277 | prefix_list_add_hook (ospf_prefix_list_update); |
1278 | prefix_list_delete_hook (ospf_prefix_list_update); | |
718e3744 | 1279 | } |