blob: b6caf3b07cc3b10e6dc742ecf222f3242573f073 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIPd and zebra interface.
2 * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "command.h"
25#include "prefix.h"
26#include "stream.h"
27#include "routemap.h"
28#include "zclient.h"
29#include "log.h"
30#include "ripd/ripd.h"
31#include "ripd/rip_debug.h"
32
33/* All information about zebra. */
34struct zclient *zclient = NULL;
35
36/* Callback prototypes for zebra client service. */
37int rip_interface_add (int, struct zclient *, zebra_size_t);
38int rip_interface_delete (int, struct zclient *, zebra_size_t);
39int rip_interface_address_add (int, struct zclient *, zebra_size_t);
40int rip_interface_address_delete (int, struct zclient *, zebra_size_t);
41int rip_interface_up (int, struct zclient *, zebra_size_t);
42int rip_interface_down (int, struct zclient *, zebra_size_t);
43
44/* RIPd to zebra command interface. */
45void
46rip_zebra_ipv4_add (struct prefix_ipv4 *p, struct in_addr *nexthop,
47 u_int32_t metric, u_char distance)
48{
49 struct zapi_ipv4 api;
50
51 if (zclient->redist[ZEBRA_ROUTE_RIP])
52 {
53 api.type = ZEBRA_ROUTE_RIP;
54 api.flags = 0;
55 api.message = 0;
56 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
57 api.nexthop_num = 1;
58 api.nexthop = &nexthop;
59 api.ifindex_num = 0;
60 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
61 api.metric = metric;
62
63 if (distance && distance != ZEBRA_RIP_DISTANCE_DEFAULT)
64 {
65 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
66 api.distance = distance;
67 }
68
69 zapi_ipv4_add (zclient, p, &api);
70
71 rip_global_route_changes++;
72 }
73}
74
75void
76rip_zebra_ipv4_delete (struct prefix_ipv4 *p, struct in_addr *nexthop,
77 u_int32_t metric)
78{
79 struct zapi_ipv4 api;
80
81 if (zclient->redist[ZEBRA_ROUTE_RIP])
82 {
83 api.type = ZEBRA_ROUTE_RIP;
84 api.flags = 0;
85 api.message = 0;
86 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
87 api.nexthop_num = 1;
88 api.nexthop = &nexthop;
89 api.ifindex_num = 0;
90 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
91 api.metric = metric;
92
93 zapi_ipv4_delete (zclient, p, &api);
94
95 rip_global_route_changes++;
96 }
97}
98
99/* Zebra route add and delete treatment. */
100int
101rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
102{
103 struct stream *s;
104 struct zapi_ipv4 api;
105 unsigned long ifindex;
106 struct in_addr nexthop;
107 struct prefix_ipv4 p;
108
109 s = zclient->ibuf;
110 ifindex = 0;
111 nexthop.s_addr = 0;
112
113 /* Type, flags, message. */
114 api.type = stream_getc (s);
115 api.flags = stream_getc (s);
116 api.message = stream_getc (s);
117
118 /* IPv4 prefix. */
119 memset (&p, 0, sizeof (struct prefix_ipv4));
120 p.family = AF_INET;
121 p.prefixlen = stream_getc (s);
122 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
123
124 /* Nexthop, ifindex, distance, metric. */
125 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
126 {
127 api.nexthop_num = stream_getc (s);
128 nexthop.s_addr = stream_get_ipv4 (s);
129 }
130 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
131 {
132 api.ifindex_num = stream_getc (s);
133 ifindex = stream_getl (s);
134 }
135 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
136 api.distance = stream_getc (s);
137 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
138 api.metric = stream_getl (s);
139
140 /* Then fetch IPv4 prefixes. */
141 if (command == ZEBRA_IPV4_ROUTE_ADD)
142 rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop);
143 else
144 rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex);
145
146 return 0;
147}
148
149void
150rip_zclient_reset ()
151{
152 zclient_reset (zclient);
153}
154
155/* RIP route-map set for redistribution */
156void
157rip_routemap_set (int type, char *name)
158{
159 if (rip->route_map[type].name)
160 free(rip->route_map[type].name);
161
162 rip->route_map[type].name = strdup (name);
163 rip->route_map[type].map = route_map_lookup_by_name (name);
164}
165
166void
167rip_redistribute_metric_set (int type, int metric)
168{
169 rip->route_map[type].metric_config = 1;
170 rip->route_map[type].metric = metric;
171}
172
173int
174rip_metric_unset (int type,int metric)
175{
176#define DONT_CARE_METRIC_RIP 17
177 if (metric != DONT_CARE_METRIC_RIP &&
178 rip->route_map[type].metric != metric)
179 return 1;
180 rip->route_map[type].metric_config = 0;
181 rip->route_map[type].metric = 0;
182 return 0;
183}
184
185/* RIP route-map unset for redistribution */
186int
187rip_routemap_unset (int type,char *name)
188{
189 if (! rip->route_map[type].name ||
190 (name != NULL && strcmp(rip->route_map[type].name,name)))
191 return 1;
192
193 free (rip->route_map[type].name);
194 rip->route_map[type].name = NULL;
195 rip->route_map[type].map = NULL;
196
197 return 0;
198}
199
200/* Redistribution types */
201static struct {
202 int type;
203 int str_min_len;
204 char *str;
205} redist_type[] = {
206 {ZEBRA_ROUTE_KERNEL, 1, "kernel"},
207 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
208 {ZEBRA_ROUTE_STATIC, 1, "static"},
209 {ZEBRA_ROUTE_OSPF, 1, "ospf"},
210 {ZEBRA_ROUTE_BGP, 1, "bgp"},
211 {0, 0, NULL}
212};
213
214DEFUN (router_zebra,
215 router_zebra_cmd,
216 "router zebra",
217 "Enable a routing process\n"
218 "Make connection to zebra daemon\n")
219{
220 vty->node = ZEBRA_NODE;
221 zclient->enable = 1;
222 zclient_start (zclient);
223 return CMD_SUCCESS;
224}
225
226DEFUN (no_router_zebra,
227 no_router_zebra_cmd,
228 "no router zebra",
229 NO_STR
230 "Enable a routing process\n"
231 "Make connection to zebra daemon\n")
232{
233 zclient->enable = 0;
234 zclient_stop (zclient);
235 return CMD_SUCCESS;
236}
237
238int
239rip_redistribute_set (int type)
240{
241 if (zclient->redist[type])
242 return CMD_SUCCESS;
243
244 zclient->redist[type] = 1;
245
246 if (zclient->sock > 0)
247 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, type);
248
249 return CMD_SUCCESS;
250}
251
252int
253rip_redistribute_unset (int type)
254{
255 if (! zclient->redist[type])
256 return CMD_SUCCESS;
257
258 zclient->redist[type] = 0;
259
260 if (zclient->sock > 0)
261 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient->sock, type);
262
263 /* Remove the routes from RIP table. */
264 rip_redistribute_withdraw (type);
265
266 return CMD_SUCCESS;
267}
268
269int
270rip_redistribute_check (int type)
271{
272 return (zclient->redist[type]);
273}
274
275void
276rip_redistribute_clean ()
277{
278 int i;
279
280 for (i = 0; redist_type[i].str; i++)
281 {
282 if (zclient->redist[redist_type[i].type])
283 {
284 if (zclient->sock > 0)
285 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE,
286 zclient->sock, redist_type[i].type);
287
288 zclient->redist[redist_type[i].type] = 0;
289
290 /* Remove the routes from RIP table. */
291 rip_redistribute_withdraw (redist_type[i].type);
292 }
293 }
294}
295
296DEFUN (rip_redistribute_rip,
297 rip_redistribute_rip_cmd,
298 "redistribute rip",
299 "Redistribute information from another routing protocol\n"
300 "Routing Information Protocol (RIP)\n")
301{
302 zclient->redist[ZEBRA_ROUTE_RIP] = 1;
303 return CMD_SUCCESS;
304}
305
306DEFUN (no_rip_redistribute_rip,
307 no_rip_redistribute_rip_cmd,
308 "no redistribute rip",
309 NO_STR
310 "Redistribute information from another routing protocol\n"
311 "Routing Information Protocol (RIP)\n")
312{
313 zclient->redist[ZEBRA_ROUTE_RIP] = 0;
314 return CMD_SUCCESS;
315}
316
317DEFUN (rip_redistribute_type,
318 rip_redistribute_type_cmd,
319 "redistribute (kernel|connected|static|ospf|bgp)",
320 "Redistribute information from another routing protocol\n"
321 "Kernel routes\n"
322 "Connected\n"
323 "Static routes\n"
324 "Open Shortest Path First (OSPF)\n"
325 "Border Gateway Protocol (BGP)\n")
326{
327 int i;
328
329 for(i = 0; redist_type[i].str; i++)
330 {
331 if (strncmp (redist_type[i].str, argv[0],
332 redist_type[i].str_min_len) == 0)
333 {
334 zclient_redistribute_set (zclient, redist_type[i].type);
335 return CMD_SUCCESS;
336 }
337 }
338
339 vty_out(vty, "Invalid type %s%s", argv[0],
340 VTY_NEWLINE);
341
342 return CMD_WARNING;
343}
344
345DEFUN (no_rip_redistribute_type,
346 no_rip_redistribute_type_cmd,
347 "no redistribute (kernel|connected|static|ospf|bgp)",
348 NO_STR
349 "Redistribute information from another routing protocol\n"
350 "Kernel routes\n"
351 "Connected\n"
352 "Static routes\n"
353 "Open Shortest Path First (OSPF)\n"
354 "Border Gateway Protocol (BGP)\n")
355{
356 int i;
357
358 for (i = 0; redist_type[i].str; i++)
359 {
360 if (strncmp(redist_type[i].str, argv[0],
361 redist_type[i].str_min_len) == 0)
362 {
363 rip_metric_unset (redist_type[i].type, DONT_CARE_METRIC_RIP);
364 rip_routemap_unset (redist_type[i].type,NULL);
365 rip_redistribute_unset (redist_type[i].type);
366 return CMD_SUCCESS;
367 }
368 }
369
370 vty_out(vty, "Invalid type %s%s", argv[0],
371 VTY_NEWLINE);
372
373 return CMD_WARNING;
374}
375
376DEFUN (rip_redistribute_type_routemap,
377 rip_redistribute_type_routemap_cmd,
378 "redistribute (kernel|connected|static|ospf|bgp) route-map WORD",
379 "Redistribute information from another routing protocol\n"
380 "Kernel routes\n"
381 "Connected\n"
382 "Static routes\n"
383 "Open Shortest Path First (OSPF)\n"
384 "Border Gateway Protocol (BGP)\n"
385 "Route map reference\n"
386 "Pointer to route-map entries\n")
387{
388 int i;
389
390 for (i = 0; redist_type[i].str; i++) {
391 if (strncmp(redist_type[i].str, argv[0],
392 redist_type[i].str_min_len) == 0)
393 {
394 rip_routemap_set (redist_type[i].type, argv[1]);
395 zclient_redistribute_set (zclient, redist_type[i].type);
396 return CMD_SUCCESS;
397 }
398 }
399
400 vty_out(vty, "Invalid type %s%s", argv[0],
401 VTY_NEWLINE);
402
403 return CMD_WARNING;
404}
405
406DEFUN (no_rip_redistribute_type_routemap,
407 no_rip_redistribute_type_routemap_cmd,
408 "no redistribute (kernel|connected|static|ospf|bgp) route-map WORD",
409 NO_STR
410 "Redistribute information from another routing protocol\n"
411 "Kernel routes\n"
412 "Connected\n"
413 "Static routes\n"
414 "Open Shortest Path First (OSPF)\n"
415 "Border Gateway Protocol (BGP)\n"
416 "Route map reference\n"
417 "Pointer to route-map entries\n")
418{
419 int i;
420
421 for (i = 0; redist_type[i].str; i++)
422 {
423 if (strncmp(redist_type[i].str, argv[0],
424 redist_type[i].str_min_len) == 0)
425 {
426 if (rip_routemap_unset (redist_type[i].type,argv[1]))
427 return CMD_WARNING;
428 rip_redistribute_unset (redist_type[i].type);
429 return CMD_SUCCESS;
430 }
431 }
432
433 vty_out(vty, "Invalid type %s%s", argv[0],
434 VTY_NEWLINE);
435
436 return CMD_WARNING;
437}
438
439DEFUN (rip_redistribute_type_metric,
440 rip_redistribute_type_metric_cmd,
441 "redistribute (kernel|connected|static|ospf|bgp) metric <0-16>",
442 "Redistribute information from another routing protocol\n"
443 "Kernel routes\n"
444 "Connected\n"
445 "Static routes\n"
446 "Open Shortest Path First (OSPF)\n"
447 "Border Gateway Protocol (BGP)\n"
448 "Metric\n"
449 "Metric value\n")
450{
451 int i;
452 int metric;
453
454 metric = atoi (argv[1]);
455
456 for (i = 0; redist_type[i].str; i++) {
457 if (strncmp(redist_type[i].str, argv[0],
458 redist_type[i].str_min_len) == 0)
459 {
460 rip_redistribute_metric_set (redist_type[i].type, metric);
461 zclient_redistribute_set (zclient, redist_type[i].type);
462 return CMD_SUCCESS;
463 }
464 }
465
466 vty_out(vty, "Invalid type %s%s", argv[0],
467 VTY_NEWLINE);
468
469 return CMD_WARNING;
470}
471
472DEFUN (no_rip_redistribute_type_metric,
473 no_rip_redistribute_type_metric_cmd,
474 "no redistribute (kernel|connected|static|ospf|bgp) metric <0-16>",
475 NO_STR
476 "Redistribute information from another routing protocol\n"
477 "Kernel routes\n"
478 "Connected\n"
479 "Static routes\n"
480 "Open Shortest Path First (OSPF)\n"
481 "Border Gateway Protocol (BGP)\n"
482 "Metric\n"
483 "Metric value\n")
484{
485 int i;
486
487 for (i = 0; redist_type[i].str; i++)
488 {
489 if (strncmp(redist_type[i].str, argv[0],
490 redist_type[i].str_min_len) == 0)
491 {
492 if (rip_metric_unset (redist_type[i].type, atoi(argv[1])))
493 return CMD_WARNING;
494 rip_redistribute_unset (redist_type[i].type);
495 return CMD_SUCCESS;
496 }
497 }
498
499 vty_out(vty, "Invalid type %s%s", argv[0],
500 VTY_NEWLINE);
501
502 return CMD_WARNING;
503}
504
505DEFUN (no_rip_redistribute_type_metric_routemap,
506 no_rip_redistribute_type_metric_routemap_cmd,
507 "no redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD",
508 NO_STR
509 "Redistribute information from another routing protocol\n"
510 "Kernel routes\n"
511 "Connected\n"
512 "Static routes\n"
513 "Open Shortest Path First (OSPF)\n"
514 "Border Gateway Protocol (BGP)\n"
515 "Metric\n"
516 "Metric value\n"
517 "Route map reference\n"
518 "Pointer to route-map entries\n")
519{
520 int i;
521
522 for (i = 0; redist_type[i].str; i++)
523 {
524 if (strncmp(redist_type[i].str, argv[0],
525 redist_type[i].str_min_len) == 0)
526 {
527 if (rip_metric_unset (redist_type[i].type, atoi(argv[1])))
528 return CMD_WARNING;
529 if (rip_routemap_unset (redist_type[i].type, argv[2]))
530 {
531 rip_redistribute_metric_set(redist_type[i].type, atoi(argv[1]));
532 return CMD_WARNING;
533 }
534 rip_redistribute_unset (redist_type[i].type);
535 return CMD_SUCCESS;
536 }
537 }
538
539 vty_out(vty, "Invalid type %s%s", argv[0],
540 VTY_NEWLINE);
541
542 return CMD_WARNING;
543}
544
545/* Default information originate. */
546
547DEFUN (rip_default_information_originate,
548 rip_default_information_originate_cmd,
549 "default-information originate",
550 "Control distribution of default route\n"
551 "Distribute a default route\n")
552{
553 struct prefix_ipv4 p;
554
555 if (! rip->default_information)
556 {
557 memset (&p, 0, sizeof (struct prefix_ipv4));
558 p.family = AF_INET;
559
560 rip->default_information = 1;
561
562 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
563 }
564
565 return CMD_SUCCESS;
566}
567
568DEFUN (no_rip_default_information_originate,
569 no_rip_default_information_originate_cmd,
570 "no default-information originate",
571 NO_STR
572 "Control distribution of default route\n"
573 "Distribute a default route\n")
574{
575 struct prefix_ipv4 p;
576
577 if (rip->default_information)
578 {
579 memset (&p, 0, sizeof (struct prefix_ipv4));
580 p.family = AF_INET;
581
582 rip->default_information = 0;
583
584 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
585 }
586
587 return CMD_SUCCESS;
588}
589
590/* RIP configuration write function. */
591int
592config_write_zebra (struct vty *vty)
593{
594 if (! zclient->enable)
595 {
596 vty_out (vty, "no router zebra%s", VTY_NEWLINE);
597 return 1;
598 }
599 else if (! zclient->redist[ZEBRA_ROUTE_RIP])
600 {
601 vty_out (vty, "router zebra%s", VTY_NEWLINE);
602 vty_out (vty, " no redistribute rip%s", VTY_NEWLINE);
603 return 1;
604 }
605 return 0;
606}
607
608int
609config_write_rip_redistribute (struct vty *vty, int config_mode)
610{
611 int i;
612 char *str[] = { "system", "kernel", "connected", "static", "rip",
613 "ripng", "ospf", "ospf6", "bgp"};
614
615 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
616 if (i != zclient->redist_default && zclient->redist[i])
617 {
618 if (config_mode)
619 {
620 if (rip->route_map[i].metric_config)
621 {
622 if (rip->route_map[i].name)
623 vty_out (vty, " redistribute %s metric %d route-map %s%s",
624 str[i], rip->route_map[i].metric,
625 rip->route_map[i].name,
626 VTY_NEWLINE);
627 else
628 vty_out (vty, " redistribute %s metric %d%s",
629 str[i], rip->route_map[i].metric,
630 VTY_NEWLINE);
631 }
632 else
633 {
634 if (rip->route_map[i].name)
635 vty_out (vty, " redistribute %s route-map %s%s",
636 str[i], rip->route_map[i].name,
637 VTY_NEWLINE);
638 else
639 vty_out (vty, " redistribute %s%s", str[i],
640 VTY_NEWLINE);
641 }
642 }
643 else
644 vty_out (vty, " %s", str[i]);
645 }
646 return 0;
647}
648
649/* Zebra node structure. */
650struct cmd_node zebra_node =
651{
652 ZEBRA_NODE,
653 "%s(config-router)# ",
654};
655
656void
657rip_zclient_init ()
658{
659 /* Set default value to the zebra client structure. */
660 zclient = zclient_new ();
661 zclient_init (zclient, ZEBRA_ROUTE_RIP);
662 zclient->interface_add = rip_interface_add;
663 zclient->interface_delete = rip_interface_delete;
664 zclient->interface_address_add = rip_interface_address_add;
665 zclient->interface_address_delete = rip_interface_address_delete;
666 zclient->ipv4_route_add = rip_zebra_read_ipv4;
667 zclient->ipv4_route_delete = rip_zebra_read_ipv4;
668 zclient->interface_up = rip_interface_up;
669 zclient->interface_down = rip_interface_down;
670
671 /* Install zebra node. */
672 install_node (&zebra_node, config_write_zebra);
673
674 /* Install command elements to zebra node. */
675 install_element (CONFIG_NODE, &router_zebra_cmd);
676 install_element (CONFIG_NODE, &no_router_zebra_cmd);
677 install_default (ZEBRA_NODE);
678 install_element (ZEBRA_NODE, &rip_redistribute_rip_cmd);
679 install_element (ZEBRA_NODE, &no_rip_redistribute_rip_cmd);
680
681 /* Install command elements to rip node. */
682 install_element (RIP_NODE, &rip_redistribute_type_cmd);
683 install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd);
684 install_element (RIP_NODE, &rip_redistribute_type_metric_cmd);
685 install_element (RIP_NODE, &no_rip_redistribute_type_cmd);
686 install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd);
687 install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd);
688 install_element (RIP_NODE, &no_rip_redistribute_type_metric_routemap_cmd);
689 install_element (RIP_NODE, &rip_default_information_originate_cmd);
690 install_element (RIP_NODE, &no_rip_default_information_originate_cmd);
691}