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
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
33 #include "ripd/ripd.h"
34 #include "ripd/rip_debug.h"
35 #include "ripd/rip_interface.h"
37 /* All information about zebra. */
38 struct zclient
*zclient
= NULL
;
40 /* Send ECMP routes to zebra. */
41 static void rip_zebra_ipv4_send(struct route_node
*rp
, u_char cmd
)
43 static struct in_addr
**nexthops
= NULL
;
44 static unsigned int nexthops_len
= 0;
46 struct list
*list
= (struct list
*)rp
->info
;
48 struct listnode
*listnode
= NULL
;
49 struct rip_info
*rinfo
= NULL
;
52 if (vrf_bitmap_check(zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_RIP
],
54 api
.vrf_id
= VRF_DEFAULT
;
55 api
.type
= ZEBRA_ROUTE_RIP
;
59 api
.safi
= SAFI_UNICAST
;
61 if (nexthops_len
< listcount(list
)) {
62 nexthops_len
= listcount(list
);
63 nexthops
= XREALLOC(MTYPE_TMP
, nexthops
,
65 * sizeof(struct in_addr
*));
68 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
69 for (ALL_LIST_ELEMENTS_RO(list
, listnode
, rinfo
)) {
70 nexthops
[count
++] = &rinfo
->nexthop
;
71 if (cmd
== ZEBRA_IPV4_ROUTE_ADD
)
72 SET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
74 UNSET_FLAG(rinfo
->flags
, RIP_RTF_FIB
);
77 api
.nexthop
= nexthops
;
78 api
.nexthop_num
= count
;
81 rinfo
= listgetdata(listhead(list
));
83 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
84 api
.metric
= rinfo
->metric
;
87 && rinfo
->distance
!= ZEBRA_RIP_DISTANCE_DEFAULT
) {
88 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
89 api
.distance
= rinfo
->distance
;
93 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
97 zapi_ipv4_route(cmd
, zclient
, (struct prefix_ipv4
*)&rp
->p
,
100 if (IS_RIP_DEBUG_ZEBRA
) {
102 zlog_debug("%s: %s/%d nexthops %d",
103 (cmd
== ZEBRA_IPV4_ROUTE_ADD
)
104 ? "Install into zebra"
105 : "Delete from zebra",
106 inet_ntoa(rp
->p
.u
.prefix4
),
107 rp
->p
.prefixlen
, count
);
109 zlog_debug("%s: %s/%d",
110 (cmd
== ZEBRA_IPV4_ROUTE_ADD
)
111 ? "Install into zebra"
112 : "Delete from zebra",
113 inet_ntoa(rp
->p
.u
.prefix4
),
117 rip_global_route_changes
++;
121 /* Add/update ECMP routes to zebra. */
122 void rip_zebra_ipv4_add(struct route_node
*rp
)
124 rip_zebra_ipv4_send(rp
, ZEBRA_IPV4_ROUTE_ADD
);
127 /* Delete ECMP routes from zebra. */
128 void rip_zebra_ipv4_delete(struct route_node
*rp
)
130 rip_zebra_ipv4_send(rp
, ZEBRA_IPV4_ROUTE_DELETE
);
133 /* Zebra route add and delete treatment. */
134 static int rip_zebra_read_ipv4(int command
, struct zclient
*zclient
,
135 zebra_size_t length
, vrf_id_t vrf_id
)
138 struct zapi_ipv4 api
;
139 unsigned long ifindex
;
140 struct in_addr nexthop
;
141 struct prefix_ipv4 p
;
150 /* Type, flags, message. */
151 api
.type
= stream_getc(s
);
152 api
.instance
= stream_getw(s
);
153 api
.flags
= stream_getl(s
);
154 api
.message
= stream_getc(s
);
157 memset(&p
, 0, sizeof(struct prefix_ipv4
));
159 p
.prefixlen
= MIN(IPV4_MAX_PREFIXLEN
, stream_getc(s
));
160 stream_get(&p
.prefix
, s
, PSIZE(p
.prefixlen
));
162 /* Nexthop, ifindex, distance, metric. */
163 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
)) {
164 api
.nexthop_num
= stream_getc(s
);
165 nexthop
.s_addr
= stream_get_ipv4(s
);
167 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_IFINDEX
)) {
168 api
.ifindex_num
= stream_getc(s
);
169 ifindex
= stream_getl(s
);
171 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
))
172 api
.distance
= stream_getc(s
);
175 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
))
176 api
.metric
= stream_getl(s
);
180 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_TAG
))
181 api
.tag
= stream_getl(s
);
185 /* Then fetch IPv4 prefixes. */
186 if (command
== ZEBRA_REDISTRIBUTE_IPV4_ADD
)
187 rip_redistribute_add(api
.type
, RIP_ROUTE_REDISTRIBUTE
, &p
,
188 ifindex
, &nexthop
, api
.metric
,
189 api
.distance
, api
.tag
);
190 else if (command
== ZEBRA_REDISTRIBUTE_IPV4_DEL
)
191 rip_redistribute_delete(api
.type
, RIP_ROUTE_REDISTRIBUTE
, &p
,
197 void rip_zclient_reset(void)
199 zclient_reset(zclient
);
202 /* RIP route-map set for redistribution */
203 static void rip_routemap_set(int type
, const char *name
)
205 if (rip
->route_map
[type
].name
)
206 free(rip
->route_map
[type
].name
);
208 rip
->route_map
[type
].name
= strdup(name
);
209 rip
->route_map
[type
].map
= route_map_lookup_by_name(name
);
212 static void rip_redistribute_metric_set(int type
, unsigned int metric
)
214 rip
->route_map
[type
].metric_config
= 1;
215 rip
->route_map
[type
].metric
= metric
;
218 static int rip_metric_unset(int type
, unsigned int metric
)
220 #define DONT_CARE_METRIC_RIP 17
221 if (metric
!= DONT_CARE_METRIC_RIP
222 && rip
->route_map
[type
].metric
!= metric
)
224 rip
->route_map
[type
].metric_config
= 0;
225 rip
->route_map
[type
].metric
= 0;
229 /* RIP route-map unset for redistribution */
230 static int rip_routemap_unset(int type
, const char *name
)
232 if (!rip
->route_map
[type
].name
233 || (name
!= NULL
&& strcmp(rip
->route_map
[type
].name
, name
)))
236 free(rip
->route_map
[type
].name
);
237 rip
->route_map
[type
].name
= NULL
;
238 rip
->route_map
[type
].map
= NULL
;
243 /* Redistribution types */
248 } redist_type
[] = {{ZEBRA_ROUTE_KERNEL
, 1, "kernel"},
249 {ZEBRA_ROUTE_CONNECT
, 1, "connected"},
250 {ZEBRA_ROUTE_STATIC
, 1, "static"},
251 {ZEBRA_ROUTE_OSPF
, 1, "ospf"},
252 {ZEBRA_ROUTE_BGP
, 2, "bgp"},
253 {ZEBRA_ROUTE_VNC
, 1, "vnc"},
256 static int rip_redistribute_unset(int type
)
258 if (!vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
))
261 vrf_bitmap_unset(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
263 if (zclient
->sock
> 0)
264 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
265 AFI_IP
, type
, 0, VRF_DEFAULT
);
267 /* Remove the routes from RIP table. */
268 rip_redistribute_withdraw(type
);
273 int rip_redistribute_check(int type
)
275 return vrf_bitmap_check(zclient
->redist
[AFI_IP
][type
], VRF_DEFAULT
);
278 void rip_redistribute_clean(void)
282 for (i
= 0; redist_type
[i
].str
; i
++) {
283 if (vrf_bitmap_check(
284 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
286 if (zclient
->sock
> 0)
287 zebra_redistribute_send(
288 ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
289 AFI_IP
, redist_type
[i
].type
, 0,
293 zclient
->redist
[AFI_IP
][redist_type
[i
].type
],
296 /* Remove the routes from RIP table. */
297 rip_redistribute_withdraw(redist_type
[i
].type
);
302 DEFUN (rip_redistribute_rip
,
303 rip_redistribute_rip_cmd
,
305 "Redistribute information from another routing protocol\n"
306 "Routing Information Protocol (RIP)\n")
308 vrf_bitmap_set(zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_RIP
], VRF_DEFAULT
);
312 DEFUN (no_rip_redistribute_rip
,
313 no_rip_redistribute_rip_cmd
,
314 "no redistribute rip",
316 "Redistribute information from another routing protocol\n"
317 "Routing Information Protocol (RIP)\n")
319 vrf_bitmap_unset(zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_RIP
], VRF_DEFAULT
);
323 DEFUN (rip_redistribute_type
,
324 rip_redistribute_type_cmd
,
325 "redistribute " FRR_REDIST_STR_RIPD
,
327 FRR_REDIST_HELP_STR_RIPD
)
331 for (i
= 0; redist_type
[i
].str
; i
++) {
332 if (strncmp(redist_type
[i
].str
, argv
[1]->arg
,
333 redist_type
[i
].str_min_len
)
335 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
336 AFI_IP
, redist_type
[i
].type
, 0,
342 vty_out(vty
, "Invalid type %s%s", argv
[1]->arg
, VTY_NEWLINE
);
347 DEFUN (no_rip_redistribute_type
,
348 no_rip_redistribute_type_cmd
,
349 "no redistribute " FRR_REDIST_STR_RIPD
,
352 FRR_REDIST_HELP_STR_RIPD
)
356 for (i
= 0; redist_type
[i
].str
; i
++) {
357 if (strncmp(redist_type
[i
].str
, argv
[2]->arg
,
358 redist_type
[i
].str_min_len
)
360 rip_metric_unset(redist_type
[i
].type
,
361 DONT_CARE_METRIC_RIP
);
362 rip_routemap_unset(redist_type
[i
].type
, NULL
);
363 rip_redistribute_unset(redist_type
[i
].type
);
368 vty_out(vty
, "Invalid type %s%s", argv
[2]->arg
, VTY_NEWLINE
);
373 DEFUN (rip_redistribute_type_routemap
,
374 rip_redistribute_type_routemap_cmd
,
375 "redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
377 FRR_REDIST_HELP_STR_RIPD
378 "Route map reference\n"
379 "Pointer to route-map entries\n")
381 int idx_protocol
= 1;
385 for (i
= 0; redist_type
[i
].str
; i
++) {
386 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
387 rip_routemap_set(redist_type
[i
].type
,
388 argv
[idx_word
]->arg
);
389 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
390 AFI_IP
, redist_type
[i
].type
, 0,
396 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
402 DEFUN (no_rip_redistribute_type_routemap
,
403 no_rip_redistribute_type_routemap_cmd
,
404 "no redistribute " FRR_REDIST_STR_RIPD
" route-map WORD",
407 FRR_REDIST_HELP_STR_RIPD
408 "Route map reference\n"
409 "Pointer to route-map entries\n")
411 int idx_protocol
= 2;
415 for (i
= 0; redist_type
[i
].str
; i
++) {
416 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
417 if (rip_routemap_unset(redist_type
[i
].type
,
418 argv
[idx_word
]->arg
))
420 rip_redistribute_unset(redist_type
[i
].type
);
425 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
431 DEFUN (rip_redistribute_type_metric
,
432 rip_redistribute_type_metric_cmd
,
433 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
435 FRR_REDIST_HELP_STR_RIPD
439 int idx_protocol
= 1;
444 metric
= atoi(argv
[idx_number
]->arg
);
446 for (i
= 0; redist_type
[i
].str
; i
++) {
447 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
448 rip_redistribute_metric_set(redist_type
[i
].type
,
450 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
451 AFI_IP
, redist_type
[i
].type
, 0,
457 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
463 DEFUN (no_rip_redistribute_type_metric
,
464 no_rip_redistribute_type_metric_cmd
,
465 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16)",
468 FRR_REDIST_HELP_STR_RIPD
472 int idx_protocol
= 2;
476 for (i
= 0; redist_type
[i
].str
; i
++) {
477 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
478 if (rip_metric_unset(redist_type
[i
].type
,
479 atoi(argv
[idx_number
]->arg
)))
481 rip_redistribute_unset(redist_type
[i
].type
);
486 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
492 DEFUN (rip_redistribute_type_metric_routemap
,
493 rip_redistribute_type_metric_routemap_cmd
,
494 "redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
496 FRR_REDIST_HELP_STR_RIPD
499 "Route map reference\n"
500 "Pointer to route-map entries\n")
502 int idx_protocol
= 1;
508 metric
= atoi(argv
[idx_number
]->arg
);
510 for (i
= 0; redist_type
[i
].str
; i
++) {
511 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
512 rip_redistribute_metric_set(redist_type
[i
].type
,
514 rip_routemap_set(redist_type
[i
].type
,
515 argv
[idx_word
]->arg
);
516 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
,
517 AFI_IP
, redist_type
[i
].type
, 0,
523 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
530 DEFUN (no_rip_redistribute_type_metric_routemap
,
531 no_rip_redistribute_type_metric_routemap_cmd
,
532 "no redistribute " FRR_REDIST_STR_RIPD
" metric (0-16) route-map WORD",
535 FRR_REDIST_HELP_STR_RIPD
538 "Route map reference\n"
539 "Pointer to route-map entries\n")
541 int idx_protocol
= 2;
546 for (i
= 0; redist_type
[i
].str
; i
++) {
547 if (strmatch(redist_type
[i
].str
, argv
[idx_protocol
]->text
)) {
548 if (rip_metric_unset(redist_type
[i
].type
,
549 atoi(argv
[idx_number
]->arg
)))
551 if (rip_routemap_unset(redist_type
[i
].type
,
552 argv
[idx_word
]->arg
)) {
553 rip_redistribute_metric_set(
555 atoi(argv
[idx_number
]->arg
));
558 rip_redistribute_unset(redist_type
[i
].type
);
563 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
569 /* Default information originate. */
571 DEFUN (rip_default_information_originate
,
572 rip_default_information_originate_cmd
,
573 "default-information originate",
574 "Control distribution of default route\n"
575 "Distribute a default route\n")
577 struct prefix_ipv4 p
;
579 if (!rip
->default_information
) {
580 memset(&p
, 0, sizeof(struct prefix_ipv4
));
583 rip
->default_information
= 1;
585 rip_redistribute_add(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
, 0,
592 DEFUN (no_rip_default_information_originate
,
593 no_rip_default_information_originate_cmd
,
594 "no default-information originate",
596 "Control distribution of default route\n"
597 "Distribute a default route\n")
599 struct prefix_ipv4 p
;
601 if (rip
->default_information
) {
602 memset(&p
, 0, sizeof(struct prefix_ipv4
));
605 rip
->default_information
= 0;
607 rip_redistribute_delete(ZEBRA_ROUTE_RIP
, RIP_ROUTE_DEFAULT
, &p
,
614 /* RIP configuration write function. */
615 static int config_write_zebra(struct vty
*vty
)
617 if (!zclient
->enable
) {
618 vty_out(vty
, "no router zebra%s", VTY_NEWLINE
);
620 } else if (!vrf_bitmap_check(zclient
->redist
[AFI_IP
][ZEBRA_ROUTE_RIP
],
622 vty_out(vty
, "router zebra%s", VTY_NEWLINE
);
623 vty_out(vty
, " no redistribute rip%s", VTY_NEWLINE
);
629 int config_write_rip_redistribute(struct vty
*vty
, int config_mode
)
633 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
634 if (i
!= zclient
->redist_default
635 && vrf_bitmap_check(zclient
->redist
[AFI_IP
][i
],
638 if (rip
->route_map
[i
].metric_config
) {
639 if (rip
->route_map
[i
].name
)
641 " redistribute %s metric %d route-map %s%s",
642 zebra_route_string(i
),
645 rip
->route_map
[i
].name
,
649 " redistribute %s metric %d%s",
650 zebra_route_string(i
),
655 if (rip
->route_map
[i
].name
)
657 " redistribute %s route-map %s%s",
658 zebra_route_string(i
),
659 rip
->route_map
[i
].name
,
663 " redistribute %s%s",
664 zebra_route_string(i
),
668 vty_out(vty
, " %s", zebra_route_string(i
));
673 /* Zebra node structure. */
674 static struct cmd_node zebra_node
= {
675 ZEBRA_NODE
, "%s(config-router)# ",
678 static void rip_zebra_connected(struct zclient
*zclient
)
680 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
683 void rip_zclient_init(struct thread_master
*master
)
685 /* Set default value to the zebra client structure. */
686 zclient
= zclient_new(master
);
687 zclient_init(zclient
, ZEBRA_ROUTE_RIP
, 0);
688 zclient
->zebra_connected
= rip_zebra_connected
;
689 zclient
->interface_add
= rip_interface_add
;
690 zclient
->interface_delete
= rip_interface_delete
;
691 zclient
->interface_address_add
= rip_interface_address_add
;
692 zclient
->interface_address_delete
= rip_interface_address_delete
;
693 zclient
->interface_up
= rip_interface_up
;
694 zclient
->interface_down
= rip_interface_down
;
695 zclient
->redistribute_route_ipv4_add
= rip_zebra_read_ipv4
;
696 zclient
->redistribute_route_ipv4_del
= rip_zebra_read_ipv4
;
698 /* Install zebra node. */
699 install_node(&zebra_node
, config_write_zebra
);
701 /* Install command elements to zebra node. */
702 install_default(ZEBRA_NODE
);
703 install_element(ZEBRA_NODE
, &rip_redistribute_rip_cmd
);
704 install_element(ZEBRA_NODE
, &no_rip_redistribute_rip_cmd
);
706 /* Install command elements to rip node. */
707 install_element(RIP_NODE
, &rip_redistribute_type_cmd
);
708 install_element(RIP_NODE
, &rip_redistribute_type_routemap_cmd
);
709 install_element(RIP_NODE
, &rip_redistribute_type_metric_cmd
);
710 install_element(RIP_NODE
, &rip_redistribute_type_metric_routemap_cmd
);
711 install_element(RIP_NODE
, &no_rip_redistribute_type_cmd
);
712 install_element(RIP_NODE
, &no_rip_redistribute_type_routemap_cmd
);
713 install_element(RIP_NODE
, &no_rip_redistribute_type_metric_cmd
);
714 install_element(RIP_NODE
,
715 &no_rip_redistribute_type_metric_routemap_cmd
);
716 install_element(RIP_NODE
, &rip_default_information_originate_cmd
);
717 install_element(RIP_NODE
, &no_rip_default_information_originate_cmd
);