blob: 81bf59af68e228ba426b7a446f2253bf1fdcfb27 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
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. */
52struct zclient *zclient = NULL;
53
54/* For registering threads. */
55extern struct thread_master *master;
56
57/* Inteface addition message from zebra. */
58int
59ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
60{
61 struct interface *ifp;
paul020709f2003-04-04 02:44:16 +000062 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +000063
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
paulf2c80652002-12-13 21:44:27 +000070 assert(ifp->info);
71
paul718e3742002-12-13 20:15:29 +000072 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
paul020709f2003-04-04 02:44:16 +000085 ospf = ospf_lookup ();
86 if (ospf != NULL)
87 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +000088
89#ifdef HAVE_SNMP
90 ospf_snmp_if_update (ifp);
91#endif /* HAVE_SNMP */
92
93 return 0;
94}
95
96int
97ospf_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
136struct interface *
137zebra_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
155void
156zebra_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. */
paul2e3b2e42002-12-13 21:03:13 +0000162 ifp->status = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000163 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
169int
170ospf_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. */
paul2e3b2e42002-12-13 21:03:13 +0000184 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000185 {
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
221int
222ospf_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
247int
248ospf_interface_address_add (int command, struct zclient *zclient,
249 zebra_size_t length)
250{
paul020709f2003-04-04 02:44:16 +0000251 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000252 struct connected *c;
253
254 c = zebra_interface_address_add_read (zclient->ibuf);
255
256 if (c == NULL)
257 return 0;
258
paul020709f2003-04-04 02:44:16 +0000259 ospf = ospf_lookup ();
260 if (ospf != NULL)
261 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000262
263#ifdef HAVE_SNMP
264 ospf_snmp_if_update (c->ifp);
265#endif /* HAVE_SNMP */
266
267 return 0;
268}
269
270int
271ospf_interface_address_delete (int command, struct zclient *zclient,
272 zebra_size_t length)
273{
paul020709f2003-04-04 02:44:16 +0000274 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000275 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
paul020709f2003-04-04 02:44:16 +0000306 ospf = ospf_lookup ();
307 if (ospf != NULL)
308 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000309
310 return 0;
311}
paul72357f22003-06-19 02:11:23 +0000312
paul718e3742002-12-13 20:15:29 +0000313void
314ospf_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)
paul72357f22003-06-19 02:11:23 +0000336 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
paul718e3742002-12-13 20:15:29 +0000337
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))
paul72357f22003-06-19 02:11:23 +0000361 {
paul718e3742002-12-13 20:15:29 +0000362 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 }
paul72357f22003-06-19 02:11:23 +0000377
378 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
379 {
380 zlog_info ("Zebra: Route add %s/%d nexthop %s",
381 inet_ntoa (p->prefix),
382 p->prefixlen,
383 inet_ntoa (path->nexthop));
384 }
paul718e3742002-12-13 20:15:29 +0000385 }
386
387 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
388 stream_putc (s, distance);
389 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
390 {
391 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
392 stream_putl (s, or->cost + or->u.ext.type2_cost);
393 else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
394 stream_putl (s, or->u.ext.type2_cost);
395 else
396 stream_putl (s, or->cost);
397 }
398
399 stream_putw_at (s, 0, stream_get_endp (s));
400
401 writen (zclient->sock, s->data, stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +0000402 }
403}
404
405void
406ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
407{
408 struct zapi_ipv4 api;
paul72357f22003-06-19 02:11:23 +0000409 struct ospf_path *path;
410 struct in_addr *nexthop;
411 listnode node;
paul718e3742002-12-13 20:15:29 +0000412
413 if (zclient->redist[ZEBRA_ROUTE_OSPF])
414 {
415 api.type = ZEBRA_ROUTE_OSPF;
416 api.flags = 0;
417 api.message = 0;
paul72357f22003-06-19 02:11:23 +0000418 api.ifindex_num = 0;
419 api.nexthop_num = 0;
420 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
paul718e3742002-12-13 20:15:29 +0000421
paul72357f22003-06-19 02:11:23 +0000422 for (node = listhead (or->path); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000423 {
paul72357f22003-06-19 02:11:23 +0000424 path = getdata (node);
paul718e3742002-12-13 20:15:29 +0000425
paul72357f22003-06-19 02:11:23 +0000426 if (path->nexthop.s_addr != INADDR_ANY)
427 {
428 api.nexthop_num = 1;
429 nexthop = &path->nexthop;
430 api.nexthop = &nexthop;
431 }
432 else
433 {
434 api.ifindex_num = 1;
435 api.ifindex = &path->oi->ifp->ifindex;
436 }
437
438 zapi_ipv4_delete (zclient, p, &api);
439
440 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.nexthop_num)
441 {
442 zlog_info ("Zebra: Route delete %s/%d nexthop %s",
443 inet_ntoa (p->prefix),
444 p->prefixlen,
445 inet_ntoa (**api.nexthop));
446 }
paul718e3742002-12-13 20:15:29 +0000447 }
paul718e3742002-12-13 20:15:29 +0000448 }
449}
450
451void
452ospf_zebra_add_discard (struct prefix_ipv4 *p)
453{
454 struct zapi_ipv4 api;
455
456 if (zclient->redist[ZEBRA_ROUTE_OSPF])
457 {
458 api.type = ZEBRA_ROUTE_OSPF;
459 api.flags = ZEBRA_FLAG_BLACKHOLE;
460 api.message = 0;
461 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
462 api.nexthop_num = 0;
463 api.ifindex_num = 0;
464
465 zapi_ipv4_add (zclient, p, &api);
466 }
467}
468
469void
470ospf_zebra_delete_discard (struct prefix_ipv4 *p)
471{
472 struct zapi_ipv4 api;
473
474 if (zclient->redist[ZEBRA_ROUTE_OSPF])
475 {
476 api.type = ZEBRA_ROUTE_OSPF;
477 api.flags = ZEBRA_FLAG_BLACKHOLE;
478 api.message = 0;
479 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
480 api.nexthop_num = 0;
481 api.ifindex_num = 0;
482
483 zapi_ipv4_delete (zclient, p, &api);
paul72357f22003-06-19 02:11:23 +0000484
485 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
486 zlog_info ("Zebra: Route delete discard %s/%d",
487 inet_ntoa (p->prefix), p->prefixlen);
488
paul718e3742002-12-13 20:15:29 +0000489 }
490}
491
492int
493ospf_is_type_redistributed (int type)
494{
495 return (DEFAULT_ROUTE_TYPE (type)) ?
496 zclient->default_information : zclient->redist[type];
497}
498
499int
paul020709f2003-04-04 02:44:16 +0000500ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue)
paul718e3742002-12-13 20:15:29 +0000501{
502 int force = 0;
503
504 if (ospf_is_type_redistributed (type))
505 {
paul68980082003-03-25 05:07:42 +0000506 if (mtype != ospf->dmetric[type].type)
paul718e3742002-12-13 20:15:29 +0000507 {
paul68980082003-03-25 05:07:42 +0000508 ospf->dmetric[type].type = mtype;
paul718e3742002-12-13 20:15:29 +0000509 force = LSA_REFRESH_FORCE;
510 }
paul68980082003-03-25 05:07:42 +0000511 if (mvalue != ospf->dmetric[type].value)
paul718e3742002-12-13 20:15:29 +0000512 {
paul68980082003-03-25 05:07:42 +0000513 ospf->dmetric[type].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000514 force = LSA_REFRESH_FORCE;
515 }
516
paul68980082003-03-25 05:07:42 +0000517 ospf_external_lsa_refresh_type (ospf, type, force);
paul718e3742002-12-13 20:15:29 +0000518
519 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
520 zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
521 LOOKUP (ospf_redistributed_proto, type),
paul68980082003-03-25 05:07:42 +0000522 metric_type (ospf, type), metric_value (ospf, type));
paul718e3742002-12-13 20:15:29 +0000523
524 return CMD_SUCCESS;
525 }
526
paul68980082003-03-25 05:07:42 +0000527 ospf->dmetric[type].type = mtype;
528 ospf->dmetric[type].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000529
530 zclient_redistribute_set (zclient, type);
531
532 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
533 zlog_info ("Redistribute[%s]: Start Type[%d], Metric[%d]",
534 LOOKUP (ospf_redistributed_proto, type),
paul68980082003-03-25 05:07:42 +0000535 metric_type (ospf, type), metric_value (ospf, type));
paul718e3742002-12-13 20:15:29 +0000536
paul68980082003-03-25 05:07:42 +0000537 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000538
539 return CMD_SUCCESS;
540}
541
542int
paul020709f2003-04-04 02:44:16 +0000543ospf_redistribute_unset (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000544{
545 if (type == zclient->redist_default)
546 return CMD_SUCCESS;
547
548 if (! ospf_is_type_redistributed (type))
549 return CMD_SUCCESS;
550
551 zclient_redistribute_unset (zclient, type);
552
553 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
554 zlog_info ("Redistribute[%s]: Stop",
555 LOOKUP (ospf_redistributed_proto, type));
556
paul68980082003-03-25 05:07:42 +0000557 ospf->dmetric[type].type = -1;
558 ospf->dmetric[type].value = -1;
paul718e3742002-12-13 20:15:29 +0000559
560 /* Remove the routes from OSPF table. */
561 ospf_redistribute_withdraw (type);
562
paul68980082003-03-25 05:07:42 +0000563 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000564
565 return CMD_SUCCESS;
566}
567
568int
paul020709f2003-04-04 02:44:16 +0000569ospf_redistribute_default_set (struct ospf *ospf, int originate,
570 int mtype, int mvalue)
paul718e3742002-12-13 20:15:29 +0000571{
572 int force = 0;
paul020709f2003-04-04 02:44:16 +0000573
paul718e3742002-12-13 20:15:29 +0000574 if (ospf_is_type_redistributed (DEFAULT_ROUTE))
575 {
paul68980082003-03-25 05:07:42 +0000576 if (mtype != ospf->dmetric[DEFAULT_ROUTE].type)
paul718e3742002-12-13 20:15:29 +0000577 {
paul68980082003-03-25 05:07:42 +0000578 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
paul718e3742002-12-13 20:15:29 +0000579 force = 1;
580 }
paul68980082003-03-25 05:07:42 +0000581 if (mvalue != ospf->dmetric[DEFAULT_ROUTE].value)
paul718e3742002-12-13 20:15:29 +0000582 {
583 force = 1;
paul68980082003-03-25 05:07:42 +0000584 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000585 }
586
paul68980082003-03-25 05:07:42 +0000587 ospf_external_lsa_refresh_default (ospf);
paul718e3742002-12-13 20:15:29 +0000588
589 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
590 zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
591 LOOKUP (ospf_redistributed_proto, DEFAULT_ROUTE),
paul68980082003-03-25 05:07:42 +0000592 metric_type (ospf, DEFAULT_ROUTE),
593 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000594 return CMD_SUCCESS;
595 }
596
paul68980082003-03-25 05:07:42 +0000597 ospf->default_originate = originate;
598 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
599 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000600
601 zclient_redistribute_default_set (zclient);
602
603 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
604 zlog_info ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
paul68980082003-03-25 05:07:42 +0000605 metric_type (ospf, DEFAULT_ROUTE),
606 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000607
paul68980082003-03-25 05:07:42 +0000608 if (ospf->router_id.s_addr == 0)
609 ospf->external_origin |= (1 << DEFAULT_ROUTE);
paul718e3742002-12-13 20:15:29 +0000610 else
611 thread_add_timer (master, ospf_default_originate_timer,
paul68980082003-03-25 05:07:42 +0000612 &ospf->default_originate, 1);
paul718e3742002-12-13 20:15:29 +0000613
paul68980082003-03-25 05:07:42 +0000614 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000615
616 return CMD_SUCCESS;
617}
618
619int
paul020709f2003-04-04 02:44:16 +0000620ospf_redistribute_default_unset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000621{
622 if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
623 return CMD_SUCCESS;
624
paul68980082003-03-25 05:07:42 +0000625 ospf->default_originate = DEFAULT_ORIGINATE_NONE;
626 ospf->dmetric[DEFAULT_ROUTE].type = -1;
627 ospf->dmetric[DEFAULT_ROUTE].value = -1;
paul718e3742002-12-13 20:15:29 +0000628
629 zclient_redistribute_default_unset (zclient);
630
631 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
632 zlog_info ("Redistribute[DEFAULT]: Stop");
633
paul68980082003-03-25 05:07:42 +0000634 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000635
636 return CMD_SUCCESS;
637}
638
639int
paul020709f2003-04-04 02:44:16 +0000640ospf_external_lsa_originate_check (struct ospf *ospf,
641 struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000642{
643 /* If prefix is multicast, then do not originate LSA. */
644 if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
645 {
646 zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
647 "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
648 return 0;
649 }
650
651 /* Take care of default-originate. */
652 if (is_prefix_default (&ei->p))
paul68980082003-03-25 05:07:42 +0000653 if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
paul718e3742002-12-13 20:15:29 +0000654 {
655 zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-exntenal-LSA "
656 "for default");
657 return 0;
658 }
659
660 return 1;
661}
662
663/* If connected prefix is OSPF enable interface, then do not announce. */
664int
paul68980082003-03-25 05:07:42 +0000665ospf_distribute_check_connected (struct ospf *ospf,
666 struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000667{
668 struct route_node *rn;
669
paul68980082003-03-25 05:07:42 +0000670 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000671 if (rn->info != NULL)
672 if (prefix_match (&rn->p, (struct prefix *)&ei->p))
paul68980082003-03-25 05:07:42 +0000673 {
674 route_unlock_node (rn);
675 return 0;
676 }
paul718e3742002-12-13 20:15:29 +0000677
678 return 1;
679}
680
681/* return 1 if external LSA must be originated, 0 otherwise */
682int
paul68980082003-03-25 05:07:42 +0000683ospf_redistribute_check (struct ospf *ospf,
684 struct external_info *ei, int *changed)
paul718e3742002-12-13 20:15:29 +0000685{
686 struct route_map_set_values save_values;
687 struct prefix_ipv4 *p = &ei->p;
688 u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
689
690 if (changed)
691 *changed = 0;
692
paul020709f2003-04-04 02:44:16 +0000693 if (!ospf_external_lsa_originate_check (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000694 return 0;
695
696 /* Take care connected route. */
paul68980082003-03-25 05:07:42 +0000697 if (type == ZEBRA_ROUTE_CONNECT &&
698 !ospf_distribute_check_connected (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000699 return 0;
700
paul020709f2003-04-04 02:44:16 +0000701 if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000702 /* distirbute-list exists, but access-list may not? */
paul020709f2003-04-04 02:44:16 +0000703 if (DISTRIBUTE_LIST (ospf, type))
704 if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
paul718e3742002-12-13 20:15:29 +0000705 {
706 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
707 zlog_info ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
708 LOOKUP (ospf_redistributed_proto, type),
709 inet_ntoa (p->prefix), p->prefixlen);
710 return 0;
711 }
712
713 save_values = ei->route_map_set;
714 ospf_reset_route_map_set_values (&ei->route_map_set);
715
716 /* apply route-map if needed */
paul020709f2003-04-04 02:44:16 +0000717 if (ROUTEMAP_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000718 {
719 int ret;
720
paul020709f2003-04-04 02:44:16 +0000721 ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *)p,
paul718e3742002-12-13 20:15:29 +0000722 RMAP_OSPF, ei);
723
724 if (ret == RMAP_DENYMATCH)
725 {
726 ei->route_map_set = save_values;
727 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
728 zlog_info ("Redistribute[%s]: %s/%d filtered by route-map.",
729 LOOKUP (ospf_redistributed_proto, type),
730 inet_ntoa (p->prefix), p->prefixlen);
731 return 0;
732 }
733
734 /* check if 'route-map set' changed something */
735 if (changed)
736 *changed = !ospf_route_map_set_compare (&ei->route_map_set,
737 &save_values);
738 }
739
740 return 1;
741}
742
743/* OSPF route-map set for redistribution */
744void
paul020709f2003-04-04 02:44:16 +0000745ospf_routemap_set (struct ospf *ospf, int type, char *name)
paul718e3742002-12-13 20:15:29 +0000746{
paul020709f2003-04-04 02:44:16 +0000747 if (ROUTEMAP_NAME (ospf, type))
748 free (ROUTEMAP_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000749
paul020709f2003-04-04 02:44:16 +0000750 ROUTEMAP_NAME (ospf, type) = strdup (name);
751 ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);
paul718e3742002-12-13 20:15:29 +0000752}
753
754void
paul020709f2003-04-04 02:44:16 +0000755ospf_routemap_unset (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000756{
paul020709f2003-04-04 02:44:16 +0000757 if (ROUTEMAP_NAME (ospf, type))
758 free (ROUTEMAP_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000759
paul020709f2003-04-04 02:44:16 +0000760 ROUTEMAP_NAME (ospf, type) = NULL;
761 ROUTEMAP (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000762}
763
764/* Zebra route add and delete treatment. */
765int
766ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
767 zebra_size_t length)
768{
769 struct stream *s;
770 struct zapi_ipv4 api;
771 unsigned long ifindex;
772 struct in_addr nexthop;
773 struct prefix_ipv4 p;
774 struct external_info *ei;
paul020709f2003-04-04 02:44:16 +0000775 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000776
777 s = zclient->ibuf;
778 ifindex = 0;
779 nexthop.s_addr = 0;
780
781 /* Type, flags, message. */
782 api.type = stream_getc (s);
783 api.flags = stream_getc (s);
784 api.message = stream_getc (s);
785
786 /* IPv4 prefix. */
787 memset (&p, 0, sizeof (struct prefix_ipv4));
788 p.family = AF_INET;
789 p.prefixlen = stream_getc (s);
790 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
791
792 /* Nexthop, ifindex, distance, metric. */
793 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
794 {
795 api.nexthop_num = stream_getc (s);
796 nexthop.s_addr = stream_get_ipv4 (s);
797 }
798 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
799 {
800 api.ifindex_num = stream_getc (s);
801 ifindex = stream_getl (s);
802 }
803 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
804 api.distance = stream_getc (s);
805 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
806 api.metric = stream_getl (s);
807
paul020709f2003-04-04 02:44:16 +0000808 ospf = ospf_lookup ();
809 if (ospf == NULL)
810 return 0;
811
paul718e3742002-12-13 20:15:29 +0000812 if (command == ZEBRA_IPV4_ROUTE_ADD)
813 {
814 ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
815
paul68980082003-03-25 05:07:42 +0000816 if (ospf->router_id.s_addr == 0)
paul718e3742002-12-13 20:15:29 +0000817 /* Set flags to generate AS-external-LSA originate event
818 for each redistributed protocols later. */
paul68980082003-03-25 05:07:42 +0000819 ospf->external_origin |= (1 << api.type);
paul718e3742002-12-13 20:15:29 +0000820 else
821 {
822 if (ei)
823 {
824 if (is_prefix_default (&p))
paul68980082003-03-25 05:07:42 +0000825 ospf_external_lsa_refresh_default (ospf);
paul718e3742002-12-13 20:15:29 +0000826 else
827 {
828 struct ospf_lsa *current;
829
paul68980082003-03-25 05:07:42 +0000830 current = ospf_external_info_find_lsa (ospf, &ei->p);
paul718e3742002-12-13 20:15:29 +0000831 if (!current)
paul68980082003-03-25 05:07:42 +0000832 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000833 else if (IS_LSA_MAXAGE (current))
paul68980082003-03-25 05:07:42 +0000834 ospf_external_lsa_refresh (ospf, current,
835 ei, LSA_REFRESH_FORCE);
paul718e3742002-12-13 20:15:29 +0000836 else
837 zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
838 inet_ntoa (p.prefix));
839 }
840 }
841 }
842 }
843 else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
844 {
845 ospf_external_info_delete (api.type, p);
846 if ( !is_prefix_default (&p))
paul68980082003-03-25 05:07:42 +0000847 ospf_external_lsa_flush (ospf, api.type, &p, ifindex, nexthop);
paul718e3742002-12-13 20:15:29 +0000848 else
paul68980082003-03-25 05:07:42 +0000849 ospf_external_lsa_refresh_default (ospf);
paul718e3742002-12-13 20:15:29 +0000850 }
851
852 return 0;
853}
854
855
856int
paul68980082003-03-25 05:07:42 +0000857ospf_distribute_list_out_set (struct ospf *ospf, int type, char *name)
paul718e3742002-12-13 20:15:29 +0000858{
859 /* Lookup access-list for distribute-list. */
paul020709f2003-04-04 02:44:16 +0000860 DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
paul718e3742002-12-13 20:15:29 +0000861
862 /* Clear previous distribute-name. */
paul020709f2003-04-04 02:44:16 +0000863 if (DISTRIBUTE_NAME (ospf, type))
864 free (DISTRIBUTE_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000865
866 /* Set distribute-name. */
paul020709f2003-04-04 02:44:16 +0000867 DISTRIBUTE_NAME (ospf, type) = strdup (name);
paul718e3742002-12-13 20:15:29 +0000868
869 /* If access-list have been set, schedule update timer. */
paul020709f2003-04-04 02:44:16 +0000870 if (DISTRIBUTE_LIST (ospf, type))
paul68980082003-03-25 05:07:42 +0000871 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000872
873 return CMD_SUCCESS;
874}
875
876int
paul68980082003-03-25 05:07:42 +0000877ospf_distribute_list_out_unset (struct ospf *ospf, int type, char *name)
paul718e3742002-12-13 20:15:29 +0000878{
879 /* Schedule update timer. */
paul020709f2003-04-04 02:44:16 +0000880 if (DISTRIBUTE_LIST (ospf, type))
paul68980082003-03-25 05:07:42 +0000881 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000882
883 /* Unset distribute-list. */
paul020709f2003-04-04 02:44:16 +0000884 DISTRIBUTE_LIST (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000885
886 /* Clear distribute-name. */
paul020709f2003-04-04 02:44:16 +0000887 if (DISTRIBUTE_NAME (ospf, type))
888 free (DISTRIBUTE_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000889
paul020709f2003-04-04 02:44:16 +0000890 DISTRIBUTE_NAME (ospf, type) = NULL;
paul718e3742002-12-13 20:15:29 +0000891
892 return CMD_SUCCESS;
893}
894
895/* distribute-list update timer. */
896int
897ospf_distribute_list_update_timer (struct thread *thread)
898{
899 struct route_node *rn;
900 struct external_info *ei;
901 struct route_table *rt;
902 struct ospf_lsa *lsa;
903 u_char type;
paul020709f2003-04-04 02:44:16 +0000904 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000905
906 type = (int) THREAD_ARG (thread);
907 rt = EXTERNAL_INFO (type);
908
paul020709f2003-04-04 02:44:16 +0000909 ospf = ospf_lookup ();
910 if (ospf == NULL)
911 return 0;
912
paul68980082003-03-25 05:07:42 +0000913 ospf->t_distribute_update = NULL;
paul718e3742002-12-13 20:15:29 +0000914
915 zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
916
917 /* foreach all external info. */
918 if (rt)
919 for (rn = route_top (rt); rn; rn = route_next (rn))
920 if ((ei = rn->info) != NULL)
921 {
922 if (is_prefix_default (&ei->p))
paul68980082003-03-25 05:07:42 +0000923 ospf_external_lsa_refresh_default (ospf);
924 else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
925 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
paul718e3742002-12-13 20:15:29 +0000926 else
paul68980082003-03-25 05:07:42 +0000927 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000928 }
929 return 0;
930}
931
932#define OSPF_DISTRIBUTE_UPDATE_DELAY 5
933
934/* Update distribute-list and set timer to apply access-list. */
935void
paul68980082003-03-25 05:07:42 +0000936ospf_distribute_list_update (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000937{
938 struct route_table *rt;
939
paul718e3742002-12-13 20:15:29 +0000940 /* External info does not exist. */
941 if (!(rt = EXTERNAL_INFO (type)))
942 return;
943
944 /* If exists previously invoked thread, then cancel it. */
paul68980082003-03-25 05:07:42 +0000945 if (ospf->t_distribute_update)
946 OSPF_TIMER_OFF (ospf->t_distribute_update);
paul718e3742002-12-13 20:15:29 +0000947
948 /* Set timer. */
paul68980082003-03-25 05:07:42 +0000949 ospf->t_distribute_update =
paul718e3742002-12-13 20:15:29 +0000950 thread_add_timer (master, ospf_distribute_list_update_timer,
951 (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000952}
953
954/* If access-list is updated, apply some check. */
955void
956ospf_filter_update (struct access_list *access)
957{
paul020709f2003-04-04 02:44:16 +0000958 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000959 int type;
960 int abr_inv = 0;
961 struct ospf_area *area;
962 listnode node;
963
964 /* If OSPF instatnce does not exist, return right now. */
paul020709f2003-04-04 02:44:16 +0000965 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000966 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000967 return;
968
paul718e3742002-12-13 20:15:29 +0000969 /* Update distribute-list, and apply filter. */
970 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
971 {
paul020709f2003-04-04 02:44:16 +0000972 if (ROUTEMAP (ospf, type) != NULL)
paul718e3742002-12-13 20:15:29 +0000973 {
974 /* if route-map is not NULL it may be using this access list */
paul68980082003-03-25 05:07:42 +0000975 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000976 continue;
977 }
978
979
paul020709f2003-04-04 02:44:16 +0000980 if (DISTRIBUTE_NAME (ospf, type))
paul718e3742002-12-13 20:15:29 +0000981 {
982 /* Keep old access-list for distribute-list. */
paul020709f2003-04-04 02:44:16 +0000983 struct access_list *old = DISTRIBUTE_LIST (ospf, type);
paul718e3742002-12-13 20:15:29 +0000984
985 /* Update access-list for distribute-list. */
paul020709f2003-04-04 02:44:16 +0000986 DISTRIBUTE_LIST (ospf, type) =
987 access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type));
paul718e3742002-12-13 20:15:29 +0000988
989 /* No update for this distribute type. */
paul020709f2003-04-04 02:44:16 +0000990 if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL)
paul718e3742002-12-13 20:15:29 +0000991 continue;
992
993 /* Schedule distribute-list update timer. */
paul020709f2003-04-04 02:44:16 +0000994 if (DISTRIBUTE_LIST (ospf, type) == NULL ||
995 strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
paul68980082003-03-25 05:07:42 +0000996 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000997 }
998 }
999
1000 /* Update Area access-list. */
paul68980082003-03-25 05:07:42 +00001001 for (node = listhead (ospf->areas); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00001002 if ((area = getdata (node)) != NULL)
1003 {
1004 if (EXPORT_NAME (area))
1005 {
1006 EXPORT_LIST (area) = NULL;
1007 abr_inv++;
1008 }
1009
1010 if (IMPORT_NAME (area))
1011 {
1012 IMPORT_LIST (area) = NULL;
1013 abr_inv++;
1014 }
1015 }
1016
1017 /* Schedule ABR tasks -- this will be changed -- takada. */
paul020709f2003-04-04 02:44:16 +00001018 if (IS_OSPF_ABR (ospf) && abr_inv)
paul68980082003-03-25 05:07:42 +00001019 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001020}
1021
1022
1023struct ospf_distance *
1024ospf_distance_new ()
1025{
1026 struct ospf_distance *new;
1027 new = XMALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
1028 memset (new, 0, sizeof (struct ospf_distance));
1029 return new;
1030}
1031
1032void
1033ospf_distance_free (struct ospf_distance *odistance)
1034{
1035 XFREE (MTYPE_OSPF_DISTANCE, odistance);
1036}
1037
1038int
paul020709f2003-04-04 02:44:16 +00001039ospf_distance_set (struct vty *vty, struct ospf *ospf, char *distance_str,
1040 char *ip_str, char *access_list_str)
paul718e3742002-12-13 20:15:29 +00001041{
1042 int ret;
1043 struct prefix_ipv4 p;
1044 u_char distance;
1045 struct route_node *rn;
1046 struct ospf_distance *odistance;
1047
1048 ret = str2prefix_ipv4 (ip_str, &p);
1049 if (ret == 0)
1050 {
1051 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1052 return CMD_WARNING;
1053 }
1054
1055 distance = atoi (distance_str);
1056
1057 /* Get OSPF distance node. */
paul68980082003-03-25 05:07:42 +00001058 rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +00001059 if (rn->info)
1060 {
1061 odistance = rn->info;
1062 route_unlock_node (rn);
1063 }
1064 else
1065 {
1066 odistance = ospf_distance_new ();
1067 rn->info = odistance;
1068 }
1069
1070 /* Set distance value. */
1071 odistance->distance = distance;
1072
1073 /* Reset access-list configuration. */
1074 if (odistance->access_list)
1075 {
1076 free (odistance->access_list);
1077 odistance->access_list = NULL;
1078 }
1079 if (access_list_str)
1080 odistance->access_list = strdup (access_list_str);
1081
1082 return CMD_SUCCESS;
1083}
1084
1085int
paul020709f2003-04-04 02:44:16 +00001086ospf_distance_unset (struct vty *vty, struct ospf *ospf, char *distance_str,
1087 char *ip_str, char *access_list_str)
paul718e3742002-12-13 20:15:29 +00001088{
1089 int ret;
1090 struct prefix_ipv4 p;
1091 u_char distance;
1092 struct route_node *rn;
1093 struct ospf_distance *odistance;
1094
1095 ret = str2prefix_ipv4 (ip_str, &p);
1096 if (ret == 0)
1097 {
1098 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1099 return CMD_WARNING;
1100 }
1101
1102 distance = atoi (distance_str);
1103
paul68980082003-03-25 05:07:42 +00001104 rn = route_node_lookup (ospf->distance_table, (struct prefix *)&p);
paul718e3742002-12-13 20:15:29 +00001105 if (! rn)
1106 {
1107 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
1108 return CMD_WARNING;
1109 }
1110
1111 odistance = rn->info;
1112
1113 if (odistance->access_list)
1114 free (odistance->access_list);
1115 ospf_distance_free (odistance);
1116
1117 rn->info = NULL;
1118 route_unlock_node (rn);
1119 route_unlock_node (rn);
1120
1121 return CMD_SUCCESS;
1122}
1123
1124void
paul68980082003-03-25 05:07:42 +00001125ospf_distance_reset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001126{
1127 struct route_node *rn;
1128 struct ospf_distance *odistance;
1129
paul68980082003-03-25 05:07:42 +00001130 for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001131 if ((odistance = rn->info) != NULL)
1132 {
1133 if (odistance->access_list)
1134 free (odistance->access_list);
1135 ospf_distance_free (odistance);
1136 rn->info = NULL;
1137 route_unlock_node (rn);
1138 }
1139}
1140
1141u_char
1142ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
1143{
paul020709f2003-04-04 02:44:16 +00001144 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001145
paul020709f2003-04-04 02:44:16 +00001146 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001147 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001148 return 0;
1149
paul68980082003-03-25 05:07:42 +00001150 if (ospf->distance_intra)
paul718e3742002-12-13 20:15:29 +00001151 if (or->path_type == OSPF_PATH_INTRA_AREA)
paul68980082003-03-25 05:07:42 +00001152 return ospf->distance_intra;
paul718e3742002-12-13 20:15:29 +00001153
paul68980082003-03-25 05:07:42 +00001154 if (ospf->distance_inter)
paul718e3742002-12-13 20:15:29 +00001155 if (or->path_type == OSPF_PATH_INTER_AREA)
paul68980082003-03-25 05:07:42 +00001156 return ospf->distance_inter;
paul718e3742002-12-13 20:15:29 +00001157
paul68980082003-03-25 05:07:42 +00001158 if (ospf->distance_external)
paul718e3742002-12-13 20:15:29 +00001159 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
1160 || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
paul68980082003-03-25 05:07:42 +00001161 return ospf->distance_external;
paul718e3742002-12-13 20:15:29 +00001162
paul68980082003-03-25 05:07:42 +00001163 if (ospf->distance_all)
1164 return ospf->distance_all;
paul718e3742002-12-13 20:15:29 +00001165
1166 return 0;
1167}
1168
1169void
1170ospf_zebra_init ()
1171{
1172 /* Allocate zebra structure. */
1173 zclient = zclient_new ();
1174 zclient_init (zclient, ZEBRA_ROUTE_OSPF);
1175 zclient->interface_add = ospf_interface_add;
1176 zclient->interface_delete = ospf_interface_delete;
1177 zclient->interface_up = ospf_interface_state_up;
1178 zclient->interface_down = ospf_interface_state_down;
1179 zclient->interface_address_add = ospf_interface_address_add;
1180 zclient->interface_address_delete = ospf_interface_address_delete;
1181 zclient->ipv4_route_add = ospf_zebra_read_ipv4;
1182 zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
1183
1184 access_list_add_hook (ospf_filter_update);
1185 access_list_delete_hook (ospf_filter_update);
1186}