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