+ note the meta-queue in NEWS
[jleu-quagga.git] / isisd / isis_zebra.c
blob9ee5ffc5d22ea07a8cc5cdfab13c1114f0820a13
1 /*
2 * IS-IS Rout(e)ing protocol - isis_zebra.c
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
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.
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.
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.
23 #include <zebra.h>
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"
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"
45 struct zclient *zclient = NULL;
47 extern struct thread_master *master;
48 extern struct isis *isis;
50 struct in_addr router_id_zebra;
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)
57 struct prefix router_id;
59 zebra_router_id_update_read (zclient->ibuf,&router_id);
60 router_id_zebra = router_id.u.prefix4;
62 /* FIXME: Do we react somehow? */
63 return 0;
66 static int
67 isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
69 struct interface *ifp;
71 ifp = zebra_interface_add_read (zclient->ibuf);
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);
77 if (if_is_operative (ifp))
78 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
80 return 0;
83 static int
84 isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
86 struct interface *ifp;
87 struct stream *s;
89 s = zclient->ibuf;
90 ifp = zebra_interface_state_read (s);
92 if (!ifp)
93 return 0;
95 if (if_is_operative (ifp))
96 zlog_warn ("Zebra: got delete of %s, but interface is still up",
97 ifp->name);
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);
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);
108 isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
110 ifp->ifindex = IFINDEX_INTERNAL;
112 return 0;
115 static struct interface *
116 zebra_interface_if_lookup (struct stream *s)
118 char ifname_tmp[INTERFACE_NAMSIZ];
120 /* Read interface name. */
121 stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
123 /* And look it up. */
124 return if_lookup_by_name_len(ifname_tmp,
125 strnlen(ifname_tmp, INTERFACE_NAMSIZ));
128 static int
129 isis_zebra_if_state_up (int command, struct zclient *zclient,
130 zebra_size_t length)
132 struct interface *ifp;
134 ifp = zebra_interface_if_lookup (zclient->ibuf);
136 if (!ifp)
137 return 0;
139 if (if_is_operative (ifp))
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;
149 zebra_interface_if_set_value (zclient->ibuf, ifp);
150 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
152 return 0;
155 static int
156 isis_zebra_if_state_down (int command, struct zclient *zclient,
157 zebra_size_t length)
159 struct interface *ifp;
161 ifp = zebra_interface_if_lookup (zclient->ibuf);
163 if (ifp == NULL)
164 return 0;
166 if (if_is_operative (ifp))
168 zebra_interface_if_set_value (zclient->ibuf, ifp);
169 isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
172 return 0;
175 static int
176 isis_zebra_if_address_add (int command, struct zclient *zclient,
177 zebra_size_t length)
179 struct connected *c;
180 struct prefix *p;
181 char buf[BUFSIZ];
183 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
184 zclient->ibuf);
186 if (c == NULL)
187 return 0;
189 p = c->address;
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);
203 return 0;
206 static int
207 isis_zebra_if_address_del (int command, struct zclient *client,
208 zebra_size_t length)
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 */
217 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
218 zclient->ibuf);
220 if (c == NULL)
221 return 0;
223 ifp = c->ifp;
225 #ifdef EXTREME_DEBUG
226 p = c->address;
227 prefix2str (p, buf, BUFSIZ);
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 */
237 if (if_is_operative (ifp))
238 isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
239 connected_free (c);
241 return 0;
244 static void
245 isis_zebra_route_add_ipv4 (struct prefix *prefix,
246 struct isis_route_info *route_info)
248 u_char message, flags;
249 int psize;
250 struct stream *stream;
251 struct isis_nexthop *nexthop;
252 struct listnode *node;
254 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
255 return;
257 if (zclient->redist[ZEBRA_ROUTE_ISIS])
259 message = 0;
260 flags = 0;
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
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);
282 stream_putc (stream, listcount (route_info->nexthops));
284 /* Nexthop, ifindex, distance and metric information */
285 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
287 /* FIXME: can it be ? */
288 if (nexthop->ip.s_addr != INADDR_ANY)
290 stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
291 stream_put_in_addr (stream, &nexthop->ip);
293 else
295 stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
296 stream_putl (stream, nexthop->ifindex);
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);
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);
312 static void
313 isis_zebra_route_del_ipv4 (struct prefix *prefix,
314 struct isis_route_info *route_info)
316 struct zapi_ipv4 api;
317 struct prefix_ipv4 prefix4;
319 if (zclient->redist[ZEBRA_ROUTE_ISIS])
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);
329 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
331 return;
334 #ifdef HAVE_IPV6
335 void
336 isis_zebra_route_add_ipv6 (struct prefix *prefix,
337 struct isis_route_info *route_info)
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;
347 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
348 return;
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);
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)
369 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
370 return;
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)
378 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
379 XFREE (MTYPE_ISIS_TMP, nexthop_list);
380 return;
383 /* for each nexthop */
384 i = 0;
385 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
387 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
388 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
390 api.nexthop_num--;
391 api.ifindex_num--;
392 continue;
395 nexthop_list[i] = &nexthop6->ip6;
396 ifindex_list[i] = nexthop6->ifindex;
397 i++;
400 api.nexthop = nexthop_list;
401 api.ifindex = ifindex_list;
403 if (api.nexthop_num && api.ifindex_num)
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);
412 XFREE (MTYPE_ISIS_TMP, nexthop_list);
413 XFREE (MTYPE_ISIS_TMP, ifindex_list);
415 return;
418 static void
419 isis_zebra_route_del_ipv6 (struct prefix *prefix,
420 struct isis_route_info *route_info)
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;
430 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
431 return;
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);
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)
446 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
447 return;
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)
455 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
456 XFREE (MTYPE_ISIS_TMP, nexthop_list);
457 return;
460 /* for each nexthop */
461 i = 0;
462 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
464 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
465 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
467 api.nexthop_num--;
468 api.ifindex_num--;
469 continue;
472 nexthop_list[i] = &nexthop6->ip6;
473 ifindex_list[i] = nexthop6->ifindex;
474 i++;
477 api.nexthop = nexthop_list;
478 api.ifindex = ifindex_list;
480 if (api.nexthop_num && api.ifindex_num)
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);
489 XFREE (MTYPE_ISIS_TMP, nexthop_list);
490 XFREE (MTYPE_ISIS_TMP, ifindex_list);
493 #endif /* HAVE_IPV6 */
495 void
496 isis_zebra_route_update (struct prefix *prefix,
497 struct isis_route_info *route_info)
499 if (zclient->sock < 0)
500 return;
502 if (!zclient->redist[ZEBRA_ROUTE_ISIS])
503 return;
505 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
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 */
514 else
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 */
523 return;
526 static int
527 isis_zebra_read_ipv4 (int command, struct zclient *zclient,
528 zebra_size_t length)
530 struct stream *stream;
531 struct zapi_ipv4 api;
532 struct prefix_ipv4 p;
533 unsigned long ifindex;
534 struct in_addr nexthop;
536 stream = zclient->ibuf;
537 memset (&p, 0, sizeof (struct prefix_ipv4));
538 ifindex = 0;
540 api.type = stream_getc (stream);
541 api.flags = stream_getc (stream);
542 api.message = stream_getc (stream);
544 p.family = AF_INET;
545 p.prefixlen = stream_getc (stream);
546 stream_get (&p.prefix, stream, PSIZE (p.prefixlen));
548 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
550 api.nexthop_num = stream_getc (stream);
551 nexthop.s_addr = stream_get_ipv4 (stream);
553 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
555 api.ifindex_num = stream_getc (stream);
556 ifindex = stream_getl (stream);
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;
565 if (command == ZEBRA_IPV4_ROUTE_ADD)
567 if (isis->debugs & DEBUG_ZEBRA)
568 zlog_debug ("IPv4 Route add from Z");
571 return 0;
574 #ifdef HAVE_IPV6
575 static int
576 isis_zebra_read_ipv6 (int command, struct zclient *zclient,
577 zebra_size_t length)
579 return 0;
581 #endif
583 #define ISIS_TYPE_IS_REDISTRIBUTED(T) \
584 T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
587 isis_distribute_list_update (int routetype)
589 return 0;
592 #if 0 /* Not yet. */
593 static int
594 isis_redistribute_default_set (int routetype, int metric_type,
595 int metric_value)
597 return 0;
599 #endif /* 0 */
601 void
602 isis_zebra_init ()
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 */
620 return;