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 struct list
*list
= (struct list
*)rp
->info
;
43 struct zapi_route api
;
44 struct zapi_nexthop
*api_nh
;
45 struct listnode
*listnode
= NULL
;
46 struct rip_info
*rinfo
= NULL
;
49 memset(&api
, 0, sizeof(api
));
50 api
.vrf_id
= VRF_DEFAULT
;
51 api
.type
= ZEBRA_ROUTE_RIP
;
52 api
.safi
= SAFI_UNICAST
;
54 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
55 for (ALL_LIST_ELEMENTS_RO(list
, listnode
, rinfo
)) {
56 if (count
>= MULTIPATH_NUM
)
58 api_nh
= &api
.nexthops
[count
];
59 api_nh
->vrf_id
= VRF_DEFAULT
;
60 api_nh
->gate
= rinfo
->nh
.gate
;
61 api_nh
->type
= NEXTHOP_TYPE_IPV4
;
62 if (cmd
== ZEBRA_ROUTE_ADD
)
63 SET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
65 UNSET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
70 api
.nexthop_num
= count
;
72 rinfo
= listgetdata(listhead(list
));
74 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
75 api
.metric
= rinfo
->metric
;
77 if (rinfo
->distance
&& rinfo
->distance
!= ZEBRA_RIP_DISTANCE_DEFAULT
) {
78 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
79 api
.distance
= rinfo
->distance
;
83 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
87 zclient_route_send(cmd
, zclient
, &api
);
89 if (IS_RIP_DEBUG_ZEBRA
) {
91 zlog_debug("%s: %s/%d nexthops %d",
92 (cmd
== ZEBRA_ROUTE_ADD
)
93 ? "Install into zebra"
94 : "Delete from zebra",
95 inet_ntoa(rp
->p
.u
.prefix4
), rp
->p
.prefixlen
,
98 zlog_debug("%s: %s/%d",
99 (cmd
== ZEBRA_ROUTE_ADD
)
100 ? "Install into zebra"
101 : "Delete from zebra",
102 inet_ntoa(rp
->p
.u
.prefix4
), rp
->p
.prefixlen
);
105 rip_global_route_changes
++;
108 /* Add/update ECMP routes to zebra. */
109 void rip_zebra_ipv4_add(struct route_node
*rp
)
111 rip_zebra_ipv4_send(rp
, ZEBRA_ROUTE_ADD
);
114 /* Delete ECMP routes from zebra. */
115 void rip_zebra_ipv4_delete(struct route_node
*rp
)
117 rip_zebra_ipv4_send(rp
, ZEBRA_ROUTE_DELETE
);
120 /* Zebra route add and delete treatment. */
121 static int rip_zebra_read_route(int command
, struct zclient
*zclient
,
122 zebra_size_t length
, vrf_id_t vrf_id
)
124 struct zapi_route api
;
130 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
133 memset(&nh
, 0, sizeof(nh
));
134 nh
.type
= api
.nexthops
[0].type
;
135 nh
.gate
.ipv4
= api
.nexthops
[0].gate
.ipv4
;
136 nh
.ifindex
= api
.nexthops
[0].ifindex
;
138 /* Then fetch IPv4 prefixes. */
139 if (command
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
)
140 rip_redistribute_add(api
.type
, RIP_ROUTE_REDISTRIBUTE
,
141 (struct prefix_ipv4
*)&api
.prefix
, &nh
,
142 api
.metric
, api
.distance
,
144 else if (command
== ZEBRA_REDISTRIBUTE_ROUTE_DEL
)
145 rip_redistribute_delete(api
.type
, RIP_ROUTE_REDISTRIBUTE
,
146 (struct prefix_ipv4
*)&api
.prefix
,
152 void rip_zclient_reset(void)
154 zclient_reset(zclient
);
157 /* RIP route-map set for redistribution */
158 static void rip_routemap_set(int type
, const char *name
)
160 if (rip
->route_map
[type
].name
)
161 free(rip
->route_map
[type
].name
);
163 rip
->route_map
[type
].name
= strdup(name
);
164 rip
->route_map
[type
].map
= route_map_lookup_by_name(name
);
167 static void rip_redistribute_metric_set(int type
, unsigned int metric
)
169 rip
->route_map
[type
].metric_config
= 1;
170 rip
->route_map
[type
].metric
= metric
;
173 static int rip_metric_unset(int type
, unsigned int metric
)
175 #define DONT_CARE_METRIC_RIP 17
176 if (metric
!= DONT_CARE_METRIC_RIP
177 && rip
->route_map
[type
].metric
!= metric
)
179 rip
->route_map
[type
].metric_config
= 0;
180 rip
->route_map
[type
].metric
= 0;
184 /* RIP route-map unset for redistribution */
185 static int rip_routemap_unset(int type
, const char *name
)
187 if (!rip
->route_map
[type
].name
188 || (name
!= NULL
&& strcmp(rip
->route_map
[type
].name
, name
)))
191 free(rip
->route_map
[type
].name
);
192 rip
->route_map
[type
].name
= NULL
;
193 rip
->route_map
[type
].map
= NULL
;
198 /* Redistribution types */
203 } redist_type
[] = {{ZEBRA_ROUTE_KERNEL
, 1, "kernel"},
204 {ZEBRA_ROUTE_CONNECT
, 1, "connected"},
205 {ZEBRA_ROUTE_STATIC
, 1, "static"},
206 {ZEBRA_ROUTE_OSPF
, 1, "ospf"},
207 {ZEBRA_ROUTE_BGP
, 2, "bgp"},
208 {ZEBRA_ROUTE_VNC
, 1, "vnc"},
211 static int rip_redistribute_unset(int type
)
213 if (!vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
))
216 vrf_bitmap_unset(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
218 if (zclient
->sock
> 0)
219 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
220 AFI_IP
, type
, 0, VRF_DEFAULT
);
222 /* Remove the routes from RIP table. */
223 rip_redistribute_withdraw(type
);
228 int rip_redistribute_check(int type
)
230 return vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
233 void rip_redistribute_clean(void)
237 for (i
= 0; redist_type
[i
].str
; i
++) {
238 if (vrf_bitmap_check(
239 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
241 if (zclient
->sock
> 0)
242 zebra_redistribute_send(
243 ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
244 AFI_IP
, redist_type
[i
].type
, 0,
248 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
251 /* Remove the routes from RIP table. */
252 rip_redistribute_withdraw(redist_type
[i
].type
);
257 DEFUN (rip_redistribute_type
,
258 rip_redistribute_type_cmd
,
259 "redistribute " FRR_REDIST_STR_RIPD
,
261 FRR_REDIST_HELP_STR_RIPD
)
265 for (i
= 0; redist_type
[i
].str
; i
++) {
266 if (strncmp(redist_type
[i
].str
, argv
[1]->arg
,
267 redist_type
[i
].str_min_len
)
269 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
270 AFI_IP
, redist_type
[i
].type
, 0,
276 vty_out(vty
, "Invalid type %s\n", argv
[1]->arg
);
278 return CMD_WARNING_CONFIG_FAILED
;
281 DEFUN (no_rip_redistribute_type
,
282 no_rip_redistribute_type_cmd
,
283 "no redistribute " FRR_REDIST_STR_RIPD
,
286 FRR_REDIST_HELP_STR_RIPD
)
290 for (i
= 0; redist_type
[i
].str
; i
++) {
291 if (strncmp(redist_type
[i
].str
, argv
[2]->arg
,
292 redist_type
[i
].str_min_len
)
294 rip_metric_unset(redist_type
[i
].type
,
295 DONT_CARE_METRIC_RIP
);
296 rip_routemap_unset(redist_type
[i
].type
, NULL
);
297 rip_redistribute_unset(redist_type
[i
].type
);
302 vty_out(vty
, "Invalid type %s\n", argv
[2]->arg
);
304 return CMD_WARNING_CONFIG_FAILED
;
307 DEFUN (rip_redistribute_type_routemap
,
308 rip_redistribute_type_routemap_cmd
,
309 "redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
311 FRR_REDIST_HELP_STR_RIPD
312 "Route map reference\n"
313 "Pointer to route-map entries\n")
315 int idx_protocol
= 1;
319 for (i
= 0; redist_type
[i
].str
; i
++) {
320 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
321 rip_routemap_set(redist_type
[i
].type
,
322 argv
[idx_word
]->arg
);
323 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
324 AFI_IP
, redist_type
[i
].type
, 0,
330 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
332 return CMD_WARNING_CONFIG_FAILED
;
335 DEFUN (no_rip_redistribute_type_routemap
,
336 no_rip_redistribute_type_routemap_cmd
,
337 "no redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
340 FRR_REDIST_HELP_STR_RIPD
341 "Route map reference\n"
342 "Pointer to route-map entries\n")
344 int idx_protocol
= 2;
348 for (i
= 0; redist_type
[i
].str
; i
++) {
349 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
350 if (rip_routemap_unset(redist_type
[i
].type
,
351 argv
[idx_word
]->arg
))
352 return CMD_WARNING_CONFIG_FAILED
;
353 rip_redistribute_unset(redist_type
[i
].type
);
358 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
360 return CMD_WARNING_CONFIG_FAILED
;
363 DEFUN (rip_redistribute_type_metric
,
364 rip_redistribute_type_metric_cmd
,
365 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
367 FRR_REDIST_HELP_STR_RIPD
371 int idx_protocol
= 1;
376 metric
= atoi(argv
[idx_number
]->arg
);
378 for (i
= 0; redist_type
[i
].str
; i
++) {
379 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
380 rip_redistribute_metric_set(redist_type
[i
].type
,
382 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
383 AFI_IP
, redist_type
[i
].type
, 0,
389 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
391 return CMD_WARNING_CONFIG_FAILED
;
394 DEFUN (no_rip_redistribute_type_metric
,
395 no_rip_redistribute_type_metric_cmd
,
396 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
399 FRR_REDIST_HELP_STR_RIPD
403 int idx_protocol
= 2;
407 for (i
= 0; redist_type
[i
].str
; i
++) {
408 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
409 if (rip_metric_unset(redist_type
[i
].type
,
410 atoi(argv
[idx_number
]->arg
)))
411 return CMD_WARNING_CONFIG_FAILED
;
412 rip_redistribute_unset(redist_type
[i
].type
);
417 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
419 return CMD_WARNING_CONFIG_FAILED
;
422 DEFUN (rip_redistribute_type_metric_routemap
,
423 rip_redistribute_type_metric_routemap_cmd
,
424 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
426 FRR_REDIST_HELP_STR_RIPD
429 "Route map reference\n"
430 "Pointer to route-map entries\n")
432 int idx_protocol
= 1;
438 metric
= atoi(argv
[idx_number
]->arg
);
440 for (i
= 0; redist_type
[i
].str
; i
++) {
441 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
442 rip_redistribute_metric_set(redist_type
[i
].type
,
444 rip_routemap_set(redist_type
[i
].type
,
445 argv
[idx_word
]->arg
);
446 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
447 AFI_IP
, redist_type
[i
].type
, 0,
453 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
455 return CMD_WARNING_CONFIG_FAILED
;
459 DEFUN (no_rip_redistribute_type_metric_routemap
,
460 no_rip_redistribute_type_metric_routemap_cmd
,
461 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
464 FRR_REDIST_HELP_STR_RIPD
467 "Route map reference\n"
468 "Pointer to route-map entries\n")
470 int idx_protocol
= 2;
475 for (i
= 0; redist_type
[i
].str
; i
++) {
476 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
477 if (rip_metric_unset(redist_type
[i
].type
,
478 atoi(argv
[idx_number
]->arg
)))
479 return CMD_WARNING_CONFIG_FAILED
;
480 if (rip_routemap_unset(redist_type
[i
].type
,
481 argv
[idx_word
]->arg
)) {
482 rip_redistribute_metric_set(
484 atoi(argv
[idx_number
]->arg
));
485 return CMD_WARNING_CONFIG_FAILED
;
487 rip_redistribute_unset(redist_type
[i
].type
);
492 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
494 return CMD_WARNING_CONFIG_FAILED
;
497 /* Default information originate. */
499 DEFUN (rip_default_information_originate
,
500 rip_default_information_originate_cmd
,
501 "default-information originate",
502 "Control distribution of default route\n"
503 "Distribute a default route\n")
505 struct prefix_ipv4 p
;
508 if (!rip
->default_information
) {
509 memset(&p
, 0, sizeof(struct prefix_ipv4
));
510 memset(&nh
, 0, sizeof(nh
));
513 nh
.type
= NEXTHOP_TYPE_IPV4
;
515 rip
->default_information
= 1;
517 rip_redistribute_add(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
,
524 DEFUN (no_rip_default_information_originate
,
525 no_rip_default_information_originate_cmd
,
526 "no default-information originate",
528 "Control distribution of default route\n"
529 "Distribute a default route\n")
531 struct prefix_ipv4 p
;
533 if (rip
->default_information
) {
534 memset(&p
, 0, sizeof(struct prefix_ipv4
));
537 rip
->default_information
= 0;
539 rip_redistribute_delete(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
,
546 int config_write_rip_redistribute(struct vty
*vty
, int config_mode
)
550 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
551 if (i
== zclient
->redist_default
552 || !vrf_bitmap_check(zclient
->redist
[AFI_IP
][i
],
557 vty_out(vty
, " %s", zebra_route_string(i
));
561 if (rip
->route_map
[i
].metric_config
) {
562 if (rip
->route_map
[i
].name
)
564 " redistribute %s metric %d route-map %s\n",
565 zebra_route_string(i
),
566 rip
->route_map
[i
].metric
,
567 rip
->route_map
[i
].name
);
569 vty_out(vty
, " redistribute %s metric %d\n",
570 zebra_route_string(i
),
571 rip
->route_map
[i
].metric
);
573 if (rip
->route_map
[i
].name
)
574 vty_out(vty
, " redistribute %s route-map %s\n",
575 zebra_route_string(i
),
576 rip
->route_map
[i
].name
);
578 vty_out(vty
, " redistribute %s\n",
579 zebra_route_string(i
));
586 static void rip_zebra_connected(struct zclient
*zclient
)
588 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
591 void rip_zclient_init(struct thread_master
*master
)
593 /* Set default value to the zebra client structure. */
594 zclient
= zclient_new_notify(master
, &zclient_options_default
);
595 zclient_init(zclient
, ZEBRA_ROUTE_RIP
, 0, &ripd_privs
);
596 zclient
->zebra_connected
= rip_zebra_connected
;
597 zclient
->interface_add
= rip_interface_add
;
598 zclient
->interface_delete
= rip_interface_delete
;
599 zclient
->interface_address_add
= rip_interface_address_add
;
600 zclient
->interface_address_delete
= rip_interface_address_delete
;
601 zclient
->interface_up
= rip_interface_up
;
602 zclient
->interface_down
= rip_interface_down
;
603 zclient
->redistribute_route_add
= rip_zebra_read_route
;
604 zclient
->redistribute_route_del
= rip_zebra_read_route
;
606 /* Install command elements to rip node. */
607 install_element(RIP_NODE
, &rip_redistribute_type_cmd
);
608 install_element(RIP_NODE
, &rip_redistribute_type_routemap_cmd
);
609 install_element(RIP_NODE
, &rip_redistribute_type_metric_cmd
);
610 install_element(RIP_NODE
, &rip_redistribute_type_metric_routemap_cmd
);
611 install_element(RIP_NODE
, &no_rip_redistribute_type_cmd
);
612 install_element(RIP_NODE
, &no_rip_redistribute_type_routemap_cmd
);
613 install_element(RIP_NODE
, &no_rip_redistribute_type_metric_cmd
);
614 install_element(RIP_NODE
,
615 &no_rip_redistribute_type_metric_routemap_cmd
);
616 install_element(RIP_NODE
, &rip_default_information_originate_cmd
);
617 install_element(RIP_NODE
, &no_rip_default_information_originate_cmd
);
620 void rip_zclient_stop(void)
622 zclient_stop(zclient
);
623 zclient_free(zclient
);