1: /*
2: * RIPngd and zebra interface.
3: * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4: *
5: * This file is part of GNU Zebra.
6: *
7: * GNU Zebra is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2, or (at your option) any
10: * later version.
11: *
12: * GNU Zebra is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with GNU Zebra; see the file COPYING. If not, write to the Free
19: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20: * 02111-1307, USA.
21: */
22:
23: #include <zebra.h>
24:
25: #include "command.h"
26: #include "prefix.h"
27: #include "stream.h"
28: #include "routemap.h"
29: #include "zclient.h"
30: #include "log.h"
31:
32: #include "ripngd/ripngd.h"
33:
34: /* All information about zebra. */
35: struct zclient *zclient = NULL;
36:
37: /* Callback prototypes for zebra client service. */
38: int ripng_interface_up (int, struct zclient *, zebra_size_t);
39: int ripng_interface_down (int, struct zclient *, zebra_size_t);
40: int ripng_interface_add (int, struct zclient *, zebra_size_t);
41: int ripng_interface_delete (int, struct zclient *, zebra_size_t);
42: int ripng_interface_address_add (int, struct zclient *, zebra_size_t);
43: int ripng_interface_address_delete (int, struct zclient *, zebra_size_t);
44:
45: void
46: ripng_zebra_ipv6_add (struct prefix_ipv6 *p, struct in6_addr *nexthop,
47: unsigned int ifindex, u_char metric)
48: {
49: struct zapi_ipv6 api;
50:
51: if (zclient->redist[ZEBRA_ROUTE_RIPNG])
52: {
53: api.type = ZEBRA_ROUTE_RIPNG;
54: api.flags = 0;
55: api.message = 0;
56: api.safi = SAFI_UNICAST;
57: SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
58: api.nexthop_num = 1;
59: api.nexthop = &nexthop;
60: SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
61: api.ifindex_num = 1;
62: api.ifindex = &ifindex;
63: SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
64: api.metric = metric;
65:
66: zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, p, &api);
67: }
68: }
69:
70: void
71: ripng_zebra_ipv6_delete (struct prefix_ipv6 *p, struct in6_addr *nexthop,
72: unsigned int ifindex)
73: {
74: struct zapi_ipv6 api;
75:
76: if (zclient->redist[ZEBRA_ROUTE_RIPNG])
77: {
78: api.type = ZEBRA_ROUTE_RIPNG;
79: api.flags = 0;
80: api.message = 0;
81: api.safi = SAFI_UNICAST;
82: SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
83: api.nexthop_num = 1;
84: api.nexthop = &nexthop;
85: SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
86: api.ifindex_num = 1;
87: api.ifindex = &ifindex;
88:
89: zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, p, &api);
90: }
91: }
92:
93: /* Zebra route add and delete treatment. */
94: static int
95: ripng_zebra_read_ipv6 (int command, struct zclient *zclient,
96: zebra_size_t length)
97: {
98: struct stream *s;
99: struct zapi_ipv6 api;
100: unsigned long ifindex;
101: struct in6_addr nexthop;
102: struct prefix_ipv6 p;
103:
104: s = zclient->ibuf;
105: ifindex = 0;
106: memset (&nexthop, 0, sizeof (struct in6_addr));
107:
108: /* Type, flags, message. */
109: api.type = stream_getc (s);
110: api.flags = stream_getc (s);
111: api.message = stream_getc (s);
112:
113: /* IPv6 prefix. */
114: memset (&p, 0, sizeof (struct prefix_ipv6));
115: p.family = AF_INET6;
116: p.prefixlen = stream_getc (s);
117: stream_get (&p.prefix, s, PSIZE (p.prefixlen));
118:
119: /* Nexthop, ifindex, distance, metric. */
120: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
121: {
122: api.nexthop_num = stream_getc (s);
123: stream_get (&nexthop, s, 16);
124: }
125: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
126: {
127: api.ifindex_num = stream_getc (s);
128: ifindex = stream_getl (s);
129: }
130: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
131: api.distance = stream_getc (s);
132: else
133: api.distance = 0;
134: if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
135: api.metric = stream_getl (s);
136: else
137: api.metric = 0;
138:
139: if (command == ZEBRA_IPV6_ROUTE_ADD)
140: ripng_redistribute_add (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop);
141: else
142: ripng_redistribute_delete (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex);
143:
144: return 0;
145: }
146:
147: void
148: ripng_zclient_reset (void)
149: {
150: zclient_reset (zclient);
151: }
152:
153: static int
154: ripng_redistribute_unset (int type)
155: {
156: if (! zclient->redist[type])
157: return CMD_SUCCESS;
158:
159: zclient->redist[type] = 0;
160:
161: if (zclient->sock > 0)
162: zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
163:
164: ripng_redistribute_withdraw (type);
165:
166: return CMD_SUCCESS;
167: }
168:
169: int
170: ripng_redistribute_check (int type)
171: {
172: return (zclient->redist[type]);
173: }
174:
175: static void
176: ripng_redistribute_metric_set (int type, int metric)
177: {
178: ripng->route_map[type].metric_config = 1;
179: ripng->route_map[type].metric = metric;
180: }
181:
182: static int
183: ripng_redistribute_metric_unset (int type)
184: {
185: ripng->route_map[type].metric_config = 0;
186: ripng->route_map[type].metric = 0;
187: return 0;
188: }
189:
190: static void
191: ripng_redistribute_routemap_set (int type, const char *name)
192: {
193: if (ripng->route_map[type].name)
194: free (ripng->route_map[type].name);
195:
196: ripng->route_map[type].name = strdup (name);
197: ripng->route_map[type].map = route_map_lookup_by_name (name);
198: }
199:
200: static void
201: ripng_redistribute_routemap_unset (int type)
202: {
203: if (ripng->route_map[type].name)
204: free (ripng->route_map[type].name);
205:
206: ripng->route_map[type].name = NULL;
207: ripng->route_map[type].map = NULL;
208: }
209:
210: /* Redistribution types */
211: static struct {
212: int type;
213: int str_min_len;
214: const char *str;
215: } redist_type[] = {
216: {ZEBRA_ROUTE_KERNEL, 1, "kernel"},
217: {ZEBRA_ROUTE_CONNECT, 1, "connected"},
218: {ZEBRA_ROUTE_STATIC, 1, "static"},
219: {ZEBRA_ROUTE_OSPF6, 1, "ospf6"},
220: {ZEBRA_ROUTE_BGP, 2, "bgp"},
221: {ZEBRA_ROUTE_BABEL, 2, "babel"},
222: {0, 0, NULL}
223: };
224:
225: void
226: ripng_redistribute_clean ()
227: {
228: int i;
229:
230: for (i = 0; redist_type[i].str; i++)
231: {
232: if (zclient->redist[redist_type[i].type])
233: {
234: if (zclient->sock > 0)
235: zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE,
236: zclient, redist_type[i].type);
237:
238: zclient->redist[redist_type[i].type] = 0;
239:
240: /* Remove the routes from RIPng table. */
241: ripng_redistribute_withdraw (redist_type[i].type);
242: }
243: }
244: }
245:
246: DEFUN (router_zebra,
247: router_zebra_cmd,
248: "router zebra",
249: "Enable a routing process\n"
250: "Make connection to zebra daemon\n")
251: {
252: vty->node = ZEBRA_NODE;
253: zclient->enable = 1;
254: zclient_start (zclient);
255: return CMD_SUCCESS;
256: }
257:
258: DEFUN (no_router_zebra,
259: no_router_zebra_cmd,
260: "no router zebra",
261: NO_STR
262: "Disable a routing process\n"
263: "Stop connection to zebra daemon\n")
264: {
265: zclient->enable = 0;
266: zclient_stop (zclient);
267: return CMD_SUCCESS;
268: }
269:
270: DEFUN (ripng_redistribute_ripng,
271: ripng_redistribute_ripng_cmd,
272: "redistribute ripng",
273: "Redistribute information from another routing protocol\n"
274: "RIPng route\n")
275: {
276: zclient->redist[ZEBRA_ROUTE_RIPNG] = 1;
277: return CMD_SUCCESS;
278: }
279:
280: DEFUN (no_ripng_redistribute_ripng,
281: no_ripng_redistribute_ripng_cmd,
282: "no redistribute ripng",
283: NO_STR
284: "Redistribute information from another routing protocol\n"
285: "RIPng route\n")
286: {
287: zclient->redist[ZEBRA_ROUTE_RIPNG] = 0;
288: return CMD_SUCCESS;
289: }
290:
291: DEFUN (ripng_redistribute_type,
292: ripng_redistribute_type_cmd,
293: "redistribute " QUAGGA_REDIST_STR_RIPNGD,
294: "Redistribute\n"
295: QUAGGA_REDIST_HELP_STR_RIPNGD)
296: {
297: int type;
298:
299: type = proto_redistnum(AFI_IP6, argv[0]);
300:
301: if (type < 0)
302: {
303: vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
304: return CMD_WARNING;
305: }
306:
307: zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
308: return CMD_SUCCESS;
309: }
310:
311: DEFUN (no_ripng_redistribute_type,
312: no_ripng_redistribute_type_cmd,
313: "no redistribute " QUAGGA_REDIST_STR_RIPNGD,
314: NO_STR
315: "Redistribute\n"
316: QUAGGA_REDIST_HELP_STR_RIPNGD)
317: {
318: int type;
319:
320: type = proto_redistnum(AFI_IP6, argv[0]);
321:
322: if (type < 0)
323: {
324: vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
325: return CMD_WARNING;
326: }
327:
328: ripng_redistribute_metric_unset (type);
329: ripng_redistribute_routemap_unset (type);
330: return ripng_redistribute_unset (type);
331: }
332:
333:
334: DEFUN (ripng_redistribute_type_metric,
335: ripng_redistribute_type_metric_cmd,
336: "redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16>",
337: "Redistribute\n"
338: QUAGGA_REDIST_HELP_STR_RIPNGD
339: "Metric\n"
340: "Metric value\n")
341: {
342: int type;
343: int metric;
344:
345: metric = atoi (argv[1]);
346: type = proto_redistnum(AFI_IP6, argv[0]);
347:
348: if (type < 0)
349: {
350: vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
351: return CMD_WARNING;
352: }
353:
354: ripng_redistribute_metric_set (type, metric);
355: zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
356: return CMD_SUCCESS;
357: }
358:
359: ALIAS (no_ripng_redistribute_type,
360: no_ripng_redistribute_type_metric_cmd,
361: "no redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16>",
362: NO_STR
363: "Redistribute\n"
364: QUAGGA_REDIST_HELP_STR_RIPNGD
365: "Metric\n"
366: "Metric value\n")
367:
368: DEFUN (ripng_redistribute_type_routemap,
369: ripng_redistribute_type_routemap_cmd,
370: "redistribute " QUAGGA_REDIST_STR_RIPNGD " route-map WORD",
371: "Redistribute\n"
372: QUAGGA_REDIST_HELP_STR_RIPNGD
373: "Route map reference\n"
374: "Pointer to route-map entries\n")
375: {
376: int type;
377:
378: type = proto_redistnum(AFI_IP6, argv[0]);
379:
380: if (type < 0)
381: {
382: vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
383: return CMD_WARNING;
384: }
385:
386: ripng_redistribute_routemap_set (type, argv[1]);
387: zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
388: return CMD_SUCCESS;
389: }
390:
391: ALIAS (no_ripng_redistribute_type,
392: no_ripng_redistribute_type_routemap_cmd,
393: "no redistribute " QUAGGA_REDIST_STR_RIPNGD " route-map WORD",
394: NO_STR
395: "Redistribute\n"
396: QUAGGA_REDIST_HELP_STR_RIPNGD
397: "Route map reference\n"
398: "Pointer to route-map entries\n")
399:
400: DEFUN (ripng_redistribute_type_metric_routemap,
401: ripng_redistribute_type_metric_routemap_cmd,
402: "redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16> route-map WORD",
403: "Redistribute\n"
404: QUAGGA_REDIST_HELP_STR_RIPNGD
405: "Metric\n"
406: "Metric value\n"
407: "Route map reference\n"
408: "Pointer to route-map entries\n")
409: {
410: int type;
411: int metric;
412:
413: type = proto_redistnum(AFI_IP6, argv[0]);
414: metric = atoi (argv[1]);
415:
416: if (type < 0)
417: {
418: vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
419: return CMD_WARNING;
420: }
421:
422: ripng_redistribute_metric_set (type, metric);
423: ripng_redistribute_routemap_set (type, argv[2]);
424: zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
425: return CMD_SUCCESS;
426: }
427:
428: ALIAS (no_ripng_redistribute_type,
429: no_ripng_redistribute_type_metric_routemap_cmd,
430: "no redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16> route-map WORD",
431: NO_STR
432: "Redistribute\n"
433: QUAGGA_REDIST_HELP_STR_RIPNGD
434: "Route map reference\n"
435: "Pointer to route-map entries\n")
436:
437: void
438: ripng_redistribute_write (struct vty *vty, int config_mode)
439: {
440: int i;
441:
442: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
443: if (i != zclient->redist_default && zclient->redist[i])
444: {
445: if (config_mode)
446: {
447: if (ripng->route_map[i].metric_config)
448: {
449: if (ripng->route_map[i].name)
450: vty_out (vty, " redistribute %s metric %d route-map %s%s",
451: zebra_route_string(i), ripng->route_map[i].metric,
452: ripng->route_map[i].name, VTY_NEWLINE);
453: else
454: vty_out (vty, " redistribute %s metric %d%s",
455: zebra_route_string(i), ripng->route_map[i].metric,
456: VTY_NEWLINE);
457: }
458: else
459: {
460: if (ripng->route_map[i].name)
461: vty_out (vty, " redistribute %s route-map %s%s",
462: zebra_route_string(i), ripng->route_map[i].name,
463: VTY_NEWLINE);
464: else
465: vty_out (vty, " redistribute %s%s", zebra_route_string(i),
466: VTY_NEWLINE);
467: }
468: }
469: else
470: vty_out (vty, " %s", zebra_route_string(i));
471: }
472: }
473:
474: /* RIPng configuration write function. */
475: static int
476: zebra_config_write (struct vty *vty)
477: {
478: if (! zclient->enable)
479: {
480: vty_out (vty, "no router zebra%s", VTY_NEWLINE);
481: return 1;
482: }
483: else if (! zclient->redist[ZEBRA_ROUTE_RIPNG])
484: {
485: vty_out (vty, "router zebra%s", VTY_NEWLINE);
486: vty_out (vty, " no redistribute ripng%s", VTY_NEWLINE);
487: return 1;
488: }
489: return 0;
490: }
491:
492: /* Zebra node structure. */
493: static struct cmd_node zebra_node =
494: {
495: ZEBRA_NODE,
496: "%s(config-router)# ",
497: };
498:
499: /* Initialize zebra structure and it's commands. */
500: void
501: zebra_init ()
502: {
503: /* Allocate zebra structure. */
504: zclient = zclient_new ();
505: zclient_init (zclient, ZEBRA_ROUTE_RIPNG);
506:
507: zclient->interface_up = ripng_interface_up;
508: zclient->interface_down = ripng_interface_down;
509: zclient->interface_add = ripng_interface_add;
510: zclient->interface_delete = ripng_interface_delete;
511: zclient->interface_address_add = ripng_interface_address_add;
512: zclient->interface_address_delete = ripng_interface_address_delete;
513: zclient->ipv6_route_add = ripng_zebra_read_ipv6;
514: zclient->ipv6_route_delete = ripng_zebra_read_ipv6;
515:
516: /* Install zebra node. */
517: install_node (&zebra_node, zebra_config_write);
518:
519: /* Install command element for zebra node. */
520: install_element (CONFIG_NODE, &router_zebra_cmd);
521: install_element (CONFIG_NODE, &no_router_zebra_cmd);
522: install_default (ZEBRA_NODE);
523: install_element (ZEBRA_NODE, &ripng_redistribute_ripng_cmd);
524: install_element (ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd);
525:
526: /* Install command elements to ripng node */
527: install_element (RIPNG_NODE, &ripng_redistribute_type_cmd);
528: install_element (RIPNG_NODE, &ripng_redistribute_type_routemap_cmd);
529: install_element (RIPNG_NODE, &ripng_redistribute_type_metric_cmd);
530: install_element (RIPNG_NODE, &ripng_redistribute_type_metric_routemap_cmd);
531: install_element (RIPNG_NODE, &no_ripng_redistribute_type_cmd);
532: install_element (RIPNG_NODE, &no_ripng_redistribute_type_routemap_cmd);
533: install_element (RIPNG_NODE, &no_ripng_redistribute_type_metric_cmd);
534: install_element (RIPNG_NODE, &no_ripng_redistribute_type_metric_routemap_cmd);
535: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>