]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_zebra.c
*: nuke ^L (page feed)
[mirror_frr.git] / ripd / rip_zebra.c
1 /* 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 #include "ripd/rip_interface.h"
33
34 /* All information about zebra. */
35 struct zclient *zclient = NULL;
36
37 /* RIPd to zebra command interface. */
38 void
39 rip_zebra_ipv4_add (struct prefix_ipv4 *p, struct in_addr *nexthop,
40 u_int32_t metric, u_char distance)
41 {
42 struct zapi_ipv4 api;
43
44 if (zclient->redist[ZEBRA_ROUTE_RIP])
45 {
46 api.type = ZEBRA_ROUTE_RIP;
47 api.flags = 0;
48 api.message = 0;
49 api.safi = SAFI_UNICAST;
50 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
51 api.nexthop_num = 1;
52 api.nexthop = &nexthop;
53 api.ifindex_num = 0;
54 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
55 api.metric = metric;
56
57 if (distance && distance != ZEBRA_RIP_DISTANCE_DEFAULT)
58 {
59 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
60 api.distance = distance;
61 }
62
63 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
64
65 rip_global_route_changes++;
66 }
67 }
68
69 void
70 rip_zebra_ipv4_delete (struct prefix_ipv4 *p, struct in_addr *nexthop,
71 u_int32_t metric)
72 {
73 struct zapi_ipv4 api;
74
75 if (zclient->redist[ZEBRA_ROUTE_RIP])
76 {
77 api.type = ZEBRA_ROUTE_RIP;
78 api.flags = 0;
79 api.message = 0;
80 api.safi = SAFI_UNICAST;
81 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
82 api.nexthop_num = 1;
83 api.nexthop = &nexthop;
84 api.ifindex_num = 0;
85 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
86 api.metric = metric;
87
88 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
89
90 rip_global_route_changes++;
91 }
92 }
93
94 /* Zebra route add and delete treatment. */
95 static int
96 rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
97 {
98 struct stream *s;
99 struct zapi_ipv4 api;
100 unsigned long ifindex;
101 struct in_addr nexthop;
102 struct prefix_ipv4 p;
103
104 s = zclient->ibuf;
105 ifindex = 0;
106 nexthop.s_addr = 0;
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 /* IPv4 prefix. */
114 memset (&p, 0, sizeof (struct prefix_ipv4));
115 p.family = AF_INET;
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 nexthop.s_addr = stream_get_ipv4 (s);
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 = 255;
134 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
135 api.metric = stream_getl (s);
136 else
137 api.metric = 0;
138
139 /* Then fetch IPv4 prefixes. */
140 if (command == ZEBRA_IPV4_ROUTE_ADD)
141 rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex,
142 &nexthop, api.metric, api.distance);
143 else
144 rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex);
145
146 return 0;
147 }
148
149 void
150 rip_zclient_reset (void)
151 {
152 zclient_reset (zclient);
153 }
154
155 /* RIP route-map set for redistribution */
156 static void
157 rip_routemap_set (int type, const 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
166 static void
167 rip_redistribute_metric_set (int type, unsigned int metric)
168 {
169 rip->route_map[type].metric_config = 1;
170 rip->route_map[type].metric = metric;
171 }
172
173 static int
174 rip_metric_unset (int type, unsigned 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 */
186 static int
187 rip_routemap_unset (int type, const 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 */
201 static struct {
202 int type;
203 int str_min_len;
204 const 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, 2, "bgp"},
211 {ZEBRA_ROUTE_BABEL, 2, "babel"},
212 {0, 0, NULL}
213 };
214
215 DEFUN (router_zebra,
216 router_zebra_cmd,
217 "router zebra",
218 "Enable a routing process\n"
219 "Make connection to zebra daemon\n")
220 {
221 vty->node = ZEBRA_NODE;
222 zclient->enable = 1;
223 zclient_start (zclient);
224 return CMD_SUCCESS;
225 }
226
227 DEFUN (no_router_zebra,
228 no_router_zebra_cmd,
229 "no router zebra",
230 NO_STR
231 "Enable a routing process\n"
232 "Make connection to zebra daemon\n")
233 {
234 zclient->enable = 0;
235 zclient_stop (zclient);
236 return CMD_SUCCESS;
237 }
238
239 #if 0
240 static int
241 rip_redistribute_set (int type)
242 {
243 if (zclient->redist[type])
244 return CMD_SUCCESS;
245
246 zclient->redist[type] = 1;
247
248 if (zclient->sock > 0)
249 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
250
251 return CMD_SUCCESS;
252 }
253 #endif
254
255 static int
256 rip_redistribute_unset (int type)
257 {
258 if (! zclient->redist[type])
259 return CMD_SUCCESS;
260
261 zclient->redist[type] = 0;
262
263 if (zclient->sock > 0)
264 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
265
266 /* Remove the routes from RIP table. */
267 rip_redistribute_withdraw (type);
268
269 return CMD_SUCCESS;
270 }
271
272 int
273 rip_redistribute_check (int type)
274 {
275 return (zclient->redist[type]);
276 }
277
278 void
279 rip_redistribute_clean (void)
280 {
281 int i;
282
283 for (i = 0; redist_type[i].str; i++)
284 {
285 if (zclient->redist[redist_type[i].type])
286 {
287 if (zclient->sock > 0)
288 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE,
289 zclient, redist_type[i].type);
290
291 zclient->redist[redist_type[i].type] = 0;
292
293 /* Remove the routes from RIP table. */
294 rip_redistribute_withdraw (redist_type[i].type);
295 }
296 }
297 }
298
299 DEFUN (rip_redistribute_rip,
300 rip_redistribute_rip_cmd,
301 "redistribute rip",
302 "Redistribute information from another routing protocol\n"
303 "Routing Information Protocol (RIP)\n")
304 {
305 zclient->redist[ZEBRA_ROUTE_RIP] = 1;
306 return CMD_SUCCESS;
307 }
308
309 DEFUN (no_rip_redistribute_rip,
310 no_rip_redistribute_rip_cmd,
311 "no redistribute rip",
312 NO_STR
313 "Redistribute information from another routing protocol\n"
314 "Routing Information Protocol (RIP)\n")
315 {
316 zclient->redist[ZEBRA_ROUTE_RIP] = 0;
317 return CMD_SUCCESS;
318 }
319
320 DEFUN (rip_redistribute_type,
321 rip_redistribute_type_cmd,
322 "redistribute " QUAGGA_REDIST_STR_RIPD,
323 REDIST_STR
324 QUAGGA_REDIST_HELP_STR_RIPD)
325 {
326 int i;
327
328 for(i = 0; redist_type[i].str; i++)
329 {
330 if (strncmp (redist_type[i].str, argv[0],
331 redist_type[i].str_min_len) == 0)
332 {
333 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient,
334 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
345 DEFUN (no_rip_redistribute_type,
346 no_rip_redistribute_type_cmd,
347 "no redistribute " QUAGGA_REDIST_STR_RIPD,
348 NO_STR
349 REDIST_STR
350 QUAGGA_REDIST_HELP_STR_RIPD)
351 {
352 int i;
353
354 for (i = 0; redist_type[i].str; i++)
355 {
356 if (strncmp(redist_type[i].str, argv[0],
357 redist_type[i].str_min_len) == 0)
358 {
359 rip_metric_unset (redist_type[i].type, DONT_CARE_METRIC_RIP);
360 rip_routemap_unset (redist_type[i].type,NULL);
361 rip_redistribute_unset (redist_type[i].type);
362 return CMD_SUCCESS;
363 }
364 }
365
366 vty_out(vty, "Invalid type %s%s", argv[0],
367 VTY_NEWLINE);
368
369 return CMD_WARNING;
370 }
371
372 DEFUN (rip_redistribute_type_routemap,
373 rip_redistribute_type_routemap_cmd,
374 "redistribute " QUAGGA_REDIST_STR_RIPD " route-map WORD",
375 REDIST_STR
376 QUAGGA_REDIST_HELP_STR_RIPD
377 "Route map reference\n"
378 "Pointer to route-map entries\n")
379 {
380 int i;
381
382 for (i = 0; redist_type[i].str; i++) {
383 if (strncmp(redist_type[i].str, argv[0],
384 redist_type[i].str_min_len) == 0)
385 {
386 rip_routemap_set (redist_type[i].type, argv[1]);
387 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type);
388 return CMD_SUCCESS;
389 }
390 }
391
392 vty_out(vty, "Invalid type %s%s", argv[0],
393 VTY_NEWLINE);
394
395 return CMD_WARNING;
396 }
397
398 DEFUN (no_rip_redistribute_type_routemap,
399 no_rip_redistribute_type_routemap_cmd,
400 "no redistribute " QUAGGA_REDIST_STR_RIPD " route-map WORD",
401 NO_STR
402 REDIST_STR
403 QUAGGA_REDIST_HELP_STR_RIPD
404 "Route map reference\n"
405 "Pointer to route-map entries\n")
406 {
407 int i;
408
409 for (i = 0; redist_type[i].str; i++)
410 {
411 if (strncmp(redist_type[i].str, argv[0],
412 redist_type[i].str_min_len) == 0)
413 {
414 if (rip_routemap_unset (redist_type[i].type,argv[1]))
415 return CMD_WARNING;
416 rip_redistribute_unset (redist_type[i].type);
417 return CMD_SUCCESS;
418 }
419 }
420
421 vty_out(vty, "Invalid type %s%s", argv[0],
422 VTY_NEWLINE);
423
424 return CMD_WARNING;
425 }
426
427 DEFUN (rip_redistribute_type_metric,
428 rip_redistribute_type_metric_cmd,
429 "redistribute " QUAGGA_REDIST_STR_RIPD " metric <0-16>",
430 REDIST_STR
431 QUAGGA_REDIST_HELP_STR_RIPD
432 "Metric\n"
433 "Metric value\n")
434 {
435 int i;
436 int metric;
437
438 metric = atoi (argv[1]);
439
440 for (i = 0; redist_type[i].str; i++) {
441 if (strncmp(redist_type[i].str, argv[0],
442 redist_type[i].str_min_len) == 0)
443 {
444 rip_redistribute_metric_set (redist_type[i].type, metric);
445 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type);
446 return CMD_SUCCESS;
447 }
448 }
449
450 vty_out(vty, "Invalid type %s%s", argv[0],
451 VTY_NEWLINE);
452
453 return CMD_WARNING;
454 }
455
456 DEFUN (no_rip_redistribute_type_metric,
457 no_rip_redistribute_type_metric_cmd,
458 "no redistribute " QUAGGA_REDIST_STR_RIPD " metric <0-16>",
459 NO_STR
460 REDIST_STR
461 QUAGGA_REDIST_HELP_STR_RIPD
462 "Metric\n"
463 "Metric value\n")
464 {
465 int i;
466
467 for (i = 0; redist_type[i].str; i++)
468 {
469 if (strncmp(redist_type[i].str, argv[0],
470 redist_type[i].str_min_len) == 0)
471 {
472 if (rip_metric_unset (redist_type[i].type, atoi(argv[1])))
473 return CMD_WARNING;
474 rip_redistribute_unset (redist_type[i].type);
475 return CMD_SUCCESS;
476 }
477 }
478
479 vty_out(vty, "Invalid type %s%s", argv[0],
480 VTY_NEWLINE);
481
482 return CMD_WARNING;
483 }
484
485 DEFUN (rip_redistribute_type_metric_routemap,
486 rip_redistribute_type_metric_routemap_cmd,
487 "redistribute " QUAGGA_REDIST_STR_RIPD " metric <0-16> route-map WORD",
488 REDIST_STR
489 QUAGGA_REDIST_HELP_STR_RIPD
490 "Metric\n"
491 "Metric value\n"
492 "Route map reference\n"
493 "Pointer to route-map entries\n")
494 {
495 int i;
496 int metric;
497
498 metric = atoi (argv[1]);
499
500 for (i = 0; redist_type[i].str; i++) {
501 if (strncmp(redist_type[i].str, argv[0],
502 redist_type[i].str_min_len) == 0)
503 {
504 rip_redistribute_metric_set (redist_type[i].type, metric);
505 rip_routemap_set (redist_type[i].type, argv[2]);
506 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type);
507 return CMD_SUCCESS;
508 }
509 }
510
511 vty_out(vty, "Invalid type %s%s", argv[0],
512 VTY_NEWLINE);
513
514 return CMD_WARNING;
515 }
516
517
518 DEFUN (no_rip_redistribute_type_metric_routemap,
519 no_rip_redistribute_type_metric_routemap_cmd,
520 "no redistribute " QUAGGA_REDIST_STR_RIPD
521 " metric <0-16> route-map WORD",
522 NO_STR
523 REDIST_STR
524 QUAGGA_REDIST_HELP_STR_RIPD
525 "Metric\n"
526 "Metric value\n"
527 "Route map reference\n"
528 "Pointer to route-map entries\n")
529 {
530 int i;
531
532 for (i = 0; redist_type[i].str; i++)
533 {
534 if (strncmp(redist_type[i].str, argv[0],
535 redist_type[i].str_min_len) == 0)
536 {
537 if (rip_metric_unset (redist_type[i].type, atoi(argv[1])))
538 return CMD_WARNING;
539 if (rip_routemap_unset (redist_type[i].type, argv[2]))
540 {
541 rip_redistribute_metric_set(redist_type[i].type, atoi(argv[1]));
542 return CMD_WARNING;
543 }
544 rip_redistribute_unset (redist_type[i].type);
545 return CMD_SUCCESS;
546 }
547 }
548
549 vty_out(vty, "Invalid type %s%s", argv[0],
550 VTY_NEWLINE);
551
552 return CMD_WARNING;
553 }
554
555 /* Default information originate. */
556
557 DEFUN (rip_default_information_originate,
558 rip_default_information_originate_cmd,
559 "default-information originate",
560 "Control distribution of default route\n"
561 "Distribute a default route\n")
562 {
563 struct prefix_ipv4 p;
564
565 if (! rip->default_information)
566 {
567 memset (&p, 0, sizeof (struct prefix_ipv4));
568 p.family = AF_INET;
569
570 rip->default_information = 1;
571
572 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0,
573 NULL, 0, 0);
574 }
575
576 return CMD_SUCCESS;
577 }
578
579 DEFUN (no_rip_default_information_originate,
580 no_rip_default_information_originate_cmd,
581 "no default-information originate",
582 NO_STR
583 "Control distribution of default route\n"
584 "Distribute a default route\n")
585 {
586 struct prefix_ipv4 p;
587
588 if (rip->default_information)
589 {
590 memset (&p, 0, sizeof (struct prefix_ipv4));
591 p.family = AF_INET;
592
593 rip->default_information = 0;
594
595 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0);
596 }
597
598 return CMD_SUCCESS;
599 }
600
601 /* RIP configuration write function. */
602 static int
603 config_write_zebra (struct vty *vty)
604 {
605 if (! zclient->enable)
606 {
607 vty_out (vty, "no router zebra%s", VTY_NEWLINE);
608 return 1;
609 }
610 else if (! zclient->redist[ZEBRA_ROUTE_RIP])
611 {
612 vty_out (vty, "router zebra%s", VTY_NEWLINE);
613 vty_out (vty, " no redistribute rip%s", VTY_NEWLINE);
614 return 1;
615 }
616 return 0;
617 }
618
619 int
620 config_write_rip_redistribute (struct vty *vty, int config_mode)
621 {
622 int i;
623
624 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
625 if (i != zclient->redist_default && zclient->redist[i])
626 {
627 if (config_mode)
628 {
629 if (rip->route_map[i].metric_config)
630 {
631 if (rip->route_map[i].name)
632 vty_out (vty, " redistribute %s metric %d route-map %s%s",
633 zebra_route_string(i), rip->route_map[i].metric,
634 rip->route_map[i].name,
635 VTY_NEWLINE);
636 else
637 vty_out (vty, " redistribute %s metric %d%s",
638 zebra_route_string(i), rip->route_map[i].metric,
639 VTY_NEWLINE);
640 }
641 else
642 {
643 if (rip->route_map[i].name)
644 vty_out (vty, " redistribute %s route-map %s%s",
645 zebra_route_string(i), rip->route_map[i].name,
646 VTY_NEWLINE);
647 else
648 vty_out (vty, " redistribute %s%s", zebra_route_string(i),
649 VTY_NEWLINE);
650 }
651 }
652 else
653 vty_out (vty, " %s", zebra_route_string(i));
654 }
655 return 0;
656 }
657
658 /* Zebra node structure. */
659 static struct cmd_node zebra_node =
660 {
661 ZEBRA_NODE,
662 "%s(config-router)# ",
663 };
664
665 void
666 rip_zclient_init ()
667 {
668 /* Set default value to the zebra client structure. */
669 zclient = zclient_new ();
670 zclient_init (zclient, ZEBRA_ROUTE_RIP);
671 zclient->interface_add = rip_interface_add;
672 zclient->interface_delete = rip_interface_delete;
673 zclient->interface_address_add = rip_interface_address_add;
674 zclient->interface_address_delete = rip_interface_address_delete;
675 zclient->ipv4_route_add = rip_zebra_read_ipv4;
676 zclient->ipv4_route_delete = rip_zebra_read_ipv4;
677 zclient->interface_up = rip_interface_up;
678 zclient->interface_down = rip_interface_down;
679
680 /* Install zebra node. */
681 install_node (&zebra_node, config_write_zebra);
682
683 /* Install command elements to zebra node. */
684 install_element (CONFIG_NODE, &router_zebra_cmd);
685 install_element (CONFIG_NODE, &no_router_zebra_cmd);
686 install_default (ZEBRA_NODE);
687 install_element (ZEBRA_NODE, &rip_redistribute_rip_cmd);
688 install_element (ZEBRA_NODE, &no_rip_redistribute_rip_cmd);
689
690 /* Install command elements to rip node. */
691 install_element (RIP_NODE, &rip_redistribute_type_cmd);
692 install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd);
693 install_element (RIP_NODE, &rip_redistribute_type_metric_cmd);
694 install_element (RIP_NODE, &rip_redistribute_type_metric_routemap_cmd);
695 install_element (RIP_NODE, &no_rip_redistribute_type_cmd);
696 install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd);
697 install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd);
698 install_element (RIP_NODE, &no_rip_redistribute_type_metric_routemap_cmd);
699 install_element (RIP_NODE, &rip_default_information_originate_cmd);
700 install_element (RIP_NODE, &no_rip_default_information_originate_cmd);
701 }