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
->gate
= rinfo
->nh
.gate
;
60 api_nh
->type
= NEXTHOP_TYPE_IPV4
;
61 if (cmd
== ZEBRA_ROUTE_ADD
)
62 SET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
64 UNSET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
69 api
.nexthop_num
= count
;
71 rinfo
= listgetdata(listhead(list
));
73 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
74 api
.metric
= rinfo
->metric
;
76 if (rinfo
->distance
&& rinfo
->distance
!= ZEBRA_RIP_DISTANCE_DEFAULT
) {
77 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
78 api
.distance
= rinfo
->distance
;
82 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
86 zclient_route_send(cmd
, zclient
, &api
);
88 if (IS_RIP_DEBUG_ZEBRA
) {
90 zlog_debug("%s: %s/%d nexthops %d",
91 (cmd
== ZEBRA_ROUTE_ADD
)
92 ? "Install into zebra"
93 : "Delete from zebra",
94 inet_ntoa(rp
->p
.u
.prefix4
), rp
->p
.prefixlen
,
97 zlog_debug("%s: %s/%d",
98 (cmd
== ZEBRA_ROUTE_ADD
)
99 ? "Install into zebra"
100 : "Delete from zebra",
101 inet_ntoa(rp
->p
.u
.prefix4
), rp
->p
.prefixlen
);
104 rip_global_route_changes
++;
107 /* Add/update ECMP routes to zebra. */
108 void rip_zebra_ipv4_add(struct route_node
*rp
)
110 rip_zebra_ipv4_send(rp
, ZEBRA_ROUTE_ADD
);
113 /* Delete ECMP routes from zebra. */
114 void rip_zebra_ipv4_delete(struct route_node
*rp
)
116 rip_zebra_ipv4_send(rp
, ZEBRA_ROUTE_DELETE
);
119 /* Zebra route add and delete treatment. */
120 static int rip_zebra_read_route(int command
, struct zclient
*zclient
,
121 zebra_size_t length
, vrf_id_t vrf_id
)
123 struct zapi_route api
;
129 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
132 memset(&nh
, 0, sizeof(nh
));
133 nh
.type
= api
.nexthops
[0].type
;
134 nh
.gate
.ipv4
= api
.nexthops
[0].gate
.ipv4
;
135 nh
.ifindex
= api
.nexthops
[0].ifindex
;
137 /* Then fetch IPv4 prefixes. */
138 if (command
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
)
139 rip_redistribute_add(api
.type
, RIP_ROUTE_REDISTRIBUTE
,
140 (struct prefix_ipv4
*)&api
.prefix
, &nh
,
141 api
.metric
, api
.distance
,
143 else if (command
== ZEBRA_REDISTRIBUTE_ROUTE_DEL
)
144 rip_redistribute_delete(api
.type
, RIP_ROUTE_REDISTRIBUTE
,
145 (struct prefix_ipv4
*)&api
.prefix
,
151 void rip_zclient_reset(void)
153 zclient_reset(zclient
);
156 /* RIP route-map set for redistribution */
157 static void rip_routemap_set(int type
, const char *name
)
159 if (rip
->route_map
[type
].name
)
160 free(rip
->route_map
[type
].name
);
162 rip
->route_map
[type
].name
= strdup(name
);
163 rip
->route_map
[type
].map
= route_map_lookup_by_name(name
);
166 static void rip_redistribute_metric_set(int type
, unsigned int metric
)
168 rip
->route_map
[type
].metric_config
= 1;
169 rip
->route_map
[type
].metric
= metric
;
172 static int rip_metric_unset(int type
, unsigned int metric
)
174 #define DONT_CARE_METRIC_RIP 17
175 if (metric
!= DONT_CARE_METRIC_RIP
176 && rip
->route_map
[type
].metric
!= metric
)
178 rip
->route_map
[type
].metric_config
= 0;
179 rip
->route_map
[type
].metric
= 0;
183 /* RIP route-map unset for redistribution */
184 static int rip_routemap_unset(int type
, const char *name
)
186 if (!rip
->route_map
[type
].name
187 || (name
!= NULL
&& strcmp(rip
->route_map
[type
].name
, name
)))
190 free(rip
->route_map
[type
].name
);
191 rip
->route_map
[type
].name
= NULL
;
192 rip
->route_map
[type
].map
= NULL
;
197 /* Redistribution types */
202 } redist_type
[] = {{ZEBRA_ROUTE_KERNEL
, 1, "kernel"},
203 {ZEBRA_ROUTE_CONNECT
, 1, "connected"},
204 {ZEBRA_ROUTE_STATIC
, 1, "static"},
205 {ZEBRA_ROUTE_OSPF
, 1, "ospf"},
206 {ZEBRA_ROUTE_BGP
, 2, "bgp"},
207 {ZEBRA_ROUTE_VNC
, 1, "vnc"},
210 static int rip_redistribute_unset(int type
)
212 if (!vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
))
215 vrf_bitmap_unset(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
217 if (zclient
->sock
> 0)
218 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
219 AFI_IP
, type
, 0, VRF_DEFAULT
);
221 /* Remove the routes from RIP table. */
222 rip_redistribute_withdraw(type
);
227 int rip_redistribute_check(int type
)
229 return vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
232 void rip_redistribute_clean(void)
236 for (i
= 0; redist_type
[i
].str
; i
++) {
237 if (vrf_bitmap_check(
238 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
240 if (zclient
->sock
> 0)
241 zebra_redistribute_send(
242 ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
243 AFI_IP
, redist_type
[i
].type
, 0,
247 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
250 /* Remove the routes from RIP table. */
251 rip_redistribute_withdraw(redist_type
[i
].type
);
256 DEFUN (rip_redistribute_type
,
257 rip_redistribute_type_cmd
,
258 "redistribute " FRR_REDIST_STR_RIPD
,
260 FRR_REDIST_HELP_STR_RIPD
)
264 for (i
= 0; redist_type
[i
].str
; i
++) {
265 if (strncmp(redist_type
[i
].str
, argv
[1]->arg
,
266 redist_type
[i
].str_min_len
)
268 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
269 AFI_IP
, redist_type
[i
].type
, 0,
275 vty_out(vty
, "Invalid type %s\n", argv
[1]->arg
);
277 return CMD_WARNING_CONFIG_FAILED
;
280 DEFUN (no_rip_redistribute_type
,
281 no_rip_redistribute_type_cmd
,
282 "no redistribute " FRR_REDIST_STR_RIPD
,
285 FRR_REDIST_HELP_STR_RIPD
)
289 for (i
= 0; redist_type
[i
].str
; i
++) {
290 if (strncmp(redist_type
[i
].str
, argv
[2]->arg
,
291 redist_type
[i
].str_min_len
)
293 rip_metric_unset(redist_type
[i
].type
,
294 DONT_CARE_METRIC_RIP
);
295 rip_routemap_unset(redist_type
[i
].type
, NULL
);
296 rip_redistribute_unset(redist_type
[i
].type
);
301 vty_out(vty
, "Invalid type %s\n", argv
[2]->arg
);
303 return CMD_WARNING_CONFIG_FAILED
;
306 DEFUN (rip_redistribute_type_routemap
,
307 rip_redistribute_type_routemap_cmd
,
308 "redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
310 FRR_REDIST_HELP_STR_RIPD
311 "Route map reference\n"
312 "Pointer to route-map entries\n")
314 int idx_protocol
= 1;
318 for (i
= 0; redist_type
[i
].str
; i
++) {
319 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
320 rip_routemap_set(redist_type
[i
].type
,
321 argv
[idx_word
]->arg
);
322 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
323 AFI_IP
, redist_type
[i
].type
, 0,
329 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
331 return CMD_WARNING_CONFIG_FAILED
;
334 DEFUN (no_rip_redistribute_type_routemap
,
335 no_rip_redistribute_type_routemap_cmd
,
336 "no redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
339 FRR_REDIST_HELP_STR_RIPD
340 "Route map reference\n"
341 "Pointer to route-map entries\n")
343 int idx_protocol
= 2;
347 for (i
= 0; redist_type
[i
].str
; i
++) {
348 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
349 if (rip_routemap_unset(redist_type
[i
].type
,
350 argv
[idx_word
]->arg
))
351 return CMD_WARNING_CONFIG_FAILED
;
352 rip_redistribute_unset(redist_type
[i
].type
);
357 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
359 return CMD_WARNING_CONFIG_FAILED
;
362 DEFUN (rip_redistribute_type_metric
,
363 rip_redistribute_type_metric_cmd
,
364 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
366 FRR_REDIST_HELP_STR_RIPD
370 int idx_protocol
= 1;
375 metric
= atoi(argv
[idx_number
]->arg
);
377 for (i
= 0; redist_type
[i
].str
; i
++) {
378 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
379 rip_redistribute_metric_set(redist_type
[i
].type
,
381 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
382 AFI_IP
, redist_type
[i
].type
, 0,
388 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
390 return CMD_WARNING_CONFIG_FAILED
;
393 DEFUN (no_rip_redistribute_type_metric
,
394 no_rip_redistribute_type_metric_cmd
,
395 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
398 FRR_REDIST_HELP_STR_RIPD
402 int idx_protocol
= 2;
406 for (i
= 0; redist_type
[i
].str
; i
++) {
407 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
408 if (rip_metric_unset(redist_type
[i
].type
,
409 atoi(argv
[idx_number
]->arg
)))
410 return CMD_WARNING_CONFIG_FAILED
;
411 rip_redistribute_unset(redist_type
[i
].type
);
416 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
418 return CMD_WARNING_CONFIG_FAILED
;
421 DEFUN (rip_redistribute_type_metric_routemap
,
422 rip_redistribute_type_metric_routemap_cmd
,
423 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
425 FRR_REDIST_HELP_STR_RIPD
428 "Route map reference\n"
429 "Pointer to route-map entries\n")
431 int idx_protocol
= 1;
437 metric
= atoi(argv
[idx_number
]->arg
);
439 for (i
= 0; redist_type
[i
].str
; i
++) {
440 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
441 rip_redistribute_metric_set(redist_type
[i
].type
,
443 rip_routemap_set(redist_type
[i
].type
,
444 argv
[idx_word
]->arg
);
445 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
446 AFI_IP
, redist_type
[i
].type
, 0,
452 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
454 return CMD_WARNING_CONFIG_FAILED
;
458 DEFUN (no_rip_redistribute_type_metric_routemap
,
459 no_rip_redistribute_type_metric_routemap_cmd
,
460 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
463 FRR_REDIST_HELP_STR_RIPD
466 "Route map reference\n"
467 "Pointer to route-map entries\n")
469 int idx_protocol
= 2;
474 for (i
= 0; redist_type
[i
].str
; i
++) {
475 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
476 if (rip_metric_unset(redist_type
[i
].type
,
477 atoi(argv
[idx_number
]->arg
)))
478 return CMD_WARNING_CONFIG_FAILED
;
479 if (rip_routemap_unset(redist_type
[i
].type
,
480 argv
[idx_word
]->arg
)) {
481 rip_redistribute_metric_set(
483 atoi(argv
[idx_number
]->arg
));
484 return CMD_WARNING_CONFIG_FAILED
;
486 rip_redistribute_unset(redist_type
[i
].type
);
491 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
493 return CMD_WARNING_CONFIG_FAILED
;
496 /* Default information originate. */
498 DEFUN (rip_default_information_originate
,
499 rip_default_information_originate_cmd
,
500 "default-information originate",
501 "Control distribution of default route\n"
502 "Distribute a default route\n")
504 struct prefix_ipv4 p
;
507 if (!rip
->default_information
) {
508 memset(&p
, 0, sizeof(struct prefix_ipv4
));
509 memset(&nh
, 0, sizeof(nh
));
512 nh
.type
= NEXTHOP_TYPE_IPV4
;
514 rip
->default_information
= 1;
516 rip_redistribute_add(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
,
523 DEFUN (no_rip_default_information_originate
,
524 no_rip_default_information_originate_cmd
,
525 "no default-information originate",
527 "Control distribution of default route\n"
528 "Distribute a default route\n")
530 struct prefix_ipv4 p
;
532 if (rip
->default_information
) {
533 memset(&p
, 0, sizeof(struct prefix_ipv4
));
536 rip
->default_information
= 0;
538 rip_redistribute_delete(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
,
545 int config_write_rip_redistribute(struct vty
*vty
, int config_mode
)
549 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
550 if (i
== zclient
->redist_default
551 || !vrf_bitmap_check(zclient
->redist
[AFI_IP
][i
],
556 vty_out(vty
, " %s", zebra_route_string(i
));
560 if (rip
->route_map
[i
].metric_config
) {
561 if (rip
->route_map
[i
].name
)
563 " redistribute %s metric %d route-map %s\n",
564 zebra_route_string(i
),
565 rip
->route_map
[i
].metric
,
566 rip
->route_map
[i
].name
);
568 vty_out(vty
, " redistribute %s metric %d\n",
569 zebra_route_string(i
),
570 rip
->route_map
[i
].metric
);
572 if (rip
->route_map
[i
].name
)
573 vty_out(vty
, " redistribute %s route-map %s\n",
574 zebra_route_string(i
),
575 rip
->route_map
[i
].name
);
577 vty_out(vty
, " redistribute %s\n",
578 zebra_route_string(i
));
585 static void rip_zebra_connected(struct zclient
*zclient
)
587 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
590 void rip_zclient_init(struct thread_master
*master
)
592 /* Set default value to the zebra client structure. */
593 zclient
= zclient_new_notify(master
, &zclient_options_default
);
594 zclient_init(zclient
, ZEBRA_ROUTE_RIP
, 0, &ripd_privs
);
595 zclient
->zebra_connected
= rip_zebra_connected
;
596 zclient
->interface_add
= rip_interface_add
;
597 zclient
->interface_delete
= rip_interface_delete
;
598 zclient
->interface_address_add
= rip_interface_address_add
;
599 zclient
->interface_address_delete
= rip_interface_address_delete
;
600 zclient
->interface_up
= rip_interface_up
;
601 zclient
->interface_down
= rip_interface_down
;
602 zclient
->redistribute_route_add
= rip_zebra_read_route
;
603 zclient
->redistribute_route_del
= rip_zebra_read_route
;
605 /* Install command elements to rip node. */
606 install_element(RIP_NODE
, &rip_redistribute_type_cmd
);
607 install_element(RIP_NODE
, &rip_redistribute_type_routemap_cmd
);
608 install_element(RIP_NODE
, &rip_redistribute_type_metric_cmd
);
609 install_element(RIP_NODE
, &rip_redistribute_type_metric_routemap_cmd
);
610 install_element(RIP_NODE
, &no_rip_redistribute_type_cmd
);
611 install_element(RIP_NODE
, &no_rip_redistribute_type_routemap_cmd
);
612 install_element(RIP_NODE
, &no_rip_redistribute_type_metric_cmd
);
613 install_element(RIP_NODE
,
614 &no_rip_redistribute_type_metric_routemap_cmd
);
615 install_element(RIP_NODE
, &rip_default_information_originate_cmd
);
616 install_element(RIP_NODE
, &no_rip_default_information_originate_cmd
);
619 void rip_zclient_stop(void)
621 zclient_stop(zclient
);
622 zclient_free(zclient
);