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