2 * RIPngd and zebra interface.
3 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "ripngd/ripngd.h"
34 #include "ripngd/ripng_debug.h"
36 /* All information about zebra. */
37 struct zclient
*zclient
= NULL
;
39 /* Send ECMP routes to zebra. */
40 static void ripng_zebra_ipv6_send(struct route_node
*rp
, u_char cmd
)
42 static struct in6_addr
**nexthops
= NULL
;
43 static ifindex_t
*ifindexes
= NULL
;
44 static unsigned int nexthops_len
= 0;
46 struct list
*list
= (struct list
*)rp
->info
;
48 struct listnode
*listnode
= NULL
;
49 struct ripng_info
*rinfo
= NULL
;
52 if (vrf_bitmap_check(zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_RIPNG
],
54 api
.vrf_id
= VRF_DEFAULT
;
55 api
.type
= ZEBRA_ROUTE_RIPNG
;
59 api
.safi
= SAFI_UNICAST
;
61 if (nexthops_len
< listcount(list
)) {
62 nexthops_len
= listcount(list
);
65 nexthops_len
* sizeof(struct in6_addr
*));
67 XREALLOC(MTYPE_TMP
, ifindexes
,
68 nexthops_len
* sizeof(unsigned int));
71 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
72 SET_FLAG(api
.message
, ZAPI_MESSAGE_IFINDEX
);
73 for (ALL_LIST_ELEMENTS_RO(list
, listnode
, rinfo
)) {
74 nexthops
[count
] = &rinfo
->nexthop
;
75 ifindexes
[count
] = rinfo
->ifindex
;
77 if (cmd
== ZEBRA_IPV6_ROUTE_ADD
)
78 SET_FLAG(rinfo
->flags
, RIPNG_RTF_FIB
);
80 UNSET_FLAG(rinfo
->flags
, RIPNG_RTF_FIB
);
83 api
.nexthop
= nexthops
;
84 api
.nexthop_num
= count
;
85 api
.ifindex
= ifindexes
;
86 api
.ifindex_num
= count
;
88 rinfo
= listgetdata(listhead(list
));
90 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
91 api
.metric
= rinfo
->metric
;
94 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
98 zapi_ipv6_route(cmd
, zclient
, (struct prefix_ipv6
*)&rp
->p
,
101 if (IS_RIPNG_DEBUG_ZEBRA
) {
103 zlog_debug("%s: %s/%d nexthops %d",
104 (cmd
== ZEBRA_IPV6_ROUTE_ADD
)
105 ? "Install into zebra"
106 : "Delete from zebra",
107 inet6_ntoa(rp
->p
.u
.prefix6
),
108 rp
->p
.prefixlen
, count
);
110 zlog_debug("%s: %s/%d",
111 (cmd
== ZEBRA_IPV6_ROUTE_ADD
)
112 ? "Install into zebra"
113 : "Delete from zebra",
114 inet6_ntoa(rp
->p
.u
.prefix6
),
120 /* Add/update ECMP routes to zebra. */
121 void ripng_zebra_ipv6_add(struct route_node
*rp
)
123 ripng_zebra_ipv6_send(rp
, ZEBRA_IPV6_ROUTE_ADD
);
126 /* Delete ECMP routes from zebra. */
127 void ripng_zebra_ipv6_delete(struct route_node
*rp
)
129 ripng_zebra_ipv6_send(rp
, ZEBRA_IPV6_ROUTE_DELETE
);
132 /* Zebra route add and delete treatment. */
133 static int ripng_zebra_read_ipv6(int command
, struct zclient
*zclient
,
134 zebra_size_t length
, vrf_id_t vrf_id
)
137 struct zapi_ipv6 api
;
138 unsigned long ifindex
;
139 struct in6_addr nexthop
;
140 struct prefix_ipv6 p
, src_p
;
144 memset(&nexthop
, 0, sizeof(struct in6_addr
));
146 /* Type, flags, message. */
147 api
.type
= stream_getc(s
);
148 api
.instance
= stream_getw(s
);
149 api
.flags
= stream_getl(s
);
150 api
.message
= stream_getc(s
);
153 memset(&p
, 0, sizeof(struct prefix_ipv6
));
155 p
.prefixlen
= MIN(IPV6_MAX_PREFIXLEN
, stream_getc(s
));
156 stream_get(&p
.prefix
, s
, PSIZE(p
.prefixlen
));
158 memset(&src_p
, 0, sizeof(struct prefix_ipv6
));
159 src_p
.family
= AF_INET6
;
160 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
)) {
161 src_p
.prefixlen
= stream_getc(s
);
162 stream_get(&src_p
.prefix
, s
, PSIZE(src_p
.prefixlen
));
166 /* we completely ignore srcdest routes for now. */
169 /* Nexthop, ifindex, distance, metric. */
170 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
)) {
171 api
.nexthop_num
= stream_getc(s
);
172 stream_get(&nexthop
, s
, 16);
174 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_IFINDEX
)) {
175 api
.ifindex_num
= stream_getc(s
);
176 ifindex
= stream_getl(s
);
178 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
))
179 api
.distance
= stream_getc(s
);
182 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
))
183 api
.metric
= stream_getl(s
);
187 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_TAG
))
188 api
.tag
= stream_getl(s
);
192 if (command
== ZEBRA_REDISTRIBUTE_IPV6_ADD
)
193 ripng_redistribute_add(api
.type
, RIPNG_ROUTE_REDISTRIBUTE
, &p
,
194 ifindex
, &nexthop
, api
.tag
);
196 ripng_redistribute_delete(api
.type
, RIPNG_ROUTE_REDISTRIBUTE
,
202 void ripng_zclient_reset(void)
204 zclient_reset(zclient
);
207 static int ripng_redistribute_unset(int type
)
210 if (!vrf_bitmap_check(zclient
->redist
[AFI_IP6
][type
], VRF_DEFAULT
))
213 vrf_bitmap_set(zclient
->redist
[AFI_IP6
][type
], VRF_DEFAULT
);
215 if (zclient
->sock
> 0)
216 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
217 AFI_IP6
, type
, 0, VRF_DEFAULT
);
219 ripng_redistribute_withdraw(type
);
224 int ripng_redistribute_check(int type
)
226 return vrf_bitmap_check(zclient
->redist
[AFI_IP6
][type
], VRF_DEFAULT
);
229 static void ripng_redistribute_metric_set(int type
, int metric
)
231 ripng
->route_map
[type
].metric_config
= 1;
232 ripng
->route_map
[type
].metric
= metric
;
235 static int ripng_redistribute_metric_unset(int type
)
237 ripng
->route_map
[type
].metric_config
= 0;
238 ripng
->route_map
[type
].metric
= 0;
242 static void ripng_redistribute_routemap_set(int type
, const char *name
)
244 if (ripng
->route_map
[type
].name
)
245 free(ripng
->route_map
[type
].name
);
247 ripng
->route_map
[type
].name
= strdup(name
);
248 ripng
->route_map
[type
].map
= route_map_lookup_by_name(name
);
251 static void ripng_redistribute_routemap_unset(int type
)
253 if (ripng
->route_map
[type
].name
)
254 free(ripng
->route_map
[type
].name
);
256 ripng
->route_map
[type
].name
= NULL
;
257 ripng
->route_map
[type
].map
= NULL
;
260 /* Redistribution types */
265 } redist_type
[] = {{ZEBRA_ROUTE_KERNEL
, 1, "kernel"},
266 {ZEBRA_ROUTE_CONNECT
, 1, "connected"},
267 {ZEBRA_ROUTE_STATIC
, 1, "static"},
268 {ZEBRA_ROUTE_OSPF6
, 1, "ospf6"},
269 {ZEBRA_ROUTE_BGP
, 2, "bgp"},
270 {ZEBRA_ROUTE_VNC
, 1, "vnc"},
273 void ripng_redistribute_clean()
277 for (i
= 0; redist_type
[i
].str
; i
++) {
278 if (vrf_bitmap_check(
279 zclient
->redist
[AFI_IP6
][redist_type
[i
].type
],
281 if (zclient
->sock
> 0)
282 zebra_redistribute_send(
283 ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
284 AFI_IP6
, redist_type
[i
].type
, 0,
288 zclient
->redist
[AFI_IP6
][redist_type
[i
].type
],
291 /* Remove the routes from RIPng table. */
292 ripng_redistribute_withdraw(redist_type
[i
].type
);
297 DEFUN (ripng_redistribute_ripng
,
298 ripng_redistribute_ripng_cmd
,
299 "redistribute ripng",
300 "Redistribute information from another routing protocol\n"
303 vrf_bitmap_set(zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_RIPNG
],
308 DEFUN (no_ripng_redistribute_ripng
,
309 no_ripng_redistribute_ripng_cmd
,
310 "no redistribute ripng",
312 "Redistribute information from another routing protocol\n"
315 vrf_bitmap_unset(zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_RIPNG
],
320 DEFUN (ripng_redistribute_type
,
321 ripng_redistribute_type_cmd
,
322 "redistribute " FRR_REDIST_STR_RIPNGD
,
324 FRR_REDIST_HELP_STR_RIPNGD
)
328 char *proto
= argv
[argc
- 1]->text
;
329 type
= proto_redistnum(AFI_IP6
, proto
);
332 vty_out(vty
, "Invalid type %s\n", proto
);
333 return CMD_WARNING_CONFIG_FAILED
;
336 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP6
, type
, 0,
341 DEFUN (no_ripng_redistribute_type
,
342 no_ripng_redistribute_type_cmd
,
343 "no redistribute " FRR_REDIST_STR_RIPNGD
" [metric (0-16)] [route-map WORD]",
346 FRR_REDIST_HELP_STR_RIPNGD
349 "Route map reference\n"
350 "Pointer to route-map entries\n")
354 char *proto
= argv
[2]->text
;
355 type
= proto_redistnum(AFI_IP6
, proto
);
358 vty_out(vty
, "Invalid type %s\n", proto
);
359 return CMD_WARNING_CONFIG_FAILED
;
362 ripng_redistribute_metric_unset(type
);
363 ripng_redistribute_routemap_unset(type
);
364 return ripng_redistribute_unset(type
);
368 DEFUN (ripng_redistribute_type_metric
,
369 ripng_redistribute_type_metric_cmd
,
370 "redistribute " FRR_REDIST_STR_RIPNGD
" metric (0-16)",
372 FRR_REDIST_HELP_STR_RIPNGD
376 int idx_protocol
= 1;
381 metric
= atoi(argv
[idx_number
]->arg
);
382 type
= proto_redistnum(AFI_IP6
, argv
[idx_protocol
]->text
);
385 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
386 return CMD_WARNING_CONFIG_FAILED
;
389 ripng_redistribute_metric_set(type
, metric
);
390 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP6
, type
, 0,
395 DEFUN (ripng_redistribute_type_routemap
,
396 ripng_redistribute_type_routemap_cmd
,
397 "redistribute " FRR_REDIST_STR_RIPNGD
" route-map WORD",
399 FRR_REDIST_HELP_STR_RIPNGD
400 "Route map reference\n"
401 "Pointer to route-map entries\n")
403 int idx_protocol
= 1;
407 type
= proto_redistnum(AFI_IP6
, argv
[idx_protocol
]->text
);
410 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
411 return CMD_WARNING_CONFIG_FAILED
;
414 ripng_redistribute_routemap_set(type
, argv
[idx_word
]->text
);
415 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP6
, type
, 0,
420 DEFUN (ripng_redistribute_type_metric_routemap
,
421 ripng_redistribute_type_metric_routemap_cmd
,
422 "redistribute " FRR_REDIST_STR_RIPNGD
" metric (0-16) route-map WORD",
424 FRR_REDIST_HELP_STR_RIPNGD
427 "Route map reference\n"
428 "Pointer to route-map entries\n")
430 int idx_protocol
= 1;
436 type
= proto_redistnum(AFI_IP6
, argv
[idx_protocol
]->text
);
437 metric
= atoi(argv
[idx_number
]->arg
);
440 vty_out(vty
, "Invalid type %s\n", argv
[idx_protocol
]->text
);
441 return CMD_WARNING_CONFIG_FAILED
;
444 ripng_redistribute_metric_set(type
, metric
);
445 ripng_redistribute_routemap_set(type
, argv
[idx_word
]->text
);
446 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP6
, type
, 0,
451 void ripng_redistribute_write(struct vty
*vty
, int config_mode
)
455 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
456 if (i
!= zclient
->redist_default
457 && vrf_bitmap_check(zclient
->redist
[AFI_IP6
][i
],
460 if (ripng
->route_map
[i
].metric_config
) {
461 if (ripng
->route_map
[i
].name
)
463 " redistribute %s metric %d route-map %s\n",
464 zebra_route_string(i
),
471 " redistribute %s metric %d\n",
472 zebra_route_string(i
),
476 if (ripng
->route_map
[i
].name
)
478 " redistribute %s route-map %s\n",
479 zebra_route_string(i
),
484 " redistribute %s\n",
485 zebra_route_string(i
));
488 vty_out(vty
, " %s", zebra_route_string(i
));
492 /* RIPng configuration write function. */
493 static int zebra_config_write(struct vty
*vty
)
495 if (!zclient
->enable
) {
496 vty_out(vty
, "no router zebra\n");
498 } else if (!vrf_bitmap_check(
499 zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_RIPNG
],
501 vty_out(vty
, "router zebra\n");
502 vty_out(vty
, " no redistribute ripng\n");
508 /* Zebra node structure. */
509 static struct cmd_node zebra_node
= {
510 ZEBRA_NODE
, "%s(config-router)# ",
513 static void ripng_zebra_connected(struct zclient
*zclient
)
515 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
518 /* Initialize zebra structure and it's commands. */
519 void zebra_init(struct thread_master
*master
)
521 /* Allocate zebra structure. */
522 zclient
= zclient_new(master
);
523 zclient_init(zclient
, ZEBRA_ROUTE_RIPNG
, 0);
525 zclient
->zebra_connected
= ripng_zebra_connected
;
526 zclient
->interface_up
= ripng_interface_up
;
527 zclient
->interface_down
= ripng_interface_down
;
528 zclient
->interface_add
= ripng_interface_add
;
529 zclient
->interface_delete
= ripng_interface_delete
;
530 zclient
->interface_address_add
= ripng_interface_address_add
;
531 zclient
->interface_address_delete
= ripng_interface_address_delete
;
532 zclient
->redistribute_route_ipv6_add
= ripng_zebra_read_ipv6
;
533 zclient
->redistribute_route_ipv6_del
= ripng_zebra_read_ipv6
;
535 /* Install zebra node. */
536 install_node(&zebra_node
, zebra_config_write
);
538 /* Install command element for zebra node. */
539 install_default(ZEBRA_NODE
);
540 install_element(ZEBRA_NODE
, &ripng_redistribute_ripng_cmd
);
541 install_element(ZEBRA_NODE
, &no_ripng_redistribute_ripng_cmd
);
543 /* Install command elements to ripng node */
544 install_element(RIPNG_NODE
, &ripng_redistribute_type_cmd
);
545 install_element(RIPNG_NODE
, &ripng_redistribute_type_routemap_cmd
);
546 install_element(RIPNG_NODE
, &ripng_redistribute_type_metric_cmd
);
547 install_element(RIPNG_NODE
,
548 &ripng_redistribute_type_metric_routemap_cmd
);
549 install_element(RIPNG_NODE
, &no_ripng_redistribute_type_cmd
);
552 void ripng_zebra_stop(void)
554 zclient_stop(zclient
);
555 zclient_free(zclient
);