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