1 /* RIPd and zebra interface.
2 * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GNU Zebra.
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
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.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #include "ripd/ripd.h"
33 #include "ripd/rip_debug.h"
34 #include "ripd/rip_interface.h"
36 /* All information about zebra. */
37 struct zclient
*zclient
= NULL
;
39 /* Send ECMP routes to zebra. */
40 static void rip_zebra_ipv4_send(struct route_node
*rp
, u_char cmd
)
42 static struct in_addr
**nexthops
= NULL
;
43 static unsigned int nexthops_len
= 0;
45 struct list
*list
= (struct list
*)rp
->info
;
47 struct listnode
*listnode
= NULL
;
48 struct rip_info
*rinfo
= NULL
;
51 if (vrf_bitmap_check(zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_RIP
],
53 api
.vrf_id
= VRF_DEFAULT
;
54 api
.type
= ZEBRA_ROUTE_RIP
;
58 api
.safi
= SAFI_UNICAST
;
60 if (nexthops_len
< listcount(list
)) {
61 nexthops_len
= listcount(list
);
62 nexthops
= XREALLOC(MTYPE_TMP
, nexthops
,
64 * sizeof(struct in_addr
*));
67 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
68 for (ALL_LIST_ELEMENTS_RO(list
, listnode
, rinfo
)) {
69 nexthops
[count
++] = &rinfo
->nexthop
;
70 if (cmd
== ZEBRA_IPV4_ROUTE_ADD
)
71 SET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
73 UNSET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
76 api
.nexthop
= nexthops
;
77 api
.nexthop_num
= count
;
80 rinfo
= listgetdata(listhead(list
));
82 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
83 api
.metric
= rinfo
->metric
;
86 && rinfo
->distance
!= ZEBRA_RIP_DISTANCE_DEFAULT
) {
87 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
88 api
.distance
= rinfo
->distance
;
92 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
96 zapi_ipv4_route(cmd
, zclient
, (struct prefix_ipv4
*)&rp
->p
,
99 if (IS_RIP_DEBUG_ZEBRA
) {
101 zlog_debug("%s: %s/%d nexthops %d",
102 (cmd
== ZEBRA_IPV4_ROUTE_ADD
)
103 ? "Install into zebra"
104 : "Delete from zebra",
105 inet_ntoa(rp
->p
.u
.prefix4
),
106 rp
->p
.prefixlen
, count
);
108 zlog_debug("%s: %s/%d",
109 (cmd
== ZEBRA_IPV4_ROUTE_ADD
)
110 ? "Install into zebra"
111 : "Delete from zebra",
112 inet_ntoa(rp
->p
.u
.prefix4
),
116 rip_global_route_changes
++;
120 /* Add/update ECMP routes to zebra. */
121 void rip_zebra_ipv4_add(struct route_node
*rp
)
123 rip_zebra_ipv4_send(rp
, ZEBRA_IPV4_ROUTE_ADD
);
126 /* Delete ECMP routes from zebra. */
127 void rip_zebra_ipv4_delete(struct route_node
*rp
)
129 rip_zebra_ipv4_send(rp
, ZEBRA_IPV4_ROUTE_DELETE
);
132 /* Zebra route add and delete treatment. */
133 static int rip_zebra_read_ipv4(int command
, struct zclient
*zclient
,
134 zebra_size_t length
, vrf_id_t vrf_id
)
137 struct zapi_ipv4 api
;
138 unsigned long ifindex
;
139 struct in_addr nexthop
;
140 struct prefix_ipv4 p
;
149 /* Type, flags, message. */
150 api
.type
= stream_getc(s
);
151 api
.instance
= stream_getw(s
);
152 api
.flags
= stream_getl(s
);
153 api
.message
= stream_getc(s
);
156 memset(&p
, 0, sizeof(struct prefix_ipv4
));
158 p
.prefixlen
= MIN(IPV4_MAX_PREFIXLEN
, stream_getc(s
));
159 stream_get(&p
.prefix
, s
, PSIZE(p
.prefixlen
));
161 /* Nexthop, ifindex, distance, metric. */
162 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
)) {
163 api
.nexthop_num
= stream_getc(s
);
164 nexthop
.s_addr
= stream_get_ipv4(s
);
166 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_IFINDEX
)) {
167 api
.ifindex_num
= stream_getc(s
);
168 ifindex
= stream_getl(s
);
170 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
))
171 api
.distance
= stream_getc(s
);
174 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
))
175 api
.metric
= stream_getl(s
);
179 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_TAG
))
180 api
.tag
= stream_getl(s
);
184 /* Then fetch IPv4 prefixes. */
185 if (command
== ZEBRA_REDISTRIBUTE_IPV4_ADD
)
186 rip_redistribute_add(api
.type
, RIP_ROUTE_REDISTRIBUTE
, &p
,
187 ifindex
, &nexthop
, api
.metric
,
188 api
.distance
, api
.tag
);
189 else if (command
== ZEBRA_REDISTRIBUTE_IPV4_DEL
)
190 rip_redistribute_delete(api
.type
, RIP_ROUTE_REDISTRIBUTE
, &p
,
196 void rip_zclient_reset(void)
198 zclient_reset(zclient
);
201 /* RIP route-map set for redistribution */
202 static void rip_routemap_set(int type
, const char *name
)
204 if (rip
->route_map
[type
].name
)
205 free(rip
->route_map
[type
].name
);
207 rip
->route_map
[type
].name
= strdup(name
);
208 rip
->route_map
[type
].map
= route_map_lookup_by_name(name
);
211 static void rip_redistribute_metric_set(int type
, unsigned int metric
)
213 rip
->route_map
[type
].metric_config
= 1;
214 rip
->route_map
[type
].metric
= metric
;
217 static int rip_metric_unset(int type
, unsigned int metric
)
219 #define DONT_CARE_METRIC_RIP 17
220 if (metric
!= DONT_CARE_METRIC_RIP
221 && rip
->route_map
[type
].metric
!= metric
)
223 rip
->route_map
[type
].metric_config
= 0;
224 rip
->route_map
[type
].metric
= 0;
228 /* RIP route-map unset for redistribution */
229 static int rip_routemap_unset(int type
, const char *name
)
231 if (!rip
->route_map
[type
].name
232 || (name
!= NULL
&& strcmp(rip
->route_map
[type
].name
, name
)))
235 free(rip
->route_map
[type
].name
);
236 rip
->route_map
[type
].name
= NULL
;
237 rip
->route_map
[type
].map
= NULL
;
242 /* Redistribution types */
247 } redist_type
[] = {{ZEBRA_ROUTE_KERNEL
, 1, "kernel"},
248 {ZEBRA_ROUTE_CONNECT
, 1, "connected"},
249 {ZEBRA_ROUTE_STATIC
, 1, "static"},
250 {ZEBRA_ROUTE_OSPF
, 1, "ospf"},
251 {ZEBRA_ROUTE_BGP
, 2, "bgp"},
252 {ZEBRA_ROUTE_VNC
, 1, "vnc"},
255 static int rip_redistribute_unset(int type
)
257 if (!vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
))
260 vrf_bitmap_unset(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
262 if (zclient
->sock
> 0)
263 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
264 AFI_IP
, type
, 0, VRF_DEFAULT
);
266 /* Remove the routes from RIP table. */
267 rip_redistribute_withdraw(type
);
272 int rip_redistribute_check(int type
)
274 return vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
277 void rip_redistribute_clean(void)
281 for (i
= 0; redist_type
[i
].str
; i
++) {
282 if (vrf_bitmap_check(
283 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
285 if (zclient
->sock
> 0)
286 zebra_redistribute_send(
287 ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
288 AFI_IP
, redist_type
[i
].type
, 0,
292 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
295 /* Remove the routes from RIP table. */
296 rip_redistribute_withdraw(redist_type
[i
].type
);
301 DEFUN (rip_redistribute_rip
,
302 rip_redistribute_rip_cmd
,
304 "Redistribute information from another routing protocol\n"
305 "Routing Information Protocol (RIP)\n")
307 vrf_bitmap_set(zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_RIP
], VRF_DEFAULT
);
311 DEFUN (no_rip_redistribute_rip
,
312 no_rip_redistribute_rip_cmd
,
313 "no redistribute rip",
315 "Redistribute information from another routing protocol\n"
316 "Routing Information Protocol (RIP)\n")
318 vrf_bitmap_unset(zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_RIP
], VRF_DEFAULT
);
322 DEFUN (rip_redistribute_type
,
323 rip_redistribute_type_cmd
,
324 "redistribute " FRR_REDIST_STR_RIPD
,
326 FRR_REDIST_HELP_STR_RIPD
)
330 for (i
= 0; redist_type
[i
].str
; i
++) {
331 if (strncmp(redist_type
[i
].str
, argv
[1]->arg
,
332 redist_type
[i
].str_min_len
)
334 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
335 AFI_IP
, redist_type
[i
].type
, 0,
341 vty_out(vty
, "Invalid type %s\n", argv
[1]->arg
);
343 return CMD_WARNING_CONFIG_FAILED
;
346 DEFUN (no_rip_redistribute_type
,
347 no_rip_redistribute_type_cmd
,
348 "no redistribute " FRR_REDIST_STR_RIPD
,
351 FRR_REDIST_HELP_STR_RIPD
)
355 for (i
= 0; redist_type
[i
].str
; i
++) {
356 if (strncmp(redist_type
[i
].str
, argv
[2]->arg
,
357 redist_type
[i
].str_min_len
)
359 rip_metric_unset(redist_type
[i
].type
,
360 DONT_CARE_METRIC_RIP
);
361 rip_routemap_unset(redist_type
[i
].type
, NULL
);
362 rip_redistribute_unset(redist_type
[i
].type
);
367 vty_out(vty
, "Invalid type %s\n", argv
[2]->arg
);
369 return CMD_WARNING_CONFIG_FAILED
;
372 DEFUN (rip_redistribute_type_routemap
,
373 rip_redistribute_type_routemap_cmd
,
374 "redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
376 FRR_REDIST_HELP_STR_RIPD
377 "Route map reference\n"
378 "Pointer to route-map entries\n")
380 int idx_protocol
= 1;
384 for (i
= 0; redist_type
[i
].str
; i
++) {
385 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
386 rip_routemap_set(redist_type
[i
].type
,
387 argv
[idx_word
]->arg
);
388 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
389 AFI_IP
, redist_type
[i
].type
, 0,
395 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
397 return CMD_WARNING_CONFIG_FAILED
;
400 DEFUN (no_rip_redistribute_type_routemap
,
401 no_rip_redistribute_type_routemap_cmd
,
402 "no redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
405 FRR_REDIST_HELP_STR_RIPD
406 "Route map reference\n"
407 "Pointer to route-map entries\n")
409 int idx_protocol
= 2;
413 for (i
= 0; redist_type
[i
].str
; i
++) {
414 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
415 if (rip_routemap_unset(redist_type
[i
].type
,
416 argv
[idx_word
]->arg
))
417 return CMD_WARNING_CONFIG_FAILED
;
418 rip_redistribute_unset(redist_type
[i
].type
);
423 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
425 return CMD_WARNING_CONFIG_FAILED
;
428 DEFUN (rip_redistribute_type_metric
,
429 rip_redistribute_type_metric_cmd
,
430 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
432 FRR_REDIST_HELP_STR_RIPD
436 int idx_protocol
= 1;
441 metric
= atoi(argv
[idx_number
]->arg
);
443 for (i
= 0; redist_type
[i
].str
; i
++) {
444 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
445 rip_redistribute_metric_set(redist_type
[i
].type
,
447 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
448 AFI_IP
, redist_type
[i
].type
, 0,
454 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
456 return CMD_WARNING_CONFIG_FAILED
;
459 DEFUN (no_rip_redistribute_type_metric
,
460 no_rip_redistribute_type_metric_cmd
,
461 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
464 FRR_REDIST_HELP_STR_RIPD
468 int idx_protocol
= 2;
472 for (i
= 0; redist_type
[i
].str
; i
++) {
473 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
474 if (rip_metric_unset(redist_type
[i
].type
,
475 atoi(argv
[idx_number
]->arg
)))
476 return CMD_WARNING_CONFIG_FAILED
;
477 rip_redistribute_unset(redist_type
[i
].type
);
482 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
484 return CMD_WARNING_CONFIG_FAILED
;
487 DEFUN (rip_redistribute_type_metric_routemap
,
488 rip_redistribute_type_metric_routemap_cmd
,
489 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
491 FRR_REDIST_HELP_STR_RIPD
494 "Route map reference\n"
495 "Pointer to route-map entries\n")
497 int idx_protocol
= 1;
503 metric
= atoi(argv
[idx_number
]->arg
);
505 for (i
= 0; redist_type
[i
].str
; i
++) {
506 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
507 rip_redistribute_metric_set(redist_type
[i
].type
,
509 rip_routemap_set(redist_type
[i
].type
,
510 argv
[idx_word
]->arg
);
511 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
512 AFI_IP
, redist_type
[i
].type
, 0,
518 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
520 return CMD_WARNING_CONFIG_FAILED
;
524 DEFUN (no_rip_redistribute_type_metric_routemap
,
525 no_rip_redistribute_type_metric_routemap_cmd
,
526 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
529 FRR_REDIST_HELP_STR_RIPD
532 "Route map reference\n"
533 "Pointer to route-map entries\n")
535 int idx_protocol
= 2;
540 for (i
= 0; redist_type
[i
].str
; i
++) {
541 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
542 if (rip_metric_unset(redist_type
[i
].type
,
543 atoi(argv
[idx_number
]->arg
)))
544 return CMD_WARNING_CONFIG_FAILED
;
545 if (rip_routemap_unset(redist_type
[i
].type
,
546 argv
[idx_word
]->arg
)) {
547 rip_redistribute_metric_set(
549 atoi(argv
[idx_number
]->arg
));
550 return CMD_WARNING_CONFIG_FAILED
;
552 rip_redistribute_unset(redist_type
[i
].type
);
557 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
559 return CMD_WARNING_CONFIG_FAILED
;
562 /* Default information originate. */
564 DEFUN (rip_default_information_originate
,
565 rip_default_information_originate_cmd
,
566 "default-information originate",
567 "Control distribution of default route\n"
568 "Distribute a default route\n")
570 struct prefix_ipv4 p
;
572 if (!rip
->default_information
) {
573 memset(&p
, 0, sizeof(struct prefix_ipv4
));
576 rip
->default_information
= 1;
578 rip_redistribute_add(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
, 0,
585 DEFUN (no_rip_default_information_originate
,
586 no_rip_default_information_originate_cmd
,
587 "no default-information originate",
589 "Control distribution of default route\n"
590 "Distribute a default route\n")
592 struct prefix_ipv4 p
;
594 if (rip
->default_information
) {
595 memset(&p
, 0, sizeof(struct prefix_ipv4
));
598 rip
->default_information
= 0;
600 rip_redistribute_delete(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
,
607 /* RIP configuration write function. */
608 static int config_write_zebra(struct vty
*vty
)
610 if (!zclient
->enable
) {
611 vty_out(vty
, "no router zebra\n");
613 } else if (!vrf_bitmap_check(zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_RIP
],
615 vty_out(vty
, "router zebra\n");
616 vty_out(vty
, " no redistribute rip\n");
622 int config_write_rip_redistribute(struct vty
*vty
, int config_mode
)
626 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
627 if (i
!= zclient
->redist_default
628 && vrf_bitmap_check(zclient
->redist
[AFI_IP
][i
],
631 if (rip
->route_map
[i
].metric_config
) {
632 if (rip
->route_map
[i
].name
)
634 " redistribute %s metric %d route-map %s\n",
635 zebra_route_string(i
),
638 rip
->route_map
[i
].name
);
641 " redistribute %s metric %d\n",
642 zebra_route_string(i
),
646 if (rip
->route_map
[i
].name
)
648 " redistribute %s route-map %s\n",
649 zebra_route_string(i
),
650 rip
->route_map
[i
].name
);
653 " redistribute %s\n",
654 zebra_route_string(i
));
657 vty_out(vty
, " %s", zebra_route_string(i
));
662 /* Zebra node structure. */
663 static struct cmd_node zebra_node
= {
665 "%s(config-router)# ",
668 static void rip_zebra_connected(struct zclient
*zclient
)
670 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
673 void rip_zclient_init(struct thread_master
*master
)
675 /* Set default value to the zebra client structure. */
676 zclient
= zclient_new(master
);
677 zclient_init(zclient
, ZEBRA_ROUTE_RIP
, 0);
678 zclient
->zebra_connected
= rip_zebra_connected
;
679 zclient
->interface_add
= rip_interface_add
;
680 zclient
->interface_delete
= rip_interface_delete
;
681 zclient
->interface_address_add
= rip_interface_address_add
;
682 zclient
->interface_address_delete
= rip_interface_address_delete
;
683 zclient
->interface_up
= rip_interface_up
;
684 zclient
->interface_down
= rip_interface_down
;
685 zclient
->redistribute_route_ipv4_add
= rip_zebra_read_ipv4
;
686 zclient
->redistribute_route_ipv4_del
= rip_zebra_read_ipv4
;
688 /* Install zebra node. */
689 install_node(&zebra_node
, config_write_zebra
);
691 /* Install command elements to zebra node. */
692 install_default(ZEBRA_NODE
);
693 install_element(ZEBRA_NODE
, &rip_redistribute_rip_cmd
);
694 install_element(ZEBRA_NODE
, &no_rip_redistribute_rip_cmd
);
696 /* Install command elements to rip node. */
697 install_element(RIP_NODE
, &rip_redistribute_type_cmd
);
698 install_element(RIP_NODE
, &rip_redistribute_type_routemap_cmd
);
699 install_element(RIP_NODE
, &rip_redistribute_type_metric_cmd
);
700 install_element(RIP_NODE
, &rip_redistribute_type_metric_routemap_cmd
);
701 install_element(RIP_NODE
, &no_rip_redistribute_type_cmd
);
702 install_element(RIP_NODE
, &no_rip_redistribute_type_routemap_cmd
);
703 install_element(RIP_NODE
, &no_rip_redistribute_type_metric_cmd
);
704 install_element(RIP_NODE
,
705 &no_rip_redistribute_type_metric_routemap_cmd
);
706 install_element(RIP_NODE
, &rip_default_information_originate_cmd
);
707 install_element(RIP_NODE
, &no_rip_default_information_originate_cmd
);
710 void rip_zclient_stop(void)
712 zclient_stop(zclient
);
713 zclient_free(zclient
);