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