]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_zebra.c
From: David Watson <dwatson@eecs.umich.edu>
[mirror_frr.git] / ospfd / ospf_zebra.c
CommitLineData
718e3744 1/*
2 * Zebra connect library for OSPFd
3 * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "thread.h"
26#include "command.h"
27#include "network.h"
28#include "prefix.h"
29#include "routemap.h"
30#include "table.h"
31#include "stream.h"
32#include "memory.h"
33#include "zclient.h"
34#include "filter.h"
35#include "log.h"
36
37#include "ospfd/ospfd.h"
38#include "ospfd/ospf_interface.h"
39#include "ospfd/ospf_ism.h"
40#include "ospfd/ospf_asbr.h"
41#include "ospfd/ospf_asbr.h"
42#include "ospfd/ospf_abr.h"
43#include "ospfd/ospf_lsa.h"
44#include "ospfd/ospf_dump.h"
45#include "ospfd/ospf_route.h"
46#include "ospfd/ospf_zebra.h"
47#ifdef HAVE_SNMP
48#include "ospfd/ospf_snmp.h"
49#endif /* HAVE_SNMP */
50
51/* Zebra structure to hold current status. */
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;
68980084 62 struct ospf *ospf = ospf_top;
718e3744 63
64 ifp = zebra_interface_add_read (zclient->ibuf);
65
66 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
67 zlog_info ("Zebra: interface add %s index %d flags %ld metric %d mtu %d",
68 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
69
f2c80652 70 assert(ifp->info);
71
718e3744 72 if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
73 {
74 SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
75 IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST;
76
77 if (if_is_broadcast (ifp))
78 IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST;
79 else if (if_is_pointopoint (ifp))
80 IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOPOINT;
81 else if (if_is_loopback (ifp))
82 IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_LOOPBACK;
83 }
84
68980084 85 ospf_if_update (ospf);
718e3744 86
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. */
2e3b2e47 160 ifp->status = stream_getc (s);
718e3744 161 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. */
2e3b2e47 182 if (if_is_operative (ifp))
718e3744 183 {
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{
68980084 249 struct ospf *ospf = ospf_top;
718e3744 250 struct connected *c;
251
252 c = zebra_interface_address_add_read (zclient->ibuf);
253
254 if (c == NULL)
255 return 0;
256
68980084 257 ospf_if_update (ospf);
718e3744 258
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{
68980084 270 struct ospf *ospf = ospf_top;
718e3744 271 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
68980084 302 ospf_if_update (ospf);
718e3744 303
304 return 0;
305}
306\f
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{
68980084 476 struct ospf *ospf = ospf_top;
718e3744 477 int force = 0;
478
479 if (ospf_is_type_redistributed (type))
480 {
68980084 481 if (mtype != ospf->dmetric[type].type)
718e3744 482 {
68980084 483 ospf->dmetric[type].type = mtype;
718e3744 484 force = LSA_REFRESH_FORCE;
485 }
68980084 486 if (mvalue != ospf->dmetric[type].value)
718e3744 487 {
68980084 488 ospf->dmetric[type].value = mvalue;
718e3744 489 force = LSA_REFRESH_FORCE;
490 }
491
68980084 492 ospf_external_lsa_refresh_type (ospf, type, force);
718e3744 493
494 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
495 zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
496 LOOKUP (ospf_redistributed_proto, type),
68980084 497 metric_type (ospf, type), metric_value (ospf, type));
718e3744 498
499 return CMD_SUCCESS;
500 }
501
68980084 502 ospf->dmetric[type].type = mtype;
503 ospf->dmetric[type].value = mvalue;
718e3744 504
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),
68980084 510 metric_type (ospf, type), metric_value (ospf, type));
718e3744 511
68980084 512 ospf_asbr_status_update (ospf, ++ospf->redistribute);
718e3744 513
514 return CMD_SUCCESS;
515}
516
517int
518ospf_redistribute_unset (int type)
519{
68980084 520 struct ospf *ospf = ospf_top;
521
718e3744 522 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
68980084 534 ospf->dmetric[type].type = -1;
535 ospf->dmetric[type].value = -1;
718e3744 536
537 /* Remove the routes from OSPF table. */
538 ospf_redistribute_withdraw (type);
539
68980084 540 ospf_asbr_status_update (ospf, --ospf->redistribute);
718e3744 541
542 return CMD_SUCCESS;
543}
544
545int
546ospf_redistribute_default_set (int originate, int mtype, int mvalue)
547{
68980084 548 struct ospf *ospf = ospf_top;
549
718e3744 550 int force = 0;
551 if (ospf_is_type_redistributed (DEFAULT_ROUTE))
552 {
68980084 553 if (mtype != ospf->dmetric[DEFAULT_ROUTE].type)
718e3744 554 {
68980084 555 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
718e3744 556 force = 1;
557 }
68980084 558 if (mvalue != ospf->dmetric[DEFAULT_ROUTE].value)
718e3744 559 {
560 force = 1;
68980084 561 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
718e3744 562 }
563
68980084 564 ospf_external_lsa_refresh_default (ospf);
718e3744 565
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),
68980084 569 metric_type (ospf, DEFAULT_ROUTE),
570 metric_value (ospf, DEFAULT_ROUTE));
718e3744 571 return CMD_SUCCESS;
572 }
573
68980084 574 ospf->default_originate = originate;
575 ospf->dmetric[DEFAULT_ROUTE].type = mtype;
576 ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
718e3744 577
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]",
68980084 582 metric_type (ospf, DEFAULT_ROUTE),
583 metric_value (ospf, DEFAULT_ROUTE));
718e3744 584
68980084 585 if (ospf->router_id.s_addr == 0)
586 ospf->external_origin |= (1 << DEFAULT_ROUTE);
718e3744 587 else
588 thread_add_timer (master, ospf_default_originate_timer,
68980084 589 &ospf->default_originate, 1);
718e3744 590
68980084 591 ospf_asbr_status_update (ospf, ++ospf->redistribute);
718e3744 592
593 return CMD_SUCCESS;
594}
595
596int
597ospf_redistribute_default_unset ()
598{
68980084 599 struct ospf *ospf = ospf_top;
600
718e3744 601 if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
602 return CMD_SUCCESS;
603
68980084 604 ospf->default_originate = DEFAULT_ORIGINATE_NONE;
605 ospf->dmetric[DEFAULT_ROUTE].type = -1;
606 ospf->dmetric[DEFAULT_ROUTE].value = -1;
718e3744 607
608 zclient_redistribute_default_unset (zclient);
609
610 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
611 zlog_info ("Redistribute[DEFAULT]: Stop");
612
68980084 613 ospf_asbr_status_update (ospf, --ospf->redistribute);
718e3744 614
615 return CMD_SUCCESS;
616}
617
618int
619ospf_external_lsa_originate_check (struct external_info *ei)
620{
68980084 621 struct ospf *ospf = ospf_top;
622
718e3744 623 /* If prefix is multicast, then do not originate LSA. */
624 if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
625 {
626 zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
627 "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
628 return 0;
629 }
630
631 /* Take care of default-originate. */
632 if (is_prefix_default (&ei->p))
68980084 633 if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
718e3744 634 {
635 zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-exntenal-LSA "
636 "for default");
637 return 0;
638 }
639
640 return 1;
641}
642
643/* If connected prefix is OSPF enable interface, then do not announce. */
644int
68980084 645ospf_distribute_check_connected (struct ospf *ospf,
646 struct external_info *ei)
718e3744 647{
648 struct route_node *rn;
649
68980084 650 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
718e3744 651 if (rn->info != NULL)
652 if (prefix_match (&rn->p, (struct prefix *)&ei->p))
68980084 653 {
654 route_unlock_node (rn);
655 return 0;
656 }
718e3744 657
658 return 1;
659}
660
661/* return 1 if external LSA must be originated, 0 otherwise */
662int
68980084 663ospf_redistribute_check (struct ospf *ospf,
664 struct external_info *ei, int *changed)
718e3744 665{
666 struct route_map_set_values save_values;
667 struct prefix_ipv4 *p = &ei->p;
668 u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
669
670 if (changed)
671 *changed = 0;
672
673 if (!ospf_external_lsa_originate_check (ei))
674 return 0;
675
676 /* Take care connected route. */
68980084 677 if (type == ZEBRA_ROUTE_CONNECT &&
678 !ospf_distribute_check_connected (ospf, ei))
718e3744 679 return 0;
680
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;
68980084 755 struct ospf *ospf = ospf_top;
718e3744 756
757 s = zclient->ibuf;
758 ifindex = 0;
759 nexthop.s_addr = 0;
760
761 /* Type, flags, message. */
762 api.type = stream_getc (s);
763 api.flags = stream_getc (s);
764 api.message = stream_getc (s);
765
766 /* IPv4 prefix. */
767 memset (&p, 0, sizeof (struct prefix_ipv4));
768 p.family = AF_INET;
769 p.prefixlen = stream_getc (s);
770 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
771
772 /* Nexthop, ifindex, distance, metric. */
773 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
774 {
775 api.nexthop_num = stream_getc (s);
776 nexthop.s_addr = stream_get_ipv4 (s);
777 }
778 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
779 {
780 api.ifindex_num = stream_getc (s);
781 ifindex = stream_getl (s);
782 }
783 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
784 api.distance = stream_getc (s);
785 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
786 api.metric = stream_getl (s);
787
788 if (command == ZEBRA_IPV4_ROUTE_ADD)
789 {
790 ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
791
68980084 792 if (ospf->router_id.s_addr == 0)
718e3744 793 /* Set flags to generate AS-external-LSA originate event
794 for each redistributed protocols later. */
68980084 795 ospf->external_origin |= (1 << api.type);
718e3744 796 else
797 {
798 if (ei)
799 {
800 if (is_prefix_default (&p))
68980084 801 ospf_external_lsa_refresh_default (ospf);
718e3744 802 else
803 {
804 struct ospf_lsa *current;
805
68980084 806 current = ospf_external_info_find_lsa (ospf, &ei->p);
718e3744 807 if (!current)
68980084 808 ospf_external_lsa_originate (ospf, ei);
718e3744 809 else if (IS_LSA_MAXAGE (current))
68980084 810 ospf_external_lsa_refresh (ospf, current,
811 ei, LSA_REFRESH_FORCE);
718e3744 812 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))
68980084 823 ospf_external_lsa_flush (ospf, api.type, &p, ifindex, nexthop);
718e3744 824 else
68980084 825 ospf_external_lsa_refresh_default (ospf);
718e3744 826 }
827
828 return 0;
829}
830
831\f
832int
68980084 833ospf_distribute_list_out_set (struct ospf *ospf, int type, char *name)
718e3744 834{
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))
68980084 847 ospf_distribute_list_update (ospf, type);
718e3744 848
849 return CMD_SUCCESS;
850}
851
852int
68980084 853ospf_distribute_list_out_unset (struct ospf *ospf, int type, char *name)
718e3744 854{
855 /* Schedule update timer. */
856 if (DISTRIBUTE_LIST (type))
68980084 857 ospf_distribute_list_update (ospf, type);
718e3744 858
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;
68980084 880 struct ospf *ospf = ospf_top;
718e3744 881
882 type = (int) THREAD_ARG (thread);
883 rt = EXTERNAL_INFO (type);
884
68980084 885 ospf->t_distribute_update = NULL;
718e3744 886
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))
68980084 895 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);
718e3744 898 else
68980084 899 ospf_external_lsa_originate (ospf, ei);
718e3744 900 }
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
68980084 908ospf_distribute_list_update (struct ospf *ospf, int type)
718e3744 909{
910 struct route_table *rt;
911
718e3744 912 /* External info does not exist. */
913 if (!(rt = EXTERNAL_INFO (type)))
914 return;
915
916 /* If exists previously invoked thread, then cancel it. */
68980084 917 if (ospf->t_distribute_update)
918 OSPF_TIMER_OFF (ospf->t_distribute_update);
718e3744 919
920 /* Set timer. */
68980084 921 ospf->t_distribute_update =
718e3744 922 thread_add_timer (master, ospf_distribute_list_update_timer,
923 (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
718e3744 924}
925
926/* If access-list is updated, apply some check. */
927void
928ospf_filter_update (struct access_list *access)
929{
68980084 930 struct ospf *ospf = ospf_top;
718e3744 931 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. */
68980084 937 if (ospf == NULL)
718e3744 938 return;
939
718e3744 940 /* 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 */
68980084 946 ospf_distribute_list_update (ospf, type);
718e3744 947 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)
68980084 967 ospf_distribute_list_update (ospf, type);
718e3744 968 }
969 }
970
971 /* Update Area access-list. */
68980084 972 for (node = listhead (ospf->areas); node; nextnode (node))
718e3744 973 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)
68980084 990 ospf_schedule_abr_task (ospf);
718e3744 991}
992
993\f
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;
68980084 1018 struct ospf *ospf = ospf_top;
718e3744 1019
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. */
68980084 1030 rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
718e3744 1031 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;
68980084 1066 struct ospf *ospf = ospf_top;
718e3744 1067
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
68980084 1077 rn = route_node_lookup (ospf->distance_table, (struct prefix *)&p);
718e3744 1078 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
68980084 1098ospf_distance_reset (struct ospf *ospf)
718e3744 1099{
1100 struct route_node *rn;
1101 struct ospf_distance *odistance;
1102
68980084 1103 for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
718e3744 1104 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{
68980084 1117 struct ospf *ospf = ospf_top;
718e3744 1118
68980084 1119 if (ospf == NULL)
718e3744 1120 return 0;
1121
68980084 1122 if (ospf->distance_intra)
718e3744 1123 if (or->path_type == OSPF_PATH_INTRA_AREA)
68980084 1124 return ospf->distance_intra;
718e3744 1125
68980084 1126 if (ospf->distance_inter)
718e3744 1127 if (or->path_type == OSPF_PATH_INTER_AREA)
68980084 1128 return ospf->distance_inter;
718e3744 1129
68980084 1130 if (ospf->distance_external)
718e3744 1131 if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
1132 || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
68980084 1133 return ospf->distance_external;
718e3744 1134
68980084 1135 if (ospf->distance_all)
1136 return ospf->distance_all;
718e3744 1137
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}