1: /*
2: * IS-IS Rout(e)ing protocol - isis_zebra.c
3: *
4: * Copyright (C) 2001,2002 Sampo Saaristo
5: * Tampere University of Technology
6: * Institute of Communications Engineering
7: *
8: * This program is free software; you can redistribute it and/or modify it
9: * under the terms of the GNU General Public Licenseas published by the Free
10: * Software Foundation; either version 2 of the License, or (at your option)
11: * any later version.
12: *
13: * This program is distributed in the hope that it will be useful,but WITHOUT
14: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16: * more details.
17:
18: * You should have received a copy of the GNU General Public License along
19: * with this program; if not, write to the Free Software Foundation, Inc.,
20: * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21: */
22:
23: #include <zebra.h>
24:
25: #include "thread.h"
26: #include "command.h"
27: #include "memory.h"
28: #include "log.h"
29: #include "if.h"
30: #include "network.h"
31: #include "prefix.h"
32: #include "zclient.h"
33: #include "stream.h"
34: #include "linklist.h"
35:
36: #include "isisd/dict.h"
37: #include "isisd/isis_constants.h"
38: #include "isisd/isis_common.h"
39: #include "isisd/isis_flags.h"
40: #include "isisd/isis_misc.h"
41: #include "isisd/isis_circuit.h"
42: #include "isisd/isis_tlv.h"
43: #include "isisd/isisd.h"
44: #include "isisd/isis_circuit.h"
45: #include "isisd/isis_csm.h"
46: #include "isisd/isis_lsp.h"
47: #include "isisd/isis_route.h"
48: #include "isisd/isis_zebra.h"
49:
50: struct zclient *zclient = NULL;
51:
52: /* Router-id update message from zebra. */
53: static int
54: isis_router_id_update_zebra (int command, struct zclient *zclient,
55: zebra_size_t length)
56: {
57: struct isis_area *area;
58: struct listnode *node;
59: struct prefix router_id;
60:
61: zebra_router_id_update_read (zclient->ibuf, &router_id);
62: if (isis->router_id == router_id.u.prefix4.s_addr)
63: return 0;
64:
65: isis->router_id = router_id.u.prefix4.s_addr;
66: for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
67: if (listcount (area->area_addrs) > 0)
68: lsp_regenerate_schedule (area, area->is_type, 0);
69:
70: return 0;
71: }
72:
73: static int
74: isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
75: {
76: struct interface *ifp;
77:
78: ifp = zebra_interface_add_read (zclient->ibuf);
79:
80: if (isis->debugs & DEBUG_ZEBRA)
81: zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
82: ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
83:
84: if (if_is_operative (ifp))
85: isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
86:
87: return 0;
88: }
89:
90: static int
91: isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
92: {
93: struct interface *ifp;
94: struct stream *s;
95:
96: s = zclient->ibuf;
97: ifp = zebra_interface_state_read (s);
98:
99: if (!ifp)
100: return 0;
101:
102: if (if_is_operative (ifp))
103: zlog_warn ("Zebra: got delete of %s, but interface is still up",
104: ifp->name);
105:
106: if (isis->debugs & DEBUG_ZEBRA)
107: zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
108: ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
109:
110: isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
111:
112: /* Cannot call if_delete because we should retain the pseudo interface
113: in case there is configuration info attached to it. */
114: if_delete_retain(ifp);
115:
116: ifp->ifindex = IFINDEX_INTERNAL;
117:
118: return 0;
119: }
120:
121: static int
122: isis_zebra_if_state_up (int command, struct zclient *zclient,
123: zebra_size_t length)
124: {
125: struct interface *ifp;
126:
127: ifp = zebra_interface_state_read (zclient->ibuf);
128:
129: if (ifp == NULL)
130: return 0;
131:
132: isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
133:
134: return 0;
135: }
136:
137: static int
138: isis_zebra_if_state_down (int command, struct zclient *zclient,
139: zebra_size_t length)
140: {
141: struct interface *ifp;
142: struct isis_circuit *circuit;
143:
144: ifp = zebra_interface_state_read (zclient->ibuf);
145:
146: if (ifp == NULL)
147: return 0;
148:
149: circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
150: ifp);
151: if (circuit)
152: SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
153:
154: return 0;
155: }
156:
157: static int
158: isis_zebra_if_address_add (int command, struct zclient *zclient,
159: zebra_size_t length)
160: {
161: struct connected *c;
162: struct prefix *p;
163: char buf[BUFSIZ];
164:
165: c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
166: zclient->ibuf);
167:
168: if (c == NULL)
169: return 0;
170:
171: p = c->address;
172:
173: prefix2str (p, buf, BUFSIZ);
174: #ifdef EXTREME_DEBUG
175: if (p->family == AF_INET)
176: zlog_debug ("connected IP address %s", buf);
177: #ifdef HAVE_IPV6
178: if (p->family == AF_INET6)
179: zlog_debug ("connected IPv6 address %s", buf);
180: #endif /* HAVE_IPV6 */
181: #endif /* EXTREME_DEBUG */
182: if (if_is_operative (c->ifp))
183: isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
184:
185: return 0;
186: }
187:
188: static int
189: isis_zebra_if_address_del (int command, struct zclient *client,
190: zebra_size_t length)
191: {
192: struct connected *c;
193: struct interface *ifp;
194: #ifdef EXTREME_DEBUG
195: struct prefix *p;
196: u_char buf[BUFSIZ];
197: #endif /* EXTREME_DEBUG */
198:
199: c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
200: zclient->ibuf);
201:
202: if (c == NULL)
203: return 0;
204:
205: ifp = c->ifp;
206:
207: #ifdef EXTREME_DEBUG
208: p = c->address;
209: prefix2str (p, buf, BUFSIZ);
210:
211: if (p->family == AF_INET)
212: zlog_debug ("disconnected IP address %s", buf);
213: #ifdef HAVE_IPV6
214: if (p->family == AF_INET6)
215: zlog_debug ("disconnected IPv6 address %s", buf);
216: #endif /* HAVE_IPV6 */
217: #endif /* EXTREME_DEBUG */
218:
219: if (if_is_operative (ifp))
220: isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
221: connected_free (c);
222:
223: return 0;
224: }
225:
226: static void
227: isis_zebra_route_add_ipv4 (struct prefix *prefix,
228: struct isis_route_info *route_info)
229: {
230: u_char message, flags;
231: int psize;
232: struct stream *stream;
233: struct isis_nexthop *nexthop;
234: struct listnode *node;
235:
236: if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
237: return;
238:
239: if (zclient->redist[ZEBRA_ROUTE_ISIS])
240: {
241: message = 0;
242: flags = 0;
243:
244: SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
245: SET_FLAG (message, ZAPI_MESSAGE_METRIC);
246: #if 0
247: SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
248: #endif
249:
250: stream = zclient->obuf;
251: stream_reset (stream);
252: zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD);
253: /* type */
254: stream_putc (stream, ZEBRA_ROUTE_ISIS);
255: /* flags */
256: stream_putc (stream, flags);
257: /* message */
258: stream_putc (stream, message);
259: /* SAFI */
260: stream_putw (stream, SAFI_UNICAST);
261: /* prefix information */
262: psize = PSIZE (prefix->prefixlen);
263: stream_putc (stream, prefix->prefixlen);
264: stream_write (stream, (u_char *) & prefix->u.prefix4, psize);
265:
266: stream_putc (stream, listcount (route_info->nexthops));
267:
268: /* Nexthop, ifindex, distance and metric information */
269: for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
270: {
271: /* FIXME: can it be ? */
272: if (nexthop->ip.s_addr != INADDR_ANY)
273: {
274: stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
275: stream_put_in_addr (stream, &nexthop->ip);
276: }
277: else
278: {
279: stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
280: stream_putl (stream, nexthop->ifindex);
281: }
282: }
283: #if 0
284: if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
285: stream_putc (stream, route_info->depth);
286: #endif
287: if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
288: stream_putl (stream, route_info->cost);
289:
290: stream_putw_at (stream, 0, stream_get_endp (stream));
291: zclient_send_message(zclient);
292: SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
293: UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
294: }
295: }
296:
297: static void
298: isis_zebra_route_del_ipv4 (struct prefix *prefix,
299: struct isis_route_info *route_info)
300: {
301: struct zapi_ipv4 api;
302: struct prefix_ipv4 prefix4;
303:
304: if (zclient->redist[ZEBRA_ROUTE_ISIS])
305: {
306: api.type = ZEBRA_ROUTE_ISIS;
307: api.flags = 0;
308: api.message = 0;
309: api.safi = SAFI_UNICAST;
310: prefix4.family = AF_INET;
311: prefix4.prefixlen = prefix->prefixlen;
312: prefix4.prefix = prefix->u.prefix4;
313: zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
314: }
315: UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
316:
317: return;
318: }
319:
320: #ifdef HAVE_IPV6
321: void
322: isis_zebra_route_add_ipv6 (struct prefix *prefix,
323: struct isis_route_info *route_info)
324: {
325: struct zapi_ipv6 api;
326: struct in6_addr **nexthop_list;
327: unsigned int *ifindex_list;
328: struct isis_nexthop6 *nexthop6;
329: int i, size;
330: struct listnode *node;
331: struct prefix_ipv6 prefix6;
332:
333: if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
334: return;
335:
336: api.type = ZEBRA_ROUTE_ISIS;
337: api.flags = 0;
338: api.message = 0;
339: api.safi = SAFI_UNICAST;
340: SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
341: SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
342: SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
343: api.metric = route_info->cost;
344: #if 0
345: SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
346: api.distance = route_info->depth;
347: #endif
348: api.nexthop_num = listcount (route_info->nexthops6);
349: api.ifindex_num = listcount (route_info->nexthops6);
350:
351: /* allocate memory for nexthop_list */
352: size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
353: nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
354: if (!nexthop_list)
355: {
356: zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
357: return;
358: }
359:
360: /* allocate memory for ifindex_list */
361: size = sizeof (unsigned int) * listcount (route_info->nexthops6);
362: ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
363: if (!ifindex_list)
364: {
365: zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
366: XFREE (MTYPE_ISIS_TMP, nexthop_list);
367: return;
368: }
369:
370: /* for each nexthop */
371: i = 0;
372: for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
373: {
374: if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
375: !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
376: {
377: api.nexthop_num--;
378: api.ifindex_num--;
379: continue;
380: }
381:
382: nexthop_list[i] = &nexthop6->ip6;
383: ifindex_list[i] = nexthop6->ifindex;
384: i++;
385: }
386:
387: api.nexthop = nexthop_list;
388: api.ifindex = ifindex_list;
389:
390: if (api.nexthop_num && api.ifindex_num)
391: {
392: prefix6.family = AF_INET6;
393: prefix6.prefixlen = prefix->prefixlen;
394: memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
395: zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
396: SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
397: UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
398: }
399:
400: XFREE (MTYPE_ISIS_TMP, nexthop_list);
401: XFREE (MTYPE_ISIS_TMP, ifindex_list);
402:
403: return;
404: }
405:
406: static void
407: isis_zebra_route_del_ipv6 (struct prefix *prefix,
408: struct isis_route_info *route_info)
409: {
410: struct zapi_ipv6 api;
411: struct in6_addr **nexthop_list;
412: unsigned int *ifindex_list;
413: struct isis_nexthop6 *nexthop6;
414: int i, size;
415: struct listnode *node;
416: struct prefix_ipv6 prefix6;
417:
418: if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
419: return;
420:
421: api.type = ZEBRA_ROUTE_ISIS;
422: api.flags = 0;
423: api.message = 0;
424: api.safi = SAFI_UNICAST;
425: SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
426: SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
427: api.nexthop_num = listcount (route_info->nexthops6);
428: api.ifindex_num = listcount (route_info->nexthops6);
429:
430: /* allocate memory for nexthop_list */
431: size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
432: nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
433: if (!nexthop_list)
434: {
435: zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
436: return;
437: }
438:
439: /* allocate memory for ifindex_list */
440: size = sizeof (unsigned int) * listcount (route_info->nexthops6);
441: ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
442: if (!ifindex_list)
443: {
444: zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
445: XFREE (MTYPE_ISIS_TMP, nexthop_list);
446: return;
447: }
448:
449: /* for each nexthop */
450: i = 0;
451: for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
452: {
453: if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
454: !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
455: {
456: api.nexthop_num--;
457: api.ifindex_num--;
458: continue;
459: }
460:
461: nexthop_list[i] = &nexthop6->ip6;
462: ifindex_list[i] = nexthop6->ifindex;
463: i++;
464: }
465:
466: api.nexthop = nexthop_list;
467: api.ifindex = ifindex_list;
468:
469: if (api.nexthop_num && api.ifindex_num)
470: {
471: prefix6.family = AF_INET6;
472: prefix6.prefixlen = prefix->prefixlen;
473: memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
474: zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
475: UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
476: }
477:
478: XFREE (MTYPE_ISIS_TMP, nexthop_list);
479: XFREE (MTYPE_ISIS_TMP, ifindex_list);
480: }
481:
482: #endif /* HAVE_IPV6 */
483:
484: void
485: isis_zebra_route_update (struct prefix *prefix,
486: struct isis_route_info *route_info)
487: {
488: if (zclient->sock < 0)
489: return;
490:
491: if (!zclient->redist[ZEBRA_ROUTE_ISIS])
492: return;
493:
494: if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
495: {
496: if (prefix->family == AF_INET)
497: isis_zebra_route_add_ipv4 (prefix, route_info);
498: #ifdef HAVE_IPV6
499: else if (prefix->family == AF_INET6)
500: isis_zebra_route_add_ipv6 (prefix, route_info);
501: #endif /* HAVE_IPV6 */
502: }
503: else
504: {
505: if (prefix->family == AF_INET)
506: isis_zebra_route_del_ipv4 (prefix, route_info);
507: #ifdef HAVE_IPV6
508: else if (prefix->family == AF_INET6)
509: isis_zebra_route_del_ipv6 (prefix, route_info);
510: #endif /* HAVE_IPV6 */
511: }
512: return;
513: }
514:
515: static int
516: isis_zebra_read_ipv4 (int command, struct zclient *zclient,
517: zebra_size_t length)
518: {
519: struct stream *stream;
520: struct zapi_ipv4 api;
521: struct prefix_ipv4 p;
522: unsigned long ifindex;
523: struct in_addr nexthop;
524:
525: stream = zclient->ibuf;
526: memset (&p, 0, sizeof (struct prefix_ipv4));
527: ifindex = 0;
528:
529: api.type = stream_getc (stream);
530: api.flags = stream_getc (stream);
531: api.message = stream_getc (stream);
532:
533: p.family = AF_INET;
534: p.prefixlen = stream_getc (stream);
535: stream_get (&p.prefix, stream, PSIZE (p.prefixlen));
536:
537: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
538: {
539: api.nexthop_num = stream_getc (stream);
540: nexthop.s_addr = stream_get_ipv4 (stream);
541: }
542: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
543: {
544: api.ifindex_num = stream_getc (stream);
545: ifindex = stream_getl (stream);
546: }
547: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
548: api.distance = stream_getc (stream);
549: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
550: api.metric = stream_getl (stream);
551: else
552: api.metric = 0;
553:
554: if (command == ZEBRA_IPV4_ROUTE_ADD)
555: {
556: if (isis->debugs & DEBUG_ZEBRA)
557: zlog_debug ("IPv4 Route add from Z");
558: }
559:
560: return 0;
561: }
562:
563: #ifdef HAVE_IPV6
564: static int
565: isis_zebra_read_ipv6 (int command, struct zclient *zclient,
566: zebra_size_t length)
567: {
568: return 0;
569: }
570: #endif
571:
572: #define ISIS_TYPE_IS_REDISTRIBUTED(T) \
573: T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
574:
575: int
576: isis_distribute_list_update (int routetype)
577: {
578: return 0;
579: }
580:
581: #if 0 /* Not yet. */
582: static int
583: isis_redistribute_default_set (int routetype, int metric_type,
584: int metric_value)
585: {
586: return 0;
587: }
588: #endif /* 0 */
589:
590: void
591: isis_zebra_init ()
592: {
593: zclient = zclient_new ();
594: zclient_init (zclient, ZEBRA_ROUTE_ISIS);
595: zclient->router_id_update = isis_router_id_update_zebra;
596: zclient->interface_add = isis_zebra_if_add;
597: zclient->interface_delete = isis_zebra_if_del;
598: zclient->interface_up = isis_zebra_if_state_up;
599: zclient->interface_down = isis_zebra_if_state_down;
600: zclient->interface_address_add = isis_zebra_if_address_add;
601: zclient->interface_address_delete = isis_zebra_if_address_del;
602: zclient->ipv4_route_add = isis_zebra_read_ipv4;
603: zclient->ipv4_route_delete = isis_zebra_read_ipv4;
604: #ifdef HAVE_IPV6
605: zclient->ipv6_route_add = isis_zebra_read_ipv6;
606: zclient->ipv6_route_delete = isis_zebra_read_ipv6;
607: #endif /* HAVE_IPV6 */
608:
609: return;
610: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>