blob: baba11d731dbee9a856c8502a6af8fc4cc831fdf [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;
paul68980082003-03-25 05:07:42 +000062 struct ospf *ospf = ospf_top;
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
paul68980082003-03-25 05:07:42 +000085 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +000086
87#ifdef HAVE_SNMP
88 ospf_snmp_if_update (ifp);
89#endif /* HAVE_SNMP */
90
91 return 0;
92}
93
94int
95ospf_interface_delete (int command, struct zclient *zclient,
96 zebra_size_t length)
97{
98 struct interface *ifp;
99 struct stream *s;
100 struct route_node *rn;
101
102 s = zclient->ibuf;
103 /* zebra_interface_state_read() updates interface structure in iflist */
104 ifp = zebra_interface_state_read (s);
105
106 if (ifp == NULL)
107 return 0;
108
109 if (if_is_up (ifp))
110 zlog_warn ("Zebra: got delete of %s, but interface is still up",
111 ifp->name);
112
113 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
114 zlog_info ("Zebra: interface delete %s index %d flags %ld metric %d mtu %d",
115 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
116
117#ifdef HAVE_SNMP
118 ospf_snmp_if_delete (ifp);
119#endif /* HAVE_SNMP */
120
121 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
122 if (rn->info)
123 ospf_if_free ((struct ospf_interface *) rn->info);
124
125 for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn))
126 if (rn->info)
127 ospf_del_if_params (rn->info);
128
129 if_delete (ifp);
130
131 return 0;
132}
133
134struct interface *
135zebra_interface_if_lookup (struct stream *s)
136{
137 struct interface *ifp;
138 u_char ifname_tmp[INTERFACE_NAMSIZ];
139
140 /* Read interface name. */
141 stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
142
143 /* Lookup this by interface index. */
144 ifp = if_lookup_by_name (ifname_tmp);
145
146 /* If such interface does not exist, indicate an error */
147 if (!ifp)
148 return NULL;
149
150 return ifp;
151}
152
153void
154zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
155{
156 /* Read interface's index. */
157 ifp->ifindex = stream_getl (s);
158
159 /* Read interface's value. */
paul2e3b2e42002-12-13 21:03:13 +0000160 ifp->status = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000161 ifp->flags = stream_getl (s);
162 ifp->metric = stream_getl (s);
163 ifp->mtu = stream_getl (s);
164 ifp->bandwidth = stream_getl (s);
165}
166
167int
168ospf_interface_state_up (int command, struct zclient *zclient,
169 zebra_size_t length)
170{
171 struct interface *ifp;
172 struct interface if_tmp;
173 struct ospf_interface *oi;
174 struct route_node *rn;
175
176 ifp = zebra_interface_if_lookup (zclient->ibuf);
177
178 if (ifp == NULL)
179 return 0;
180
181 /* Interface is already up. */
paul2e3b2e42002-12-13 21:03:13 +0000182 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000183 {
184 /* Temporarily keep ifp values. */
185 memcpy (&if_tmp, ifp, sizeof (struct interface));
186
187 zebra_interface_if_set_value (zclient->ibuf, ifp);
188
189 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
190 zlog_info ("Zebra: Interface[%s] state update.", ifp->name);
191
192 if (if_tmp.bandwidth != ifp->bandwidth)
193 {
194 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
195 zlog_info ("Zebra: Interface[%s] bandwidth change %d -> %d.",
196 ifp->name, if_tmp.bandwidth, ifp->bandwidth);
197
198 ospf_if_recalculate_output_cost (ifp);
199 }
200 return 0;
201 }
202
203 zebra_interface_if_set_value (zclient->ibuf, ifp);
204
205 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
206 zlog_info ("Zebra: Interface[%s] state change to up.", ifp->name);
207
208 for (rn = route_top (IF_OIFS (ifp));rn; rn = route_next (rn))
209 {
210 if ( (oi = rn->info) == NULL)
211 continue;
212
213 ospf_if_up (oi);
214 }
215
216 return 0;
217}
218
219int
220ospf_interface_state_down (int command, struct zclient *zclient,
221 zebra_size_t length)
222{
223 struct interface *ifp;
224 struct ospf_interface *oi;
225 struct route_node *node;
226
227 ifp = zebra_interface_state_read (zclient->ibuf);
228
229 if (ifp == NULL)
230 return 0;
231
232 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
233 zlog_info ("Zebra: Interface[%s] state change to down.", ifp->name);
234
235 for (node = route_top (IF_OIFS (ifp));node; node = route_next (node))
236 {
237 if ( (oi = node->info) == NULL)
238 continue;
239 ospf_if_down (oi);
240 }
241
242 return 0;
243}
244
245int
246ospf_interface_address_add (int command, struct zclient *zclient,
247 zebra_size_t length)
248{
paul68980082003-03-25 05:07:42 +0000249 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +0000250 struct connected *c;
251
252 c = zebra_interface_address_add_read (zclient->ibuf);
253
254 if (c == NULL)
255 return 0;
256
paul68980082003-03-25 05:07:42 +0000257 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000258
259#ifdef HAVE_SNMP
260 ospf_snmp_if_update (c->ifp);
261#endif /* HAVE_SNMP */
262
263 return 0;
264}
265
266int
267ospf_interface_address_delete (int command, struct zclient *zclient,
268 zebra_size_t length)
269{
paul68980082003-03-25 05:07:42 +0000270 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +0000271 struct connected *c;
272 struct interface *ifp;
273 struct ospf_interface *oi;
274 struct route_node *rn;
275 struct prefix p;
276
277 c = zebra_interface_address_delete_read (zclient->ibuf);
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);
287 if (! rn)
288 return 0;
289
290 assert (rn->info);
291 oi = rn->info;
292
293 /* Call interface hook functions to clean up */
294 ospf_if_free (oi);
295
296#ifdef HAVE_SNMP
297 ospf_snmp_if_update (c->ifp);
298#endif /* HAVE_SNMP */
299
300 connected_free (c);
301
paul68980082003-03-25 05:07:42 +0000302 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000303
304 return 0;
305}
306
307void
308ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
309{
310 u_char message;
311 u_char distance;
312 u_char flags;
313 int psize;
314 struct stream *s;
315 struct ospf_path *path;
316 listnode node;
317
318 if (zclient->redist[ZEBRA_ROUTE_OSPF])
319 {
320 message = 0;
321 flags = 0;
322
323 /* OSPF pass nexthop and metric */
324 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
325 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
326
327 /* Distance value. */
328 distance = ospf_distance_apply (p, or);
329 if (distance)
330 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
331
332 /* Make packet. */
333 s = zclient->obuf;
334 stream_reset (s);
335
336 /* Length place holder. */
337 stream_putw (s, 0);
338
339 /* Put command, type, flags, message. */
340 stream_putc (s, ZEBRA_IPV4_ROUTE_ADD);
341 stream_putc (s, ZEBRA_ROUTE_OSPF);
342 stream_putc (s, flags);
343 stream_putc (s, message);
344
345 /* Put prefix information. */
346 psize = PSIZE (p->prefixlen);
347 stream_putc (s, p->prefixlen);
348 stream_write (s, (u_char *)&p->prefix, psize);
349
350 /* Nexthop count. */
351 stream_putc (s, or->path->count);
352
353 /* Nexthop, ifindex, distance and metric information. */
354 for (node = listhead (or->path); node; nextnode (node))
355 {
356 path = getdata (node);
357
358 if (path->nexthop.s_addr != INADDR_ANY)
359 {
360 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
361 stream_put_in_addr (s, &path->nexthop);
362 }
363 else
364 {
365 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
366 if (path->oi)
367 stream_putl (s, path->oi->ifp->ifindex);
368 else
369 stream_putl (s, 0);
370 }
371 }
372
373 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
374 stream_putc (s, distance);
375 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
376 {
377 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
378 stream_putl (s, or->cost + or->u.ext.type2_cost);
379 else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
380 stream_putl (s, or->u.ext.type2_cost);
381 else
382 stream_putl (s, or->cost);
383 }
384
385 stream_putw_at (s, 0, stream_get_endp (s));
386
387 writen (zclient->sock, s->data, stream_get_endp (s));
388
389#if 0
390 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
391 {
392 char *nexthop_str;
393
394 nexthop_str = strdup (inet_ntoa (*nexthop));
395 zlog_info ("Zebra: Route add %s/%d nexthop %s metric %d",
396 inet_ntoa (p->prefix), p->prefixlen, nexthop_str,
397 metric);
398 free (nexthop_str);
399 }
400#endif /* 0 */
401 }
402}
403
404void
405ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
406{
407 struct zapi_ipv4 api;
408
409 if (zclient->redist[ZEBRA_ROUTE_OSPF])
410 {
411 api.type = ZEBRA_ROUTE_OSPF;
412 api.flags = 0;
413 api.message = 0;
414 zapi_ipv4_delete (zclient, p, &api);
415
416#if 0
417 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
418 {
419 char *nexthop_str;
420
421 nexthop_str = strdup (inet_ntoa (*nexthop));
422 zlog_info ("Zebra: Route delete %s/%d nexthop %s",
423 inet_ntoa (p->prefix), p->prefixlen, nexthop_str);
424 free (nexthop_str);
425 }
426#endif /* 0 */
427 }
428}
429
430void
431ospf_zebra_add_discard (struct prefix_ipv4 *p)
432{
433 struct zapi_ipv4 api;
434
435 if (zclient->redist[ZEBRA_ROUTE_OSPF])
436 {
437 api.type = ZEBRA_ROUTE_OSPF;
438 api.flags = ZEBRA_FLAG_BLACKHOLE;
439 api.message = 0;
440 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
441 api.nexthop_num = 0;
442 api.ifindex_num = 0;
443
444 zapi_ipv4_add (zclient, p, &api);
445 }
446}
447
448void
449ospf_zebra_delete_discard (struct prefix_ipv4 *p)
450{
451 struct zapi_ipv4 api;
452
453 if (zclient->redist[ZEBRA_ROUTE_OSPF])
454 {
455 api.type = ZEBRA_ROUTE_OSPF;
456 api.flags = ZEBRA_FLAG_BLACKHOLE;
457 api.message = 0;
458 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
459 api.nexthop_num = 0;
460 api.ifindex_num = 0;
461
462 zapi_ipv4_delete (zclient, p, &api);
463 }
464}
465
466int
467ospf_is_type_redistributed (int type)
468{
469 return (DEFAULT_ROUTE_TYPE (type)) ?
470 zclient->default_information : zclient->redist[type];
471}
472
473int
474ospf_redistribute_set (int type, int mtype, int mvalue)
475{
paul68980082003-03-25 05:07:42 +0000476 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +0000477 int force = 0;
478
479 if (ospf_is_type_redistributed (type))
480 {
paul68980082003-03-25 05:07:42 +0000481 if (mtype != ospf->dmetric[type].type)
paul718e3742002-12-13 20:15:29 +0000482 {
paul68980082003-03-25 05:07:42 +0000483 ospf->dmetric[type].type = mtype;
paul718e3742002-12-13 20:15:29 +0000484 force = LSA_REFRESH_FORCE;
485 }
paul68980082003-03-25 05:07:42 +0000486 if (mvalue != ospf->dmetric[type].value)
paul718e3742002-12-13 20:15:29 +0000487 {
paul68980082003-03-25 05:07:42 +0000488 ospf->dmetric[type].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000489 force = LSA_REFRESH_FORCE;
490 }
491
paul68980082003-03-25 05:07:42 +0000492 ospf_external_lsa_refresh_type (ospf, type, force);
paul718e3742002-12-13 20:15:29 +0000493
494 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
495 zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
496 LOOKUP (ospf_redistributed_proto, type),
paul68980082003-03-25 05:07:42 +0000497 metric_type (ospf, type), metric_value (ospf, type));
paul718e3742002-12-13 20:15:29 +0000498
499 return CMD_SUCCESS;
500 }
501
paul68980082003-03-25 05:07:42 +0000502 ospf->dmetric[type].type = mtype;
503 ospf->dmetric[type].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000504
505 zclient_redistribute_set (zclient, type);
506
507 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
508 zlog_info ("Redistribute[%s]: Start Type[%d], Metric[%d]",
509 LOOKUP (ospf_redistributed_proto, type),
paul68980082003-03-25 05:07:42 +0000510 metric_type (ospf, type), metric_value (ospf, type));
paul718e3742002-12-13 20:15:29 +0000511
paul68980082003-03-25 05:07:42 +0000512 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000513
514 return CMD_SUCCESS;
515}
516
517int
518ospf_redistribute_unset (int type)
519{
paul68980082003-03-25 05:07:42 +0000520 struct ospf *ospf = ospf_top;
521
paul718e3742002-12-13 20:15:29 +0000522 if (type == zclient->redist_default)
523 return CMD_SUCCESS;
524
525 if (! ospf_is_type_redistributed (type))
526 return CMD_SUCCESS;
527
528 zclient_redistribute_unset (zclient, type);
529
530 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
531 zlog_info ("Redistribute[%s]: Stop",
532 LOOKUP (ospf_redistributed_proto, type));
533
paul68980082003-03-25 05:07:42 +0000534 ospf->dmetric[type].type = -1;
535 ospf->dmetric[type].value = -1;
paul718e3742002-12-13 20:15:29 +0000536
537 /* Remove the routes from OSPF table. */
538 ospf_redistribute_withdraw (type);
539
paul68980082003-03-25 05:07:42 +0000540 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000541
542 return CMD_SUCCESS;
543}
544
545int
546ospf_redistribute_default_set (int originate, int mtype, int mvalue)
547{
paul68980082003-03-25 05:07:42 +0000548 struct ospf *ospf = ospf_top;
549
paul718e3742002-12-13 20:15:29 +0000550 int force = 0;
551 if (ospf_is_type_redistributed (DEFAULT_ROUTE))
552 {
paul68980082003-03-25 05:07:42 +0000553 if (mtype != ospf->dmetric[DEFAULT_ROUTE].type)
paul718e3742002-12-13 20:15:29 +0000554 {
paul68980082003-03-25 05:07:42 +0000555 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
paul718e3742002-12-13 20:15:29 +0000556 force = 1;
557 }
paul68980082003-03-25 05:07:42 +0000558 if (mvalue != ospf->dmetric[DEFAULT_ROUTE].value)
paul718e3742002-12-13 20:15:29 +0000559 {
560 force = 1;
paul68980082003-03-25 05:07:42 +0000561 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000562 }
563
paul68980082003-03-25 05:07:42 +0000564 ospf_external_lsa_refresh_default (ospf);
paul718e3742002-12-13 20:15:29 +0000565
566 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
567 zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
568 LOOKUP (ospf_redistributed_proto, DEFAULT_ROUTE),
paul68980082003-03-25 05:07:42 +0000569 metric_type (ospf, DEFAULT_ROUTE),
570 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000571 return CMD_SUCCESS;
572 }
573
paul68980082003-03-25 05:07:42 +0000574 ospf->default_originate = originate;
575 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
576 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
paul718e3742002-12-13 20:15:29 +0000577
578 zclient_redistribute_default_set (zclient);
579
580 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
581 zlog_info ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
paul68980082003-03-25 05:07:42 +0000582 metric_type (ospf, DEFAULT_ROUTE),
583 metric_value (ospf, DEFAULT_ROUTE));
paul718e3742002-12-13 20:15:29 +0000584
paul68980082003-03-25 05:07:42 +0000585 if (ospf->router_id.s_addr == 0)
586 ospf->external_origin |= (1 << DEFAULT_ROUTE);
paul718e3742002-12-13 20:15:29 +0000587 else
588 thread_add_timer (master, ospf_default_originate_timer,
paul68980082003-03-25 05:07:42 +0000589 &ospf->default_originate, 1);
paul718e3742002-12-13 20:15:29 +0000590
paul68980082003-03-25 05:07:42 +0000591 ospf_asbr_status_update (ospf, ++ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000592
593 return CMD_SUCCESS;
594}
595
596int
597ospf_redistribute_default_unset ()
598{
paul68980082003-03-25 05:07:42 +0000599 struct ospf *ospf = ospf_top;
600
paul718e3742002-12-13 20:15:29 +0000601 if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
602 return CMD_SUCCESS;
603
paul68980082003-03-25 05:07:42 +0000604 ospf->default_originate = DEFAULT_ORIGINATE_NONE;
605 ospf->dmetric[DEFAULT_ROUTE].type = -1;
606 ospf->dmetric[DEFAULT_ROUTE].value = -1;
paul718e3742002-12-13 20:15:29 +0000607
608 zclient_redistribute_default_unset (zclient);
609
610 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
611 zlog_info ("Redistribute[DEFAULT]: Stop");
612
paul68980082003-03-25 05:07:42 +0000613 ospf_asbr_status_update (ospf, --ospf->redistribute);
paul718e3742002-12-13 20:15:29 +0000614
615 return CMD_SUCCESS;
616}
617
618int
619ospf_external_lsa_originate_check (struct external_info *ei)
620{
paul68980082003-03-25 05:07:42 +0000621 struct ospf *ospf = ospf_top;
622
paul718e3742002-12-13 20:15:29 +0000623 /* 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))
paul68980082003-03-25 05:07:42 +0000633 if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
paul718e3742002-12-13 20:15:29 +0000634 {
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. */
644int
paul68980082003-03-25 05:07:42 +0000645ospf_distribute_check_connected (struct ospf *ospf,
646 struct external_info *ei)
paul718e3742002-12-13 20:15:29 +0000647{
648 struct route_node *rn;
649
paul68980082003-03-25 05:07:42 +0000650 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000651 if (rn->info != NULL)
652 if (prefix_match (&rn->p, (struct prefix *)&ei->p))
paul68980082003-03-25 05:07:42 +0000653 {
654 route_unlock_node (rn);
655 return 0;
656 }
paul718e3742002-12-13 20:15:29 +0000657
658 return 1;
659}
660
661/* return 1 if external LSA must be originated, 0 otherwise */
662int
paul68980082003-03-25 05:07:42 +0000663ospf_redistribute_check (struct ospf *ospf,
664 struct external_info *ei, int *changed)
paul718e3742002-12-13 20:15:29 +0000665{
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
673 if (!ospf_external_lsa_originate_check (ei))
674 return 0;
675
676 /* Take care connected route. */
paul68980082003-03-25 05:07:42 +0000677 if (type == ZEBRA_ROUTE_CONNECT &&
678 !ospf_distribute_check_connected (ospf, ei))
paul718e3742002-12-13 20:15:29 +0000679 return 0;
680
681 if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (type))
682 /* distirbute-list exists, but access-list may not? */
683 if (DISTRIBUTE_LIST (type))
684 if (access_list_apply (DISTRIBUTE_LIST (type), p) == FILTER_DENY)
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 */
697 if (ROUTEMAP_NAME (type))
698 {
699 int ret;
700
701 ret = route_map_apply (ROUTEMAP (type), (struct prefix *)p,
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 */
724void
725ospf_routemap_set (int type, char *name)
726{
727 if (ROUTEMAP_NAME (type))
728 free (ROUTEMAP_NAME (type));
729
730 ROUTEMAP_NAME (type) = strdup (name);
731 ROUTEMAP (type) = route_map_lookup_by_name (name);
732}
733
734void
735ospf_routemap_unset (int type)
736{
737 if (ROUTEMAP_NAME (type))
738 free (ROUTEMAP_NAME (type));
739
740 ROUTEMAP_NAME (type) = NULL;
741 ROUTEMAP (type) = NULL;
742}
743
744/* Zebra route add and delete treatment. */
745int
746ospf_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;
paul68980082003-03-25 05:07:42 +0000755 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +0000756
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
788 if (command == ZEBRA_IPV4_ROUTE_ADD)
789 {
790 ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
791
paul68980082003-03-25 05:07:42 +0000792 if (ospf->router_id.s_addr == 0)
paul718e3742002-12-13 20:15:29 +0000793 /* Set flags to generate AS-external-LSA originate event
794 for each redistributed protocols later. */
paul68980082003-03-25 05:07:42 +0000795 ospf->external_origin |= (1 << api.type);
paul718e3742002-12-13 20:15:29 +0000796 else
797 {
798 if (ei)
799 {
800 if (is_prefix_default (&p))
paul68980082003-03-25 05:07:42 +0000801 ospf_external_lsa_refresh_default (ospf);
paul718e3742002-12-13 20:15:29 +0000802 else
803 {
804 struct ospf_lsa *current;
805
paul68980082003-03-25 05:07:42 +0000806 current = ospf_external_info_find_lsa (ospf, &ei->p);
paul718e3742002-12-13 20:15:29 +0000807 if (!current)
paul68980082003-03-25 05:07:42 +0000808 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000809 else if (IS_LSA_MAXAGE (current))
paul68980082003-03-25 05:07:42 +0000810 ospf_external_lsa_refresh (ospf, current,
811 ei, LSA_REFRESH_FORCE);
paul718e3742002-12-13 20:15:29 +0000812 else
813 zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
814 inet_ntoa (p.prefix));
815 }
816 }
817 }
818 }
819 else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
820 {
821 ospf_external_info_delete (api.type, p);
822 if ( !is_prefix_default (&p))
paul68980082003-03-25 05:07:42 +0000823 ospf_external_lsa_flush (ospf, api.type, &p, ifindex, nexthop);
paul718e3742002-12-13 20:15:29 +0000824 else
paul68980082003-03-25 05:07:42 +0000825 ospf_external_lsa_refresh_default (ospf);
paul718e3742002-12-13 20:15:29 +0000826 }
827
828 return 0;
829}
830
831
832int
paul68980082003-03-25 05:07:42 +0000833ospf_distribute_list_out_set (struct ospf *ospf, int type, char *name)
paul718e3742002-12-13 20:15:29 +0000834{
835 /* Lookup access-list for distribute-list. */
836 DISTRIBUTE_LIST (type) = access_list_lookup (AFI_IP, name);
837
838 /* Clear previous distribute-name. */
839 if (DISTRIBUTE_NAME (type))
840 free (DISTRIBUTE_NAME (type));
841
842 /* Set distribute-name. */
843 DISTRIBUTE_NAME (type) = strdup (name);
844
845 /* If access-list have been set, schedule update timer. */
846 if (DISTRIBUTE_LIST (type))
paul68980082003-03-25 05:07:42 +0000847 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000848
849 return CMD_SUCCESS;
850}
851
852int
paul68980082003-03-25 05:07:42 +0000853ospf_distribute_list_out_unset (struct ospf *ospf, int type, char *name)
paul718e3742002-12-13 20:15:29 +0000854{
855 /* Schedule update timer. */
856 if (DISTRIBUTE_LIST (type))
paul68980082003-03-25 05:07:42 +0000857 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000858
859 /* Unset distribute-list. */
860 DISTRIBUTE_LIST (type) = NULL;
861
862 /* Clear distribute-name. */
863 if (DISTRIBUTE_NAME (type))
864 free (DISTRIBUTE_NAME (type));
865
866 DISTRIBUTE_NAME (type) = NULL;
867
868 return CMD_SUCCESS;
869}
870
871/* distribute-list update timer. */
872int
873ospf_distribute_list_update_timer (struct thread *thread)
874{
875 struct route_node *rn;
876 struct external_info *ei;
877 struct route_table *rt;
878 struct ospf_lsa *lsa;
879 u_char type;
paul68980082003-03-25 05:07:42 +0000880 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +0000881
882 type = (int) THREAD_ARG (thread);
883 rt = EXTERNAL_INFO (type);
884
paul68980082003-03-25 05:07:42 +0000885 ospf->t_distribute_update = NULL;
paul718e3742002-12-13 20:15:29 +0000886
887 zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
888
889 /* foreach all external info. */
890 if (rt)
891 for (rn = route_top (rt); rn; rn = route_next (rn))
892 if ((ei = rn->info) != NULL)
893 {
894 if (is_prefix_default (&ei->p))
paul68980082003-03-25 05:07:42 +0000895 ospf_external_lsa_refresh_default (ospf);
896 else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
897 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
paul718e3742002-12-13 20:15:29 +0000898 else
paul68980082003-03-25 05:07:42 +0000899 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000900 }
901 return 0;
902}
903
904#define OSPF_DISTRIBUTE_UPDATE_DELAY 5
905
906/* Update distribute-list and set timer to apply access-list. */
907void
paul68980082003-03-25 05:07:42 +0000908ospf_distribute_list_update (struct ospf *ospf, int type)
paul718e3742002-12-13 20:15:29 +0000909{
910 struct route_table *rt;
911
paul718e3742002-12-13 20:15:29 +0000912 /* External info does not exist. */
913 if (!(rt = EXTERNAL_INFO (type)))
914 return;
915
916 /* If exists previously invoked thread, then cancel it. */
paul68980082003-03-25 05:07:42 +0000917 if (ospf->t_distribute_update)
918 OSPF_TIMER_OFF (ospf->t_distribute_update);
paul718e3742002-12-13 20:15:29 +0000919
920 /* Set timer. */
paul68980082003-03-25 05:07:42 +0000921 ospf->t_distribute_update =
paul718e3742002-12-13 20:15:29 +0000922 thread_add_timer (master, ospf_distribute_list_update_timer,
923 (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000924}
925
926/* If access-list is updated, apply some check. */
927void
928ospf_filter_update (struct access_list *access)
929{
paul68980082003-03-25 05:07:42 +0000930 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +0000931 int type;
932 int abr_inv = 0;
933 struct ospf_area *area;
934 listnode node;
935
936 /* If OSPF instatnce does not exist, return right now. */
paul68980082003-03-25 05:07:42 +0000937 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000938 return;
939
paul718e3742002-12-13 20:15:29 +0000940 /* Update distribute-list, and apply filter. */
941 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
942 {
943 if (ROUTEMAP (type) != NULL)
944 {
945 /* if route-map is not NULL it may be using this access list */
paul68980082003-03-25 05:07:42 +0000946 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000947 continue;
948 }
949
950
951 if (DISTRIBUTE_NAME (type))
952 {
953 /* Keep old access-list for distribute-list. */
954 struct access_list *old = DISTRIBUTE_LIST (type);
955
956 /* Update access-list for distribute-list. */
957 DISTRIBUTE_LIST (type) =
958 access_list_lookup (AFI_IP, DISTRIBUTE_NAME (type));
959
960 /* No update for this distribute type. */
961 if (old == NULL && DISTRIBUTE_LIST (type) == NULL)
962 continue;
963
964 /* Schedule distribute-list update timer. */
965 if (DISTRIBUTE_LIST (type) == NULL ||
966 strcmp (DISTRIBUTE_NAME (type), access->name) == 0)
paul68980082003-03-25 05:07:42 +0000967 ospf_distribute_list_update (ospf, type);
paul718e3742002-12-13 20:15:29 +0000968 }
969 }
970
971 /* Update Area access-list. */
paul68980082003-03-25 05:07:42 +0000972 for (node = listhead (ospf->areas); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000973 if ((area = getdata (node)) != NULL)
974 {
975 if (EXPORT_NAME (area))
976 {
977 EXPORT_LIST (area) = NULL;
978 abr_inv++;
979 }
980
981 if (IMPORT_NAME (area))
982 {
983 IMPORT_LIST (area) = NULL;
984 abr_inv++;
985 }
986 }
987
988 /* Schedule ABR tasks -- this will be changed -- takada. */
989 if (OSPF_IS_ABR && abr_inv)
paul68980082003-03-25 05:07:42 +0000990 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000991}
992
993
994struct ospf_distance *
995ospf_distance_new ()
996{
997 struct ospf_distance *new;
998 new = XMALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
999 memset (new, 0, sizeof (struct ospf_distance));
1000 return new;
1001}
1002
1003void
1004ospf_distance_free (struct ospf_distance *odistance)
1005{
1006 XFREE (MTYPE_OSPF_DISTANCE, odistance);
1007}
1008
1009int
1010ospf_distance_set (struct vty *vty, char *distance_str, char *ip_str,
1011 char *access_list_str)
1012{
1013 int ret;
1014 struct prefix_ipv4 p;
1015 u_char distance;
1016 struct route_node *rn;
1017 struct ospf_distance *odistance;
paul68980082003-03-25 05:07:42 +00001018 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +00001019
1020 ret = str2prefix_ipv4 (ip_str, &p);
1021 if (ret == 0)
1022 {
1023 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1024 return CMD_WARNING;
1025 }
1026
1027 distance = atoi (distance_str);
1028
1029 /* Get OSPF distance node. */
paul68980082003-03-25 05:07:42 +00001030 rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +00001031 if (rn->info)
1032 {
1033 odistance = rn->info;
1034 route_unlock_node (rn);
1035 }
1036 else
1037 {
1038 odistance = ospf_distance_new ();
1039 rn->info = odistance;
1040 }
1041
1042 /* Set distance value. */
1043 odistance->distance = distance;
1044
1045 /* Reset access-list configuration. */
1046 if (odistance->access_list)
1047 {
1048 free (odistance->access_list);
1049 odistance->access_list = NULL;
1050 }
1051 if (access_list_str)
1052 odistance->access_list = strdup (access_list_str);
1053
1054 return CMD_SUCCESS;
1055}
1056
1057int
1058ospf_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
1059 char *access_list_str)
1060{
1061 int ret;
1062 struct prefix_ipv4 p;
1063 u_char distance;
1064 struct route_node *rn;
1065 struct ospf_distance *odistance;
paul68980082003-03-25 05:07:42 +00001066 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +00001067
1068 ret = str2prefix_ipv4 (ip_str, &p);
1069 if (ret == 0)
1070 {
1071 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1072 return CMD_WARNING;
1073 }
1074
1075 distance = atoi (distance_str);
1076
paul68980082003-03-25 05:07:42 +00001077 rn = route_node_lookup (ospf->distance_table, (struct prefix *)&p);
paul718e3742002-12-13 20:15:29 +00001078 if (! rn)
1079 {
1080 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
1081 return CMD_WARNING;
1082 }
1083
1084 odistance = rn->info;
1085
1086 if (odistance->access_list)
1087 free (odistance->access_list);
1088 ospf_distance_free (odistance);
1089
1090 rn->info = NULL;
1091 route_unlock_node (rn);
1092 route_unlock_node (rn);
1093
1094 return CMD_SUCCESS;
1095}
1096
1097void
paul68980082003-03-25 05:07:42 +00001098ospf_distance_reset (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001099{
1100 struct route_node *rn;
1101 struct ospf_distance *odistance;
1102
paul68980082003-03-25 05:07:42 +00001103 for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001104 if ((odistance = rn->info) != NULL)
1105 {
1106 if (odistance->access_list)
1107 free (odistance->access_list);
1108 ospf_distance_free (odistance);
1109 rn->info = NULL;
1110 route_unlock_node (rn);
1111 }
1112}
1113
1114u_char
1115ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
1116{
paul68980082003-03-25 05:07:42 +00001117 struct ospf *ospf = ospf_top;
paul718e3742002-12-13 20:15:29 +00001118
paul68980082003-03-25 05:07:42 +00001119 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001120 return 0;
1121
paul68980082003-03-25 05:07:42 +00001122 if (ospf->distance_intra)
paul718e3742002-12-13 20:15:29 +00001123 if (or->path_type == OSPF_PATH_INTRA_AREA)
paul68980082003-03-25 05:07:42 +00001124 return ospf->distance_intra;
paul718e3742002-12-13 20:15:29 +00001125
paul68980082003-03-25 05:07:42 +00001126 if (ospf->distance_inter)
paul718e3742002-12-13 20:15:29 +00001127 if (or->path_type == OSPF_PATH_INTER_AREA)
paul68980082003-03-25 05:07:42 +00001128 return ospf->distance_inter;
paul718e3742002-12-13 20:15:29 +00001129
paul68980082003-03-25 05:07:42 +00001130 if (ospf->distance_external)
paul718e3742002-12-13 20:15:29 +00001131 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
1132 || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
paul68980082003-03-25 05:07:42 +00001133 return ospf->distance_external;
paul718e3742002-12-13 20:15:29 +00001134
paul68980082003-03-25 05:07:42 +00001135 if (ospf->distance_all)
1136 return ospf->distance_all;
paul718e3742002-12-13 20:15:29 +00001137
1138 return 0;
1139}
1140
1141void
1142ospf_zebra_init ()
1143{
1144 /* Allocate zebra structure. */
1145 zclient = zclient_new ();
1146 zclient_init (zclient, ZEBRA_ROUTE_OSPF);
1147 zclient->interface_add = ospf_interface_add;
1148 zclient->interface_delete = ospf_interface_delete;
1149 zclient->interface_up = ospf_interface_state_up;
1150 zclient->interface_down = ospf_interface_state_down;
1151 zclient->interface_address_add = ospf_interface_address_add;
1152 zclient->interface_address_delete = ospf_interface_address_delete;
1153 zclient->ipv4_route_add = ospf_zebra_read_ipv4;
1154 zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
1155
1156 access_list_add_hook (ospf_filter_update);
1157 access_list_delete_hook (ospf_filter_update);
1158}