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