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