Annotation of embedaddon/quagga/ospfd/ospf_zebra.c, revision 1.1.1.3
1.1 misho 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 "plist.h"
36: #include "log.h"
37:
38: #include "ospfd/ospfd.h"
39: #include "ospfd/ospf_interface.h"
40: #include "ospfd/ospf_ism.h"
41: #include "ospfd/ospf_asbr.h"
42: #include "ospfd/ospf_asbr.h"
43: #include "ospfd/ospf_abr.h"
44: #include "ospfd/ospf_lsa.h"
45: #include "ospfd/ospf_dump.h"
46: #include "ospfd/ospf_route.h"
47: #include "ospfd/ospf_zebra.h"
48: #ifdef HAVE_SNMP
49: #include "ospfd/ospf_snmp.h"
50: #endif /* HAVE_SNMP */
51:
52: /* Zebra structure to hold current status. */
53: struct zclient *zclient = NULL;
54:
55: /* For registering threads. */
56: extern struct thread_master *master;
57: struct in_addr router_id_zebra;
58:
59: /* Router-id update message from zebra. */
60: static int
61: ospf_router_id_update_zebra (int command, struct zclient *zclient,
62: zebra_size_t length)
63: {
64: struct ospf *ospf;
65: struct prefix router_id;
66: zebra_router_id_update_read(zclient->ibuf,&router_id);
67:
68: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
69: {
70: char buf[128];
71: prefix2str(&router_id, buf, sizeof(buf));
72: zlog_debug("Zebra rcvd: router id update %s", buf);
73: }
74:
75: router_id_zebra = router_id.u.prefix4;
76:
77: ospf = ospf_lookup ();
78:
79: if (ospf != NULL)
80: ospf_router_id_update (ospf);
81:
82: return 0;
83: }
84:
85: /* Inteface addition message from zebra. */
86: static int
87: ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
88: {
89: struct interface *ifp;
90:
91: ifp = zebra_interface_add_read (zclient->ibuf);
92:
93: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
94: zlog_debug ("Zebra: interface add %s index %d flags %llx metric %d mtu %d",
95: ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
96: ifp->metric, ifp->mtu);
97:
98: assert (ifp->info);
99:
100: if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
101: {
102: SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
103: IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp);
104: }
105:
106: ospf_if_update (NULL, ifp);
107:
108: #ifdef HAVE_SNMP
109: ospf_snmp_if_update (ifp);
110: #endif /* HAVE_SNMP */
111:
112: return 0;
113: }
114:
115: static int
116: ospf_interface_delete (int command, struct zclient *zclient,
117: zebra_size_t length)
118: {
119: struct interface *ifp;
120: struct stream *s;
121: struct route_node *rn;
122:
123: s = zclient->ibuf;
124: /* zebra_interface_state_read() updates interface structure in iflist */
125: ifp = zebra_interface_state_read (s);
126:
127: if (ifp == NULL)
128: return 0;
129:
130: if (if_is_up (ifp))
131: zlog_warn ("Zebra: got delete of %s, but interface is still up",
132: ifp->name);
133:
134: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
135: zlog_debug
1.1.1.3 ! misho 136: ("Zebra: interface delete %s index %d flags %llx metric %d mtu %d",
! 137: ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
1.1 misho 138:
139: #ifdef HAVE_SNMP
140: ospf_snmp_if_delete (ifp);
141: #endif /* HAVE_SNMP */
142:
143: for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
144: if (rn->info)
145: ospf_if_free ((struct ospf_interface *) rn->info);
146:
147: ifp->ifindex = IFINDEX_INTERNAL;
148: return 0;
149: }
150:
151: static struct interface *
152: zebra_interface_if_lookup (struct stream *s)
153: {
154: char ifname_tmp[INTERFACE_NAMSIZ];
155:
156: /* Read interface name. */
157: stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
158:
159: /* And look it up. */
160: return if_lookup_by_name_len(ifname_tmp,
161: strnlen(ifname_tmp, INTERFACE_NAMSIZ));
162: }
163:
164: static int
165: ospf_interface_state_up (int command, struct zclient *zclient,
166: zebra_size_t length)
167: {
168: struct interface *ifp;
169: struct ospf_interface *oi;
170: struct route_node *rn;
171:
172: ifp = zebra_interface_if_lookup (zclient->ibuf);
173:
174: if (ifp == NULL)
175: return 0;
176:
177: /* Interface is already up. */
178: if (if_is_operative (ifp))
179: {
180: /* Temporarily keep ifp values. */
181: struct interface if_tmp;
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_debug ("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_debug ("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:
198: if (if_tmp.mtu != ifp->mtu)
199: {
200: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
201: zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.",
202: ifp->name, if_tmp.mtu, ifp->mtu);
203:
204: /* Must reset the interface (simulate down/up) when MTU changes. */
205: ospf_if_reset(ifp);
206: }
207: return 0;
208: }
209:
210: zebra_interface_if_set_value (zclient->ibuf, ifp);
211:
212: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
213: zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name);
214:
215: for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
216: {
217: if ((oi = rn->info) == NULL)
218: continue;
219:
220: ospf_if_up (oi);
221: }
222:
223: return 0;
224: }
225:
226: static int
227: ospf_interface_state_down (int command, struct zclient *zclient,
228: zebra_size_t length)
229: {
230: struct interface *ifp;
231: struct ospf_interface *oi;
232: struct route_node *node;
233:
234: ifp = zebra_interface_state_read (zclient->ibuf);
235:
236: if (ifp == NULL)
237: return 0;
238:
239: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
240: zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name);
241:
242: for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
243: {
244: if ((oi = node->info) == NULL)
245: continue;
246: ospf_if_down (oi);
247: }
248:
249: return 0;
250: }
251:
252: static int
253: ospf_interface_address_add (int command, struct zclient *zclient,
254: zebra_size_t length)
255: {
256: struct connected *c;
257:
258: c = zebra_interface_address_read (command, zclient->ibuf);
259:
260: if (c == NULL)
261: return 0;
262:
263: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
264: {
265: char buf[128];
266: prefix2str(c->address, buf, sizeof(buf));
267: zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
268: }
269:
270: ospf_if_update (NULL, c->ifp);
271:
272: #ifdef HAVE_SNMP
273: ospf_snmp_if_update (c->ifp);
274: #endif /* HAVE_SNMP */
275:
276: return 0;
277: }
278:
279: static int
280: ospf_interface_address_delete (int command, struct zclient *zclient,
281: zebra_size_t length)
282: {
283: struct connected *c;
284: struct interface *ifp;
285: struct ospf_interface *oi;
286: struct route_node *rn;
287: struct prefix p;
288:
289: c = zebra_interface_address_read (command, zclient->ibuf);
290:
291: if (c == NULL)
292: return 0;
293:
294: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
295: {
296: char buf[128];
297: prefix2str(c->address, buf, sizeof(buf));
298: zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf);
299: }
300:
301: ifp = c->ifp;
302: p = *c->address;
303: p.prefixlen = IPV4_MAX_PREFIXLEN;
304:
305: rn = route_node_lookup (IF_OIFS (ifp), &p);
306: if (!rn)
307: {
308: connected_free (c);
309: return 0;
310: }
311:
312: assert (rn->info);
313: oi = rn->info;
314:
315: /* Call interface hook functions to clean up */
316: ospf_if_free (oi);
317:
318: #ifdef HAVE_SNMP
319: ospf_snmp_if_update (c->ifp);
320: #endif /* HAVE_SNMP */
321:
322: connected_free (c);
323:
324: return 0;
325: }
326:
327: void
328: ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
329: {
330: u_char message;
331: u_char distance;
332: u_char flags;
333: int psize;
334: struct stream *s;
335: struct ospf_path *path;
336: struct listnode *node;
337:
338: if (zclient->redist[ZEBRA_ROUTE_OSPF])
339: {
340: message = 0;
341: flags = 0;
342:
343: /* OSPF pass nexthop and metric */
344: SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
345: SET_FLAG (message, ZAPI_MESSAGE_METRIC);
346:
347: /* Distance value. */
348: distance = ospf_distance_apply (p, or);
349: if (distance)
350: SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
351:
352: /* Make packet. */
353: s = zclient->obuf;
354: stream_reset (s);
355:
356: /* Put command, type, flags, message. */
357: zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD);
358: stream_putc (s, ZEBRA_ROUTE_OSPF);
359: stream_putc (s, flags);
360: stream_putc (s, message);
1.1.1.2 misho 361: stream_putw (s, SAFI_UNICAST);
1.1 misho 362:
363: /* Put prefix information. */
364: psize = PSIZE (p->prefixlen);
365: stream_putc (s, p->prefixlen);
366: stream_write (s, (u_char *) & p->prefix, psize);
367:
368: /* Nexthop count. */
369: stream_putc (s, or->paths->count);
370:
371: /* Nexthop, ifindex, distance and metric information. */
372: for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
373: {
1.1.1.3 ! misho 374: if (path->nexthop.s_addr != INADDR_ANY &&
! 375: path->ifindex != 0)
! 376: {
! 377: stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
! 378: stream_put_in_addr (s, &path->nexthop);
! 379: stream_putl (s, path->ifindex);
! 380: }
! 381: else if (path->nexthop.s_addr != INADDR_ANY)
1.1 misho 382: {
383: stream_putc (s, ZEBRA_NEXTHOP_IPV4);
384: stream_put_in_addr (s, &path->nexthop);
385: }
386: else
387: {
388: stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
389: if (path->ifindex)
390: stream_putl (s, path->ifindex);
391: else
392: stream_putl (s, 0);
393: }
394:
395: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
396: {
397: char buf[2][INET_ADDRSTRLEN];
398: zlog_debug("Zebra: Route add %s/%d nexthop %s",
399: inet_ntop(AF_INET, &p->prefix,
400: buf[0], sizeof(buf[0])),
401: p->prefixlen,
402: inet_ntop(AF_INET, &path->nexthop,
403: buf[1], sizeof(buf[1])));
404: }
405: }
406:
407: if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
408: stream_putc (s, distance);
409: if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
410: {
411: if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
412: stream_putl (s, or->cost + or->u.ext.type2_cost);
413: else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
414: stream_putl (s, or->u.ext.type2_cost);
415: else
416: stream_putl (s, or->cost);
417: }
418:
419: stream_putw_at (s, 0, stream_get_endp (s));
420:
421: zclient_send_message(zclient);
422: }
423: }
424:
425: void
426: ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
427: {
1.1.1.3 ! misho 428: u_char message;
! 429: u_char distance;
! 430: u_char flags;
! 431: int psize;
! 432: struct stream *s;
1.1 misho 433: struct ospf_path *path;
1.1.1.3 ! misho 434: struct listnode *node;
1.1 misho 435:
436: if (zclient->redist[ZEBRA_ROUTE_OSPF])
437: {
1.1.1.3 ! misho 438: message = 0;
! 439: flags = 0;
! 440: /* Distance value. */
! 441: distance = ospf_distance_apply (p, or);
! 442: /* Make packet. */
! 443: s = zclient->obuf;
! 444: stream_reset (s);
1.1 misho 445:
1.1.1.3 ! misho 446: /* Put command, type, flags, message. */
! 447: zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE);
! 448: stream_putc (s, ZEBRA_ROUTE_OSPF);
! 449: stream_putc (s, flags);
! 450: stream_putc (s, message);
! 451: stream_putw (s, SAFI_UNICAST);
1.1 misho 452:
1.1.1.3 ! misho 453: /* Put prefix information. */
! 454: psize = PSIZE (p->prefixlen);
! 455: stream_putc (s, p->prefixlen);
! 456: stream_write (s, (u_char *) & p->prefix, psize);
1.1 misho 457:
1.1.1.3 ! misho 458: /* Nexthop count. */
! 459: stream_putc (s, or->paths->count);
! 460:
! 461: /* Nexthop, ifindex, distance and metric information. */
! 462: for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
! 463: {
! 464: if (path->nexthop.s_addr != INADDR_ANY &&
! 465: path->ifindex != 0)
! 466: {
! 467: stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
! 468: stream_put_in_addr (s, &path->nexthop);
! 469: stream_putl (s, path->ifindex);
! 470: }
! 471: else if (path->nexthop.s_addr != INADDR_ANY)
! 472: {
! 473: stream_putc (s, ZEBRA_NEXTHOP_IPV4);
! 474: stream_put_in_addr (s, &path->nexthop);
! 475: }
! 476: else
! 477: {
! 478: stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
! 479: stream_putl (s, path->ifindex);
! 480: }
! 481:
! 482: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
! 483: {
1.1 misho 484: char buf[2][INET_ADDRSTRLEN];
1.1.1.3 ! misho 485: zlog_debug("Zebra: Route add %s/%d nexthop %s",
! 486: inet_ntop(AF_INET, &p->prefix,
! 487: buf[0], sizeof(buf[0])),
1.1 misho 488: p->prefixlen,
1.1.1.3 ! misho 489: inet_ntop(AF_INET, &path->nexthop,
1.1 misho 490: buf[1], sizeof(buf[1])));
1.1.1.3 ! misho 491: }
! 492: }
! 493:
! 494: if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
! 495: stream_putc (s, distance);
! 496: if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
! 497: {
! 498: if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
! 499: stream_putl (s, or->cost + or->u.ext.type2_cost);
! 500: else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
! 501: stream_putl (s, or->u.ext.type2_cost);
! 502: else
! 503: stream_putl (s, or->cost);
! 504: }
! 505:
! 506: stream_putw_at (s, 0, stream_get_endp (s));
! 507:
! 508: zclient_send_message(zclient);
1.1 misho 509: }
510: }
511:
512: void
513: ospf_zebra_add_discard (struct prefix_ipv4 *p)
514: {
515: struct zapi_ipv4 api;
516:
517: if (zclient->redist[ZEBRA_ROUTE_OSPF])
518: {
519: api.type = ZEBRA_ROUTE_OSPF;
520: api.flags = ZEBRA_FLAG_BLACKHOLE;
521: api.message = 0;
1.1.1.2 misho 522: api.safi = SAFI_UNICAST;
1.1 misho 523: SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
524: api.nexthop_num = 0;
525: api.ifindex_num = 0;
526:
527: zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
528:
529: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
530: zlog_debug ("Zebra: Route add discard %s/%d",
531: inet_ntoa (p->prefix), p->prefixlen);
532: }
533: }
534:
535: void
536: ospf_zebra_delete_discard (struct prefix_ipv4 *p)
537: {
538: struct zapi_ipv4 api;
539:
540: if (zclient->redist[ZEBRA_ROUTE_OSPF])
541: {
542: api.type = ZEBRA_ROUTE_OSPF;
543: api.flags = ZEBRA_FLAG_BLACKHOLE;
544: api.message = 0;
1.1.1.2 misho 545: api.safi = SAFI_UNICAST;
1.1 misho 546: SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
547: api.nexthop_num = 0;
548: api.ifindex_num = 0;
549:
550: zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
551:
552: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
553: zlog_debug ("Zebra: Route delete discard %s/%d",
554: inet_ntoa (p->prefix), p->prefixlen);
555:
556: }
557: }
558:
559: int
560: ospf_is_type_redistributed (int type)
561: {
562: return (DEFAULT_ROUTE_TYPE (type)) ?
563: zclient->default_information : zclient->redist[type];
564: }
565:
566: int
567: ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue)
568: {
569: int force = 0;
570:
571: if (ospf_is_type_redistributed (type))
572: {
573: if (mtype != ospf->dmetric[type].type)
574: {
575: ospf->dmetric[type].type = mtype;
576: force = LSA_REFRESH_FORCE;
577: }
578: if (mvalue != ospf->dmetric[type].value)
579: {
580: ospf->dmetric[type].value = mvalue;
581: force = LSA_REFRESH_FORCE;
582: }
583:
584: ospf_external_lsa_refresh_type (ospf, type, force);
585:
586: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
587: zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
588: ospf_redist_string(type),
589: metric_type (ospf, type), metric_value (ospf, type));
590:
591: return CMD_SUCCESS;
592: }
593:
594: ospf->dmetric[type].type = mtype;
595: ospf->dmetric[type].value = mvalue;
596:
597: zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
598:
599: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
600: zlog_debug ("Redistribute[%s]: Start Type[%d], Metric[%d]",
601: ospf_redist_string(type),
602: metric_type (ospf, type), metric_value (ospf, type));
603:
604: ospf_asbr_status_update (ospf, ++ospf->redistribute);
605:
606: return CMD_SUCCESS;
607: }
608:
609: int
610: ospf_redistribute_unset (struct ospf *ospf, int type)
611: {
612: if (type == zclient->redist_default)
613: return CMD_SUCCESS;
614:
615: if (!ospf_is_type_redistributed (type))
616: return CMD_SUCCESS;
617:
618: zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
619:
620: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
621: zlog_debug ("Redistribute[%s]: Stop",
622: ospf_redist_string(type));
623:
624: ospf->dmetric[type].type = -1;
625: ospf->dmetric[type].value = -1;
626:
627: /* Remove the routes from OSPF table. */
628: ospf_redistribute_withdraw (ospf, type);
629:
630: ospf_asbr_status_update (ospf, --ospf->redistribute);
631:
632: return CMD_SUCCESS;
633: }
634:
635: int
636: ospf_redistribute_default_set (struct ospf *ospf, int originate,
637: int mtype, int mvalue)
638: {
639: ospf->default_originate = originate;
640: ospf->dmetric[DEFAULT_ROUTE].type = mtype;
641: ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
642:
643: if (ospf_is_type_redistributed (DEFAULT_ROUTE))
644: {
645: /* if ospf->default_originate changes value, is calling
646: ospf_external_lsa_refresh_default sufficient to implement
647: the change? */
648: ospf_external_lsa_refresh_default (ospf);
649:
650: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
651: zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
652: ospf_redist_string(DEFAULT_ROUTE),
653: metric_type (ospf, DEFAULT_ROUTE),
654: metric_value (ospf, DEFAULT_ROUTE));
655: return CMD_SUCCESS;
656: }
657:
658: zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient);
659:
660: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
661: zlog_debug ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
662: metric_type (ospf, DEFAULT_ROUTE),
663: metric_value (ospf, DEFAULT_ROUTE));
664:
665: if (ospf->router_id.s_addr == 0)
666: ospf->external_origin |= (1 << DEFAULT_ROUTE);
667: else
668: thread_add_timer (master, ospf_default_originate_timer, ospf, 1);
669:
670: ospf_asbr_status_update (ospf, ++ospf->redistribute);
671:
672: return CMD_SUCCESS;
673: }
674:
675: int
676: ospf_redistribute_default_unset (struct ospf *ospf)
677: {
678: if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
679: return CMD_SUCCESS;
680:
681: ospf->default_originate = DEFAULT_ORIGINATE_NONE;
682: ospf->dmetric[DEFAULT_ROUTE].type = -1;
683: ospf->dmetric[DEFAULT_ROUTE].value = -1;
684:
685: zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient);
686:
687: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
688: zlog_debug ("Redistribute[DEFAULT]: Stop");
689:
690: ospf_asbr_status_update (ospf, --ospf->redistribute);
691:
692: return CMD_SUCCESS;
693: }
694:
695: static int
696: ospf_external_lsa_originate_check (struct ospf *ospf,
697: struct external_info *ei)
698: {
699: /* If prefix is multicast, then do not originate LSA. */
700: if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
701: {
702: zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
703: "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
704: return 0;
705: }
706:
707: /* Take care of default-originate. */
708: if (is_prefix_default (&ei->p))
709: if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
710: {
711: zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA "
712: "for default");
713: return 0;
714: }
715:
716: return 1;
717: }
718:
719: /* If connected prefix is OSPF enable interface, then do not announce. */
720: int
721: ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei)
722: {
723: struct listnode *node;
724: struct ospf_interface *oi;
725:
726:
727: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
728: if (prefix_match (oi->address, (struct prefix *) &ei->p))
729: return 0;
730: return 1;
731: }
732:
733: /* return 1 if external LSA must be originated, 0 otherwise */
734: int
735: ospf_redistribute_check (struct ospf *ospf,
736: struct external_info *ei, int *changed)
737: {
738: struct route_map_set_values save_values;
739: struct prefix_ipv4 *p = &ei->p;
740: u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
741:
742: if (changed)
743: *changed = 0;
744:
745: if (!ospf_external_lsa_originate_check (ospf, ei))
746: return 0;
747:
748: /* Take care connected route. */
749: if (type == ZEBRA_ROUTE_CONNECT &&
750: !ospf_distribute_check_connected (ospf, ei))
751: return 0;
752:
753: if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type))
754: /* distirbute-list exists, but access-list may not? */
755: if (DISTRIBUTE_LIST (ospf, type))
756: if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
757: {
758: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
759: zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
760: ospf_redist_string(type),
761: inet_ntoa (p->prefix), p->prefixlen);
762: return 0;
763: }
764:
765: save_values = ei->route_map_set;
766: ospf_reset_route_map_set_values (&ei->route_map_set);
767:
768: /* apply route-map if needed */
769: if (ROUTEMAP_NAME (ospf, type))
770: {
771: int ret;
772:
773: ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p,
774: RMAP_OSPF, ei);
775:
776: if (ret == RMAP_DENYMATCH)
777: {
778: ei->route_map_set = save_values;
779: if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
780: zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.",
781: ospf_redist_string(type),
782: inet_ntoa (p->prefix), p->prefixlen);
783: return 0;
784: }
785:
786: /* check if 'route-map set' changed something */
787: if (changed)
788: *changed = !ospf_route_map_set_compare (&ei->route_map_set,
789: &save_values);
790: }
791:
792: return 1;
793: }
794:
795: /* OSPF route-map set for redistribution */
796: void
797: ospf_routemap_set (struct ospf *ospf, int type, const char *name)
798: {
799: if (ROUTEMAP_NAME (ospf, type))
800: free (ROUTEMAP_NAME (ospf, type));
801:
802: ROUTEMAP_NAME (ospf, type) = strdup (name);
803: ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);
804: }
805:
806: void
807: ospf_routemap_unset (struct ospf *ospf, int type)
808: {
809: if (ROUTEMAP_NAME (ospf, type))
810: free (ROUTEMAP_NAME (ospf, type));
811:
812: ROUTEMAP_NAME (ospf, type) = NULL;
813: ROUTEMAP (ospf, type) = NULL;
814: }
815:
816: /* Zebra route add and delete treatment. */
817: static int
818: ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
819: zebra_size_t length)
820: {
821: struct stream *s;
822: struct zapi_ipv4 api;
823: unsigned long ifindex;
824: struct in_addr nexthop;
825: struct prefix_ipv4 p;
826: struct external_info *ei;
827: struct ospf *ospf;
828:
829: s = zclient->ibuf;
830: ifindex = 0;
831: nexthop.s_addr = 0;
832:
833: /* Type, flags, message. */
834: api.type = stream_getc (s);
835: api.flags = stream_getc (s);
836: api.message = stream_getc (s);
837:
838: /* IPv4 prefix. */
839: memset (&p, 0, sizeof (struct prefix_ipv4));
840: p.family = AF_INET;
841: p.prefixlen = stream_getc (s);
842: stream_get (&p.prefix, s, PSIZE (p.prefixlen));
843:
844: if (IPV4_NET127(ntohl(p.prefix.s_addr)))
845: return 0;
846:
847: /* Nexthop, ifindex, distance, metric. */
848: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
849: {
850: api.nexthop_num = stream_getc (s);
851: nexthop.s_addr = stream_get_ipv4 (s);
852: }
853: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
854: {
855: api.ifindex_num = stream_getc (s);
856: /* XXX assert(api.ifindex_num == 1); */
857: ifindex = stream_getl (s);
858: }
859: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
860: api.distance = stream_getc (s);
861: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
862: api.metric = stream_getl (s);
863:
864: ospf = ospf_lookup ();
865: if (ospf == NULL)
866: return 0;
867:
868: if (command == ZEBRA_IPV4_ROUTE_ADD)
869: {
870: /* XXX|HACK|TODO|FIXME:
871: * Maybe we should ignore reject/blackhole routes? Testing shows that
872: * there is no problems though and this is only way to "summarize"
873: * routes in ASBR at the moment. Maybe we need just a better generalised
874: * solution for these types?
875: *
876: * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE)
877: * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
878: * return 0;
879: */
880:
881: ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
882:
883: if (ospf->router_id.s_addr == 0)
884: /* Set flags to generate AS-external-LSA originate event
885: for each redistributed protocols later. */
886: ospf->external_origin |= (1 << api.type);
887: else
888: {
889: if (ei)
890: {
891: if (is_prefix_default (&p))
892: ospf_external_lsa_refresh_default (ospf);
893: else
894: {
895: struct ospf_lsa *current;
896:
897: current = ospf_external_info_find_lsa (ospf, &ei->p);
898: if (!current)
899: ospf_external_lsa_originate (ospf, ei);
900: else if (IS_LSA_MAXAGE (current))
901: ospf_external_lsa_refresh (ospf, current,
902: ei, LSA_REFRESH_FORCE);
903: else
904: zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
905: inet_ntoa (p.prefix));
906: }
907: }
908: }
909: }
910: else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
911: {
912: ospf_external_info_delete (api.type, p);
913: if (is_prefix_default (&p))
914: ospf_external_lsa_refresh_default (ospf);
915: else
916: ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */);
917: }
918:
919: return 0;
920: }
921:
922:
923: int
924: ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name)
925: {
926: /* Lookup access-list for distribute-list. */
927: DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
928:
929: /* Clear previous distribute-name. */
930: if (DISTRIBUTE_NAME (ospf, type))
931: free (DISTRIBUTE_NAME (ospf, type));
932:
933: /* Set distribute-name. */
934: DISTRIBUTE_NAME (ospf, type) = strdup (name);
935:
936: /* If access-list have been set, schedule update timer. */
937: if (DISTRIBUTE_LIST (ospf, type))
938: ospf_distribute_list_update (ospf, type);
939:
940: return CMD_SUCCESS;
941: }
942:
943: int
944: ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name)
945: {
946: /* Schedule update timer. */
947: if (DISTRIBUTE_LIST (ospf, type))
948: ospf_distribute_list_update (ospf, type);
949:
950: /* Unset distribute-list. */
951: DISTRIBUTE_LIST (ospf, type) = NULL;
952:
953: /* Clear distribute-name. */
954: if (DISTRIBUTE_NAME (ospf, type))
955: free (DISTRIBUTE_NAME (ospf, type));
956:
957: DISTRIBUTE_NAME (ospf, type) = NULL;
958:
959: return CMD_SUCCESS;
960: }
961:
962: /* distribute-list update timer. */
963: static int
964: ospf_distribute_list_update_timer (struct thread *thread)
965: {
966: struct route_node *rn;
967: struct external_info *ei;
968: struct route_table *rt;
969: struct ospf_lsa *lsa;
970: int type, default_refresh = 0;
971: struct ospf *ospf;
972:
973: ospf = ospf_lookup ();
974: if (ospf == NULL)
975: return 0;
976:
977: ospf->t_distribute_update = NULL;
978:
979: zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
980:
981: /* foreach all external info. */
982: for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
983: {
984: rt = EXTERNAL_INFO (type);
985: if (!rt)
986: continue;
987: for (rn = route_top (rt); rn; rn = route_next (rn))
988: if ((ei = rn->info) != NULL)
989: {
990: if (is_prefix_default (&ei->p))
991: default_refresh = 1;
992: else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
993: ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
994: else
995: ospf_external_lsa_originate (ospf, ei);
996: }
997: }
998: if (default_refresh)
999: ospf_external_lsa_refresh_default (ospf);
1000: return 0;
1001: }
1002:
1003: #define OSPF_DISTRIBUTE_UPDATE_DELAY 5
1004:
1005: /* Update distribute-list and set timer to apply access-list. */
1006: void
1.1.1.3 ! misho 1007: ospf_distribute_list_update (struct ospf *ospf, uintptr_t type)
1.1 misho 1008: {
1009: struct route_table *rt;
1010:
1011: /* External info does not exist. */
1012: if (!(rt = EXTERNAL_INFO (type)))
1013: return;
1014:
1015: /* If exists previously invoked thread, then let it continue. */
1016: if (ospf->t_distribute_update)
1017: return;
1018:
1019: /* Set timer. */
1020: ospf->t_distribute_update =
1021: thread_add_timer (master, ospf_distribute_list_update_timer,
1022: (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
1023: }
1024:
1025: /* If access-list is updated, apply some check. */
1026: static void
1027: ospf_filter_update (struct access_list *access)
1028: {
1029: struct ospf *ospf;
1030: int type;
1031: int abr_inv = 0;
1032: struct ospf_area *area;
1033: struct listnode *node;
1034:
1035: /* If OSPF instatnce does not exist, return right now. */
1036: ospf = ospf_lookup ();
1037: if (ospf == NULL)
1038: return;
1039:
1040: /* Update distribute-list, and apply filter. */
1041: for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
1042: {
1043: if (ROUTEMAP (ospf, type) != NULL)
1044: {
1045: /* if route-map is not NULL it may be using this access list */
1046: ospf_distribute_list_update (ospf, type);
1047: continue;
1048: }
1049:
1050: /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX),
1051: * but no distribute list. */
1052: if (type == ZEBRA_ROUTE_MAX)
1053: break;
1054:
1055: if (DISTRIBUTE_NAME (ospf, type))
1056: {
1057: /* Keep old access-list for distribute-list. */
1058: struct access_list *old = DISTRIBUTE_LIST (ospf, type);
1059:
1060: /* Update access-list for distribute-list. */
1061: DISTRIBUTE_LIST (ospf, type) =
1062: access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type));
1063:
1064: /* No update for this distribute type. */
1065: if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL)
1066: continue;
1067:
1068: /* Schedule distribute-list update timer. */
1069: if (DISTRIBUTE_LIST (ospf, type) == NULL ||
1070: strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
1071: ospf_distribute_list_update (ospf, type);
1072: }
1073: }
1074:
1075: /* Update Area access-list. */
1076: for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1077: {
1078: if (EXPORT_NAME (area))
1079: {
1080: EXPORT_LIST (area) = NULL;
1081: abr_inv++;
1082: }
1083:
1084: if (IMPORT_NAME (area))
1085: {
1086: IMPORT_LIST (area) = NULL;
1087: abr_inv++;
1088: }
1089: }
1090:
1091: /* Schedule ABR tasks -- this will be changed -- takada. */
1092: if (IS_OSPF_ABR (ospf) && abr_inv)
1093: ospf_schedule_abr_task (ospf);
1094: }
1095:
1096: /* If prefix-list is updated, do some updates. */
1097: void
1098: ospf_prefix_list_update (struct prefix_list *plist)
1099: {
1100: struct ospf *ospf;
1101: int type;
1102: int abr_inv = 0;
1103: struct ospf_area *area;
1104: struct listnode *node;
1105:
1106: /* If OSPF instatnce does not exist, return right now. */
1107: ospf = ospf_lookup ();
1108: if (ospf == NULL)
1109: return;
1110:
1111: /* Update all route-maps which are used as redistribution filters.
1112: * They might use prefix-list.
1113: */
1114: for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
1115: {
1116: if (ROUTEMAP (ospf, type) != NULL)
1117: {
1118: /* If route-map is not NULL it may be using this prefix list */
1119: ospf_distribute_list_update (ospf, type);
1120: continue;
1121: }
1122: }
1123:
1124: /* Update area filter-lists. */
1125: for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
1126: {
1127: /* Update filter-list in. */
1128: if (PREFIX_NAME_IN (area))
1129: if (strcmp (PREFIX_NAME_IN (area), plist->name) == 0)
1130: {
1131: PREFIX_LIST_IN (area) =
1132: prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
1133: abr_inv++;
1134: }
1135:
1136: /* Update filter-list out. */
1137: if (PREFIX_NAME_OUT (area))
1138: if (strcmp (PREFIX_NAME_OUT (area), plist->name) == 0)
1139: {
1140: PREFIX_LIST_IN (area) =
1141: prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
1142: abr_inv++;
1143: }
1144: }
1145:
1146: /* Schedule ABR task. */
1147: if (IS_OSPF_ABR (ospf) && abr_inv)
1148: ospf_schedule_abr_task (ospf);
1149: }
1150:
1151: static struct ospf_distance *
1152: ospf_distance_new (void)
1153: {
1154: return XCALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
1155: }
1156:
1157: static void
1158: ospf_distance_free (struct ospf_distance *odistance)
1159: {
1160: XFREE (MTYPE_OSPF_DISTANCE, odistance);
1161: }
1162:
1163: int
1164: ospf_distance_set (struct vty *vty, struct ospf *ospf,
1165: const char *distance_str,
1166: const char *ip_str,
1167: const char *access_list_str)
1168: {
1169: int ret;
1170: struct prefix_ipv4 p;
1171: u_char distance;
1172: struct route_node *rn;
1173: struct ospf_distance *odistance;
1174:
1175: ret = str2prefix_ipv4 (ip_str, &p);
1176: if (ret == 0)
1177: {
1178: vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1179: return CMD_WARNING;
1180: }
1181:
1182: distance = atoi (distance_str);
1183:
1184: /* Get OSPF distance node. */
1185: rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
1186: if (rn->info)
1187: {
1188: odistance = rn->info;
1189: route_unlock_node (rn);
1190: }
1191: else
1192: {
1193: odistance = ospf_distance_new ();
1194: rn->info = odistance;
1195: }
1196:
1197: /* Set distance value. */
1198: odistance->distance = distance;
1199:
1200: /* Reset access-list configuration. */
1201: if (odistance->access_list)
1202: {
1203: free (odistance->access_list);
1204: odistance->access_list = NULL;
1205: }
1206: if (access_list_str)
1207: odistance->access_list = strdup (access_list_str);
1208:
1209: return CMD_SUCCESS;
1210: }
1211:
1212: int
1213: ospf_distance_unset (struct vty *vty, struct ospf *ospf,
1214: const char *distance_str,
1215: const char *ip_str, char
1216: const *access_list_str)
1217: {
1218: int ret;
1219: struct prefix_ipv4 p;
1220: struct route_node *rn;
1221: struct ospf_distance *odistance;
1222:
1223: ret = str2prefix_ipv4 (ip_str, &p);
1224: if (ret == 0)
1225: {
1226: vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
1227: return CMD_WARNING;
1228: }
1229:
1230: rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p);
1231: if (!rn)
1232: {
1233: vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
1234: return CMD_WARNING;
1235: }
1236:
1237: odistance = rn->info;
1238:
1239: if (odistance->access_list)
1240: free (odistance->access_list);
1241: ospf_distance_free (odistance);
1242:
1243: rn->info = NULL;
1244: route_unlock_node (rn);
1245: route_unlock_node (rn);
1246:
1247: return CMD_SUCCESS;
1248: }
1249:
1250: void
1251: ospf_distance_reset (struct ospf *ospf)
1252: {
1253: struct route_node *rn;
1254: struct ospf_distance *odistance;
1255:
1256: for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
1257: if ((odistance = rn->info) != NULL)
1258: {
1259: if (odistance->access_list)
1260: free (odistance->access_list);
1261: ospf_distance_free (odistance);
1262: rn->info = NULL;
1263: route_unlock_node (rn);
1264: }
1265: }
1266:
1267: u_char
1268: ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
1269: {
1270: struct ospf *ospf;
1271:
1272: ospf = ospf_lookup ();
1273: if (ospf == NULL)
1274: return 0;
1275:
1276: if (ospf->distance_intra)
1277: if (or->path_type == OSPF_PATH_INTRA_AREA)
1278: return ospf->distance_intra;
1279:
1280: if (ospf->distance_inter)
1281: if (or->path_type == OSPF_PATH_INTER_AREA)
1282: return ospf->distance_inter;
1283:
1284: if (ospf->distance_external)
1285: if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
1286: || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
1287: return ospf->distance_external;
1288:
1289: if (ospf->distance_all)
1290: return ospf->distance_all;
1291:
1292: return 0;
1293: }
1294:
1295: void
1296: ospf_zebra_init ()
1297: {
1298: /* Allocate zebra structure. */
1299: zclient = zclient_new ();
1300: zclient_init (zclient, ZEBRA_ROUTE_OSPF);
1301: zclient->router_id_update = ospf_router_id_update_zebra;
1302: zclient->interface_add = ospf_interface_add;
1303: zclient->interface_delete = ospf_interface_delete;
1304: zclient->interface_up = ospf_interface_state_up;
1305: zclient->interface_down = ospf_interface_state_down;
1306: zclient->interface_address_add = ospf_interface_address_add;
1307: zclient->interface_address_delete = ospf_interface_address_delete;
1308: zclient->ipv4_route_add = ospf_zebra_read_ipv4;
1309: zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
1310:
1311: access_list_add_hook (ospf_filter_update);
1312: access_list_delete_hook (ospf_filter_update);
1313: prefix_list_add_hook (ospf_prefix_list_update);
1314: prefix_list_delete_hook (ospf_prefix_list_update);
1315: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>