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
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34 #include "ripngd/ripngd.h"
35 #include "ripngd/ripng_debug.h"
37 /* All information about zebra. */
38 struct zclient
*zclient
= NULL
;
40 /* Send ECMP routes to zebra. */
41 static void ripng_zebra_ipv6_send(struct route_node
*rp
, u_char cmd
)
43 static struct in6_addr
**nexthops
= NULL
;
44 static ifindex_t
*ifindexes
= NULL
;
45 static unsigned int nexthops_len
= 0;
47 struct list
*list
= (struct list
*)rp
->info
;
49 struct listnode
*listnode
= NULL
;
50 struct ripng_info
*rinfo
= NULL
;
53 if (vrf_bitmap_check(zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_RIPNG
],
55 api
.vrf_id
= VRF_DEFAULT
;
56 api
.type
= ZEBRA_ROUTE_RIPNG
;
60 api
.safi
= SAFI_UNICAST
;
62 if (nexthops_len
< listcount(list
)) {
63 nexthops_len
= listcount(list
);
66 nexthops_len
* sizeof(struct in6_addr
*));
68 XREALLOC(MTYPE_TMP
, ifindexes
,
69 nexthops_len
* sizeof(unsigned int));
72 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
73 SET_FLAG(api
.message
, ZAPI_MESSAGE_IFINDEX
);
74 for (ALL_LIST_ELEMENTS_RO(list
, listnode
, rinfo
)) {
75 nexthops
[count
] = &rinfo
->nexthop
;
76 ifindexes
[count
] = rinfo
->ifindex
;
78 if (cmd
== ZEBRA_IPV6_ROUTE_ADD
)
79 SET_FLAG(rinfo
->flags
, RIPNG_RTF_FIB
);
81 UNSET_FLAG(rinfo
->flags
, RIPNG_RTF_FIB
);
84 api
.nexthop
= nexthops
;
85 api
.nexthop_num
= count
;
86 api
.ifindex
= ifindexes
;
87 api
.ifindex_num
= count
;
89 rinfo
= listgetdata(listhead(list
));
91 SET_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
);
92 api
.metric
= rinfo
->metric
;
95 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
99 zapi_ipv6_route(cmd
, zclient
, (struct prefix_ipv6
*)&rp
->p
,
102 if (IS_RIPNG_DEBUG_ZEBRA
) {
104 zlog_debug("%s: %s/%d nexthops %d",
105 (cmd
== ZEBRA_IPV6_ROUTE_ADD
)
106 ? "Install into zebra"
107 : "Delete from zebra",
108 inet6_ntoa(rp
->p
.u
.prefix6
),
109 rp
->p
.prefixlen
, count
);
111 zlog_debug("%s: %s/%d",
112 (cmd
== ZEBRA_IPV6_ROUTE_ADD
)
113 ? "Install into zebra"
114 : "Delete from zebra",
115 inet6_ntoa(rp
->p
.u
.prefix6
),
121 /* Add/update ECMP routes to zebra. */
122 void ripng_zebra_ipv6_add(struct route_node
*rp
)
124 ripng_zebra_ipv6_send(rp
, ZEBRA_IPV6_ROUTE_ADD
);
127 /* Delete ECMP routes from zebra. */
128 void ripng_zebra_ipv6_delete(struct route_node
*rp
)
130 ripng_zebra_ipv6_send(rp
, ZEBRA_IPV6_ROUTE_DELETE
);
133 /* Zebra route add and delete treatment. */
134 static int ripng_zebra_read_ipv6(int command
, struct zclient
*zclient
,
135 zebra_size_t length
, vrf_id_t vrf_id
)
138 struct zapi_ipv6 api
;
139 unsigned long ifindex
;
140 struct in6_addr nexthop
;
141 struct prefix_ipv6 p
, src_p
;
145 memset(&nexthop
, 0, sizeof(struct in6_addr
));
147 /* Type, flags, message. */
148 api
.type
= stream_getc(s
);
149 api
.instance
= stream_getw(s
);
150 api
.flags
= stream_getl(s
);
151 api
.message
= stream_getc(s
);
154 memset(&p
, 0, sizeof(struct prefix_ipv6
));
156 p
.prefixlen
= MIN(IPV6_MAX_PREFIXLEN
, stream_getc(s
));
157 stream_get(&p
.prefix
, s
, PSIZE(p
.prefixlen
));
159 memset(&src_p
, 0, sizeof(struct prefix_ipv6
));
160 src_p
.family
= AF_INET6
;
161 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
)) {
162 src_p
.prefixlen
= stream_getc(s
);
163 stream_get(&src_p
.prefix
, s
, PSIZE(src_p
.prefixlen
));
167 /* we completely ignore srcdest routes for now. */
170 /* Nexthop, ifindex, distance, metric. */
171 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
)) {
172 api
.nexthop_num
= stream_getc(s
);
173 stream_get(&nexthop
, s
, 16);
175 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_IFINDEX
)) {
176 api
.ifindex_num
= stream_getc(s
);
177 ifindex
= stream_getl(s
);
179 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
))
180 api
.distance
= stream_getc(s
);
183 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_METRIC
))
184 api
.metric
= stream_getl(s
);
188 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_TAG
))
189 api
.tag
= stream_getl(s
);
193 if (command
== ZEBRA_REDISTRIBUTE_IPV6_ADD
)
194 ripng_redistribute_add(api
.type
, RIPNG_ROUTE_REDISTRIBUTE
, &p
,
195 ifindex
, &nexthop
, api
.tag
);
197 ripng_redistribute_delete(api
.type
, RIPNG_ROUTE_REDISTRIBUTE
,
203 void ripng_zclient_reset(void)
205 zclient_reset(zclient
);
208 static int ripng_redistribute_unset(int type
)
211 if (!vrf_bitmap_check(zclient
->redist
[AFI_IP6
][type
], VRF_DEFAULT
))
214 vrf_bitmap_set(zclient
->redist
[AFI_IP6
][type
], VRF_DEFAULT
);
216 if (zclient
->sock
> 0)
217 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
218 AFI_IP6
, type
, 0, VRF_DEFAULT
);
220 ripng_redistribute_withdraw(type
);
225 int ripng_redistribute_check(int type
)
227 return vrf_bitmap_check(zclient
->redist
[AFI_IP6
][type
], VRF_DEFAULT
);
230 static void ripng_redistribute_metric_set(int type
, int metric
)
232 ripng
->route_map
[type
].metric_config
= 1;
233 ripng
->route_map
[type
].metric
= metric
;
236 static int ripng_redistribute_metric_unset(int type
)
238 ripng
->route_map
[type
].metric_config
= 0;
239 ripng
->route_map
[type
].metric
= 0;
243 static void ripng_redistribute_routemap_set(int type
, const char *name
)
245 if (ripng
->route_map
[type
].name
)
246 free(ripng
->route_map
[type
].name
);
248 ripng
->route_map
[type
].name
= strdup(name
);
249 ripng
->route_map
[type
].map
= route_map_lookup_by_name(name
);
252 static void ripng_redistribute_routemap_unset(int type
)
254 if (ripng
->route_map
[type
].name
)
255 free(ripng
->route_map
[type
].name
);
257 ripng
->route_map
[type
].name
= NULL
;
258 ripng
->route_map
[type
].map
= NULL
;
261 /* Redistribution types */
266 } redist_type
[] = {{ZEBRA_ROUTE_KERNEL
, 1, "kernel"},
267 {ZEBRA_ROUTE_CONNECT
, 1, "connected"},
268 {ZEBRA_ROUTE_STATIC
, 1, "static"},
269 {ZEBRA_ROUTE_OSPF6
, 1, "ospf6"},
270 {ZEBRA_ROUTE_BGP
, 2, "bgp"},
271 {ZEBRA_ROUTE_VNC
, 1, "vnc"},
274 void ripng_redistribute_clean()
278 for (i
= 0; redist_type
[i
].str
; i
++) {
279 if (vrf_bitmap_check(
280 zclient
->redist
[AFI_IP6
][redist_type
[i
].type
],
282 if (zclient
->sock
> 0)
283 zebra_redistribute_send(
284 ZEBRA_REDISTRIBUTE_DELETE
, zclient
,
285 AFI_IP6
, redist_type
[i
].type
, 0,
289 zclient
->redist
[AFI_IP6
][redist_type
[i
].type
],
292 /* Remove the routes from RIPng table. */
293 ripng_redistribute_withdraw(redist_type
[i
].type
);
298 DEFUN (ripng_redistribute_ripng
,
299 ripng_redistribute_ripng_cmd
,
300 "redistribute ripng",
301 "Redistribute information from another routing protocol\n"
304 vrf_bitmap_set(zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_RIPNG
],
309 DEFUN (no_ripng_redistribute_ripng
,
310 no_ripng_redistribute_ripng_cmd
,
311 "no redistribute ripng",
313 "Redistribute information from another routing protocol\n"
316 vrf_bitmap_unset(zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_RIPNG
],
321 DEFUN (ripng_redistribute_type
,
322 ripng_redistribute_type_cmd
,
323 "redistribute " FRR_REDIST_STR_RIPNGD
,
325 FRR_REDIST_HELP_STR_RIPNGD
)
329 char *proto
= argv
[argc
- 1]->text
;
330 type
= proto_redistnum(AFI_IP6
, proto
);
333 vty_out(vty
, "Invalid type %s%s", proto
, VTY_NEWLINE
);
337 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP6
, type
, 0,
342 DEFUN (no_ripng_redistribute_type
,
343 no_ripng_redistribute_type_cmd
,
344 "no redistribute " FRR_REDIST_STR_RIPNGD
" [metric (0-16)] [route-map WORD]",
347 FRR_REDIST_HELP_STR_RIPNGD
350 "Route map reference\n"
351 "Pointer to route-map entries\n")
355 char *proto
= argv
[2]->text
;
356 type
= proto_redistnum(AFI_IP6
, proto
);
359 vty_out(vty
, "Invalid type %s%s", proto
, VTY_NEWLINE
);
363 ripng_redistribute_metric_unset(type
);
364 ripng_redistribute_routemap_unset(type
);
365 return ripng_redistribute_unset(type
);
369 DEFUN (ripng_redistribute_type_metric
,
370 ripng_redistribute_type_metric_cmd
,
371 "redistribute " FRR_REDIST_STR_RIPNGD
" metric (0-16)",
373 FRR_REDIST_HELP_STR_RIPNGD
377 int idx_protocol
= 1;
382 metric
= atoi(argv
[idx_number
]->arg
);
383 type
= proto_redistnum(AFI_IP6
, argv
[idx_protocol
]->text
);
386 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
391 ripng_redistribute_metric_set(type
, metric
);
392 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP6
, type
, 0,
397 DEFUN (ripng_redistribute_type_routemap
,
398 ripng_redistribute_type_routemap_cmd
,
399 "redistribute " FRR_REDIST_STR_RIPNGD
" route-map WORD",
401 FRR_REDIST_HELP_STR_RIPNGD
402 "Route map reference\n"
403 "Pointer to route-map entries\n")
405 int idx_protocol
= 1;
409 type
= proto_redistnum(AFI_IP6
, argv
[idx_protocol
]->text
);
412 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
417 ripng_redistribute_routemap_set(type
, argv
[idx_word
]->text
);
418 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP6
, type
, 0,
423 DEFUN (ripng_redistribute_type_metric_routemap
,
424 ripng_redistribute_type_metric_routemap_cmd
,
425 "redistribute " FRR_REDIST_STR_RIPNGD
" metric (0-16) route-map WORD",
427 FRR_REDIST_HELP_STR_RIPNGD
430 "Route map reference\n"
431 "Pointer to route-map entries\n")
433 int idx_protocol
= 1;
439 type
= proto_redistnum(AFI_IP6
, argv
[idx_protocol
]->text
);
440 metric
= atoi(argv
[idx_number
]->arg
);
443 vty_out(vty
, "Invalid type %s%s", argv
[idx_protocol
]->text
,
448 ripng_redistribute_metric_set(type
, metric
);
449 ripng_redistribute_routemap_set(type
, argv
[idx_word
]->text
);
450 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP6
, type
, 0,
455 void ripng_redistribute_write(struct vty
*vty
, int config_mode
)
459 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
460 if (i
!= zclient
->redist_default
461 && vrf_bitmap_check(zclient
->redist
[AFI_IP6
][i
],
464 if (ripng
->route_map
[i
].metric_config
) {
465 if (ripng
->route_map
[i
].name
)
467 " redistribute %s metric %d route-map %s%s",
468 zebra_route_string(i
),
476 " redistribute %s metric %d%s",
477 zebra_route_string(i
),
482 if (ripng
->route_map
[i
].name
)
484 " redistribute %s route-map %s%s",
485 zebra_route_string(i
),
491 " redistribute %s%s",
492 zebra_route_string(i
),
496 vty_out(vty
, " %s", zebra_route_string(i
));
500 /* RIPng configuration write function. */
501 static int zebra_config_write(struct vty
*vty
)
503 if (!zclient
->enable
) {
504 vty_out(vty
, "no router zebra%s", VTY_NEWLINE
);
506 } else if (!vrf_bitmap_check(
507 zclient
->redist
[AFI_IP6
][ZEBRA_ROUTE_RIPNG
],
509 vty_out(vty
, "router zebra%s", VTY_NEWLINE
);
510 vty_out(vty
, " no redistribute ripng%s", VTY_NEWLINE
);
516 /* Zebra node structure. */
517 static struct cmd_node zebra_node
= {
518 ZEBRA_NODE
, "%s(config-router)# ",
521 static void ripng_zebra_connected(struct zclient
*zclient
)
523 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
526 /* Initialize zebra structure and it's commands. */
527 void zebra_init(struct thread_master
*master
)
529 /* Allocate zebra structure. */
530 zclient
= zclient_new(master
);
531 zclient_init(zclient
, ZEBRA_ROUTE_RIPNG
, 0);
533 zclient
->zebra_connected
= ripng_zebra_connected
;
534 zclient
->interface_up
= ripng_interface_up
;
535 zclient
->interface_down
= ripng_interface_down
;
536 zclient
->interface_add
= ripng_interface_add
;
537 zclient
->interface_delete
= ripng_interface_delete
;
538 zclient
->interface_address_add
= ripng_interface_address_add
;
539 zclient
->interface_address_delete
= ripng_interface_address_delete
;
540 zclient
->redistribute_route_ipv6_add
= ripng_zebra_read_ipv6
;
541 zclient
->redistribute_route_ipv6_del
= ripng_zebra_read_ipv6
;
543 /* Install zebra node. */
544 install_node(&zebra_node
, zebra_config_write
);
546 /* Install command element for zebra node. */
547 install_default(ZEBRA_NODE
);
548 install_element(ZEBRA_NODE
, &ripng_redistribute_ripng_cmd
);
549 install_element(ZEBRA_NODE
, &no_ripng_redistribute_ripng_cmd
);
551 /* Install command elements to ripng node */
552 install_element(RIPNG_NODE
, &ripng_redistribute_type_cmd
);
553 install_element(RIPNG_NODE
, &ripng_redistribute_type_routemap_cmd
);
554 install_element(RIPNG_NODE
, &ripng_redistribute_type_metric_cmd
);
555 install_element(RIPNG_NODE
,
556 &ripng_redistribute_type_metric_routemap_cmd
);
557 install_element(RIPNG_NODE
, &no_ripng_redistribute_type_cmd
);