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