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