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 api_nh
= &api
.nexthops
[count
];
57 api_nh
->gate
.ipv4
= rinfo
->nexthop
;
58 api_nh
->type
= NEXTHOP_TYPE_IPV4
;
59 if (cmd
== ZEBRA_ROUTE_ADD
)
60 SET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
62 UNSET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
67 api
.nexthop_num
= count
;
69 rinfo
= listgetdata(listhead(list
));
71 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
72 api
.metric
= rinfo
->metric
;
74 if (rinfo
->distance
&& rinfo
->distance
!= ZEBRA_RIP_DISTANCE_DEFAULT
) {
75 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
76 api
.distance
= rinfo
->distance
;
80 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
84 zclient_route_send(cmd
, zclient
, &api
);
86 if (IS_RIP_DEBUG_ZEBRA
) {
88 zlog_debug("%s: %s/%d nexthops %d",
89 (cmd
== ZEBRA_ROUTE_ADD
)
90 ? "Install into zebra"
91 : "Delete from zebra",
92 inet_ntoa(rp
->p
.u
.prefix4
), rp
->p
.prefixlen
,
95 zlog_debug("%s: %s/%d",
96 (cmd
== ZEBRA_ROUTE_ADD
)
97 ? "Install into zebra"
98 : "Delete from zebra",
99 inet_ntoa(rp
->p
.u
.prefix4
), rp
->p
.prefixlen
);
102 rip_global_route_changes
++;
105 /* Add/update ECMP routes to zebra. */
106 void rip_zebra_ipv4_add(struct route_node
*rp
)
108 rip_zebra_ipv4_send(rp
, ZEBRA_ROUTE_ADD
);
111 /* Delete ECMP routes from zebra. */
112 void rip_zebra_ipv4_delete(struct route_node
*rp
)
114 rip_zebra_ipv4_send(rp
, ZEBRA_ROUTE_DELETE
);
117 /* Zebra route add and delete treatment. */
118 static int rip_zebra_read_route(int command
, struct zclient
*zclient
,
119 zebra_size_t length
, vrf_id_t vrf_id
)
121 struct zapi_route api
;
122 struct in_addr nexthop
;
123 unsigned long ifindex
;
128 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
131 nexthop
= api
.nexthops
[0].gate
.ipv4
;
132 ifindex
= api
.nexthops
[0].ifindex
;
134 /* Then fetch IPv4 prefixes. */
135 if (command
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
)
136 rip_redistribute_add(api
.type
, RIP_ROUTE_REDISTRIBUTE
,
137 (struct prefix_ipv4
*)&api
.prefix
, ifindex
,
138 &nexthop
, api
.metric
, api
.distance
,
140 else if (command
== ZEBRA_REDISTRIBUTE_ROUTE_DEL
)
141 rip_redistribute_delete(api
.type
, RIP_ROUTE_REDISTRIBUTE
,
142 (struct prefix_ipv4
*)&api
.prefix
,
148 void rip_zclient_reset(void)
150 zclient_reset(zclient
);
153 /* RIP route-map set for redistribution */
154 static void rip_routemap_set(int type
, const char *name
)
156 if (rip
->route_map
[type
].name
)
157 free(rip
->route_map
[type
].name
);
159 rip
->route_map
[type
].name
= strdup(name
);
160 rip
->route_map
[type
].map
= route_map_lookup_by_name(name
);
163 static void rip_redistribute_metric_set(int type
, unsigned int metric
)
165 rip
->route_map
[type
].metric_config
= 1;
166 rip
->route_map
[type
].metric
= metric
;
169 static int rip_metric_unset(int type
, unsigned int metric
)
171 #define DONT_CARE_METRIC_RIP 17
172 if (metric
!= DONT_CARE_METRIC_RIP
173 && rip
->route_map
[type
].metric
!= metric
)
175 rip
->route_map
[type
].metric_config
= 0;
176 rip
->route_map
[type
].metric
= 0;
180 /* RIP route-map unset for redistribution */
181 static int rip_routemap_unset(int type
, const char *name
)
183 if (!rip
->route_map
[type
].name
184 || (name
!= NULL
&& strcmp(rip
->route_map
[type
].name
, name
)))
187 free(rip
->route_map
[type
].name
);
188 rip
->route_map
[type
].name
= NULL
;
189 rip
->route_map
[type
].map
= NULL
;
194 /* Redistribution types */
199 } redist_type
[] = {{ZEBRA_ROUTE_KERNEL
, 1, "kernel"},
200 {ZEBRA_ROUTE_CONNECT
, 1, "connected"},
201 {ZEBRA_ROUTE_STATIC
, 1, "static"},
202 {ZEBRA_ROUTE_OSPF
, 1, "ospf"},
203 {ZEBRA_ROUTE_BGP
, 2, "bgp"},
204 {ZEBRA_ROUTE_VNC
, 1, "vnc"},
207 static int rip_redistribute_unset(int type
)
209 if (!vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
))
212 vrf_bitmap_unset(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
214 if (zclient
->sock
> 0)
215 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
216 AFI_IP
, type
, 0, VRF_DEFAULT
);
218 /* Remove the routes from RIP table. */
219 rip_redistribute_withdraw(type
);
224 int rip_redistribute_check(int type
)
226 return vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
229 void rip_redistribute_clean(void)
233 for (i
= 0; redist_type
[i
].str
; i
++) {
234 if (vrf_bitmap_check(
235 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
237 if (zclient
->sock
> 0)
238 zebra_redistribute_send(
239 ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
240 AFI_IP
, redist_type
[i
].type
, 0,
244 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
247 /* Remove the routes from RIP table. */
248 rip_redistribute_withdraw(redist_type
[i
].type
);
253 DEFUN (rip_redistribute_type
,
254 rip_redistribute_type_cmd
,
255 "redistribute " FRR_REDIST_STR_RIPD
,
257 FRR_REDIST_HELP_STR_RIPD
)
261 for (i
= 0; redist_type
[i
].str
; i
++) {
262 if (strncmp(redist_type
[i
].str
, argv
[1]->arg
,
263 redist_type
[i
].str_min_len
)
265 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
266 AFI_IP
, redist_type
[i
].type
, 0,
272 vty_out(vty
, "Invalid type %s\n", argv
[1]->arg
);
274 return CMD_WARNING_CONFIG_FAILED
;
277 DEFUN (no_rip_redistribute_type
,
278 no_rip_redistribute_type_cmd
,
279 "no redistribute " FRR_REDIST_STR_RIPD
,
282 FRR_REDIST_HELP_STR_RIPD
)
286 for (i
= 0; redist_type
[i
].str
; i
++) {
287 if (strncmp(redist_type
[i
].str
, argv
[2]->arg
,
288 redist_type
[i
].str_min_len
)
290 rip_metric_unset(redist_type
[i
].type
,
291 DONT_CARE_METRIC_RIP
);
292 rip_routemap_unset(redist_type
[i
].type
, NULL
);
293 rip_redistribute_unset(redist_type
[i
].type
);
298 vty_out(vty
, "Invalid type %s\n", argv
[2]->arg
);
300 return CMD_WARNING_CONFIG_FAILED
;
303 DEFUN (rip_redistribute_type_routemap
,
304 rip_redistribute_type_routemap_cmd
,
305 "redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
307 FRR_REDIST_HELP_STR_RIPD
308 "Route map reference\n"
309 "Pointer to route-map entries\n")
311 int idx_protocol
= 1;
315 for (i
= 0; redist_type
[i
].str
; i
++) {
316 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
317 rip_routemap_set(redist_type
[i
].type
,
318 argv
[idx_word
]->arg
);
319 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
320 AFI_IP
, redist_type
[i
].type
, 0,
326 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
328 return CMD_WARNING_CONFIG_FAILED
;
331 DEFUN (no_rip_redistribute_type_routemap
,
332 no_rip_redistribute_type_routemap_cmd
,
333 "no redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
336 FRR_REDIST_HELP_STR_RIPD
337 "Route map reference\n"
338 "Pointer to route-map entries\n")
340 int idx_protocol
= 2;
344 for (i
= 0; redist_type
[i
].str
; i
++) {
345 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
346 if (rip_routemap_unset(redist_type
[i
].type
,
347 argv
[idx_word
]->arg
))
348 return CMD_WARNING_CONFIG_FAILED
;
349 rip_redistribute_unset(redist_type
[i
].type
);
354 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
356 return CMD_WARNING_CONFIG_FAILED
;
359 DEFUN (rip_redistribute_type_metric
,
360 rip_redistribute_type_metric_cmd
,
361 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
363 FRR_REDIST_HELP_STR_RIPD
367 int idx_protocol
= 1;
372 metric
= atoi(argv
[idx_number
]->arg
);
374 for (i
= 0; redist_type
[i
].str
; i
++) {
375 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
376 rip_redistribute_metric_set(redist_type
[i
].type
,
378 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
379 AFI_IP
, redist_type
[i
].type
, 0,
385 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
387 return CMD_WARNING_CONFIG_FAILED
;
390 DEFUN (no_rip_redistribute_type_metric
,
391 no_rip_redistribute_type_metric_cmd
,
392 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
395 FRR_REDIST_HELP_STR_RIPD
399 int idx_protocol
= 2;
403 for (i
= 0; redist_type
[i
].str
; i
++) {
404 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
405 if (rip_metric_unset(redist_type
[i
].type
,
406 atoi(argv
[idx_number
]->arg
)))
407 return CMD_WARNING_CONFIG_FAILED
;
408 rip_redistribute_unset(redist_type
[i
].type
);
413 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
415 return CMD_WARNING_CONFIG_FAILED
;
418 DEFUN (rip_redistribute_type_metric_routemap
,
419 rip_redistribute_type_metric_routemap_cmd
,
420 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
422 FRR_REDIST_HELP_STR_RIPD
425 "Route map reference\n"
426 "Pointer to route-map entries\n")
428 int idx_protocol
= 1;
434 metric
= atoi(argv
[idx_number
]->arg
);
436 for (i
= 0; redist_type
[i
].str
; i
++) {
437 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
438 rip_redistribute_metric_set(redist_type
[i
].type
,
440 rip_routemap_set(redist_type
[i
].type
,
441 argv
[idx_word
]->arg
);
442 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
443 AFI_IP
, redist_type
[i
].type
, 0,
449 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
451 return CMD_WARNING_CONFIG_FAILED
;
455 DEFUN (no_rip_redistribute_type_metric_routemap
,
456 no_rip_redistribute_type_metric_routemap_cmd
,
457 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
460 FRR_REDIST_HELP_STR_RIPD
463 "Route map reference\n"
464 "Pointer to route-map entries\n")
466 int idx_protocol
= 2;
471 for (i
= 0; redist_type
[i
].str
; i
++) {
472 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
473 if (rip_metric_unset(redist_type
[i
].type
,
474 atoi(argv
[idx_number
]->arg
)))
475 return CMD_WARNING_CONFIG_FAILED
;
476 if (rip_routemap_unset(redist_type
[i
].type
,
477 argv
[idx_word
]->arg
)) {
478 rip_redistribute_metric_set(
480 atoi(argv
[idx_number
]->arg
));
481 return CMD_WARNING_CONFIG_FAILED
;
483 rip_redistribute_unset(redist_type
[i
].type
);
488 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
490 return CMD_WARNING_CONFIG_FAILED
;
493 /* Default information originate. */
495 DEFUN (rip_default_information_originate
,
496 rip_default_information_originate_cmd
,
497 "default-information originate",
498 "Control distribution of default route\n"
499 "Distribute a default route\n")
501 struct prefix_ipv4 p
;
503 if (!rip
->default_information
) {
504 memset(&p
, 0, sizeof(struct prefix_ipv4
));
507 rip
->default_information
= 1;
509 rip_redistribute_add(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
, 0,
516 DEFUN (no_rip_default_information_originate
,
517 no_rip_default_information_originate_cmd
,
518 "no default-information originate",
520 "Control distribution of default route\n"
521 "Distribute a default route\n")
523 struct prefix_ipv4 p
;
525 if (rip
->default_information
) {
526 memset(&p
, 0, sizeof(struct prefix_ipv4
));
529 rip
->default_information
= 0;
531 rip_redistribute_delete(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
,
538 int config_write_rip_redistribute(struct vty
*vty
, int config_mode
)
542 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
543 if (i
== zclient
->redist_default
544 || !vrf_bitmap_check(zclient
->redist
[AFI_IP
][i
],
549 vty_out(vty
, " %s", zebra_route_string(i
));
553 if (rip
->route_map
[i
].metric_config
) {
554 if (rip
->route_map
[i
].name
)
556 " redistribute %s metric %d route-map %s\n",
557 zebra_route_string(i
),
558 rip
->route_map
[i
].metric
,
559 rip
->route_map
[i
].name
);
561 vty_out(vty
, " redistribute %s metric %d\n",
562 zebra_route_string(i
),
563 rip
->route_map
[i
].metric
);
565 if (rip
->route_map
[i
].name
)
566 vty_out(vty
, " redistribute %s route-map %s\n",
567 zebra_route_string(i
),
568 rip
->route_map
[i
].name
);
570 vty_out(vty
, " redistribute %s\n",
571 zebra_route_string(i
));
578 static void rip_zebra_connected(struct zclient
*zclient
)
580 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
583 void rip_zclient_init(struct thread_master
*master
)
585 /* Set default value to the zebra client structure. */
586 zclient
= zclient_new(master
);
587 zclient_init(zclient
, ZEBRA_ROUTE_RIP
, 0);
588 zclient
->zebra_connected
= rip_zebra_connected
;
589 zclient
->interface_add
= rip_interface_add
;
590 zclient
->interface_delete
= rip_interface_delete
;
591 zclient
->interface_address_add
= rip_interface_address_add
;
592 zclient
->interface_address_delete
= rip_interface_address_delete
;
593 zclient
->interface_up
= rip_interface_up
;
594 zclient
->interface_down
= rip_interface_down
;
595 zclient
->redistribute_route_add
= rip_zebra_read_route
;
596 zclient
->redistribute_route_del
= rip_zebra_read_route
;
598 /* Install command elements to rip node. */
599 install_element(RIP_NODE
, &rip_redistribute_type_cmd
);
600 install_element(RIP_NODE
, &rip_redistribute_type_routemap_cmd
);
601 install_element(RIP_NODE
, &rip_redistribute_type_metric_cmd
);
602 install_element(RIP_NODE
, &rip_redistribute_type_metric_routemap_cmd
);
603 install_element(RIP_NODE
, &no_rip_redistribute_type_cmd
);
604 install_element(RIP_NODE
, &no_rip_redistribute_type_routemap_cmd
);
605 install_element(RIP_NODE
, &no_rip_redistribute_type_metric_cmd
);
606 install_element(RIP_NODE
,
607 &no_rip_redistribute_type_metric_routemap_cmd
);
608 install_element(RIP_NODE
, &rip_default_information_originate_cmd
);
609 install_element(RIP_NODE
, &no_rip_default_information_originate_cmd
);
612 void rip_zclient_stop(void)
614 zclient_stop(zclient
);
615 zclient_free(zclient
);