Line data Source code
1 : /*
2 : * RIPngd and zebra interface.
3 : * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 : *
5 : * This file is part of GNU Zebra.
6 : *
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
10 : * later version.
11 : *
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.
16 : *
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
20 : */
21 :
22 : #include <zebra.h>
23 :
24 : #include "command.h"
25 : #include "prefix.h"
26 : #include "agg_table.h"
27 : #include "stream.h"
28 : #include "memory.h"
29 : #include "routemap.h"
30 : #include "zclient.h"
31 : #include "log.h"
32 :
33 : #include "ripngd/ripngd.h"
34 : #include "ripngd/ripng_debug.h"
35 :
36 : /* All information about zebra. */
37 : struct zclient *zclient = NULL;
38 :
39 : /* Send ECMP routes to zebra. */
40 0 : static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp,
41 : uint8_t cmd)
42 : {
43 0 : struct list *list = (struct list *)rp->info;
44 0 : struct zapi_route api;
45 0 : struct zapi_nexthop *api_nh;
46 0 : struct listnode *listnode = NULL;
47 0 : struct ripng_info *rinfo = NULL;
48 0 : int count = 0;
49 0 : const struct prefix *p = agg_node_get_prefix(rp);
50 :
51 0 : memset(&api, 0, sizeof(api));
52 0 : api.vrf_id = ripng->vrf->vrf_id;
53 0 : api.type = ZEBRA_ROUTE_RIPNG;
54 0 : api.safi = SAFI_UNICAST;
55 0 : api.prefix = *p;
56 :
57 0 : SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
58 0 : for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
59 0 : if (count >= MULTIPATH_NUM)
60 : break;
61 0 : api_nh = &api.nexthops[count];
62 0 : api_nh->vrf_id = ripng->vrf->vrf_id;
63 0 : api_nh->gate.ipv6 = rinfo->nexthop;
64 0 : api_nh->ifindex = rinfo->ifindex;
65 0 : api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
66 0 : count++;
67 0 : if (cmd == ZEBRA_ROUTE_ADD)
68 0 : SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
69 : else
70 0 : UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
71 : }
72 :
73 0 : api.nexthop_num = count;
74 :
75 0 : rinfo = listgetdata(listhead(list));
76 :
77 0 : SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
78 0 : api.metric = rinfo->metric;
79 :
80 0 : if (rinfo->tag) {
81 0 : SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
82 0 : api.tag = rinfo->tag;
83 : }
84 :
85 0 : zclient_route_send(cmd, zclient, &api);
86 :
87 0 : if (IS_RIPNG_DEBUG_ZEBRA) {
88 0 : if (ripng->ecmp)
89 0 : zlog_debug("%s: %pRN nexthops %d",
90 : (cmd == ZEBRA_ROUTE_ADD)
91 : ? "Install into zebra"
92 : : "Delete from zebra",
93 : rp, count);
94 : else
95 0 : zlog_debug("%s: %pRN",
96 : (cmd == ZEBRA_ROUTE_ADD)
97 : ? "Install into zebra"
98 : : "Delete from zebra",
99 : rp);
100 : }
101 0 : }
102 :
103 : /* Add/update ECMP routes to zebra. */
104 0 : void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *rp)
105 : {
106 0 : ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_ADD);
107 0 : }
108 :
109 : /* Delete ECMP routes from zebra. */
110 0 : void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *rp)
111 : {
112 0 : ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_DELETE);
113 0 : }
114 :
115 : /* Zebra route add and delete treatment. */
116 0 : static int ripng_zebra_read_route(ZAPI_CALLBACK_ARGS)
117 : {
118 0 : struct ripng *ripng;
119 0 : struct zapi_route api;
120 0 : struct in6_addr nexthop;
121 0 : unsigned long ifindex;
122 :
123 0 : ripng = ripng_lookup_by_vrf_id(vrf_id);
124 0 : if (!ripng)
125 : return 0;
126 :
127 0 : if (zapi_route_decode(zclient->ibuf, &api) < 0)
128 : return -1;
129 :
130 : /* we completely ignore srcdest routes for now. */
131 0 : if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
132 : return 0;
133 :
134 0 : if (IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
135 : return 0;
136 :
137 0 : nexthop = api.nexthops[0].gate.ipv6;
138 0 : ifindex = api.nexthops[0].ifindex;
139 :
140 0 : if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
141 0 : ripng_redistribute_add(ripng, api.type,
142 : RIPNG_ROUTE_REDISTRIBUTE,
143 : (struct prefix_ipv6 *)&api.prefix,
144 : ifindex, &nexthop, api.tag);
145 : else
146 0 : ripng_redistribute_delete(
147 0 : ripng, api.type, RIPNG_ROUTE_REDISTRIBUTE,
148 : (struct prefix_ipv6 *)&api.prefix, ifindex);
149 :
150 : return 0;
151 : }
152 :
153 0 : void ripng_redistribute_conf_update(struct ripng *ripng, int type)
154 : {
155 0 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6,
156 0 : type, 0, ripng->vrf->vrf_id);
157 0 : }
158 :
159 0 : void ripng_redistribute_conf_delete(struct ripng *ripng, int type)
160 : {
161 0 : if (zclient->sock > 0)
162 0 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
163 0 : AFI_IP6, type, 0, ripng->vrf->vrf_id);
164 :
165 0 : ripng_redistribute_withdraw(ripng, type);
166 0 : }
167 :
168 92 : int ripng_redistribute_check(struct ripng *ripng, int type)
169 : {
170 92 : return ripng->redist[type].enabled;
171 : }
172 :
173 1 : void ripng_redistribute_enable(struct ripng *ripng)
174 : {
175 32 : for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
176 31 : if (!ripng_redistribute_check(ripng, i))
177 31 : continue;
178 :
179 0 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
180 0 : AFI_IP6, i, 0, ripng->vrf->vrf_id);
181 : }
182 1 : }
183 :
184 1 : void ripng_redistribute_disable(struct ripng *ripng)
185 : {
186 32 : for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
187 31 : if (!ripng_redistribute_check(ripng, i))
188 31 : continue;
189 :
190 0 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
191 0 : AFI_IP6, i, 0, ripng->vrf->vrf_id);
192 : }
193 1 : }
194 :
195 1 : void ripng_redistribute_write(struct vty *vty, struct ripng *ripng)
196 : {
197 1 : int i;
198 :
199 32 : for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
200 31 : if (i == zclient->redist_default
201 30 : || !ripng_redistribute_check(ripng, i))
202 31 : continue;
203 :
204 0 : vty_out(vty, " %s", zebra_route_string(i));
205 : }
206 1 : }
207 :
208 1 : void ripng_zebra_vrf_register(struct vrf *vrf)
209 : {
210 1 : if (vrf->vrf_id == VRF_DEFAULT)
211 : return;
212 :
213 0 : if (IS_RIPNG_DEBUG_EVENT)
214 0 : zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
215 : vrf->name, vrf->vrf_id);
216 :
217 0 : zclient_send_reg_requests(zclient, vrf->vrf_id);
218 : }
219 :
220 1 : void ripng_zebra_vrf_deregister(struct vrf *vrf)
221 : {
222 1 : if (vrf->vrf_id == VRF_DEFAULT)
223 : return;
224 :
225 0 : if (IS_RIPNG_DEBUG_EVENT)
226 0 : zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
227 : vrf->name, vrf->vrf_id);
228 :
229 0 : zclient_send_dereg_requests(zclient, vrf->vrf_id);
230 : }
231 :
232 1 : static void ripng_zebra_connected(struct zclient *zclient)
233 : {
234 1 : zclient_send_reg_requests(zclient, VRF_DEFAULT);
235 1 : }
236 :
237 : static zclient_handler *const ripng_handlers[] = {
238 : [ZEBRA_INTERFACE_ADDRESS_ADD] = ripng_interface_address_add,
239 : [ZEBRA_INTERFACE_ADDRESS_DELETE] = ripng_interface_address_delete,
240 : [ZEBRA_INTERFACE_VRF_UPDATE] = ripng_interface_vrf_update,
241 : [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ripng_zebra_read_route,
242 : [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ripng_zebra_read_route,
243 : };
244 :
245 : /* Initialize zebra structure and it's commands. */
246 1 : void zebra_init(struct thread_master *master)
247 : {
248 : /* Allocate zebra structure. */
249 1 : zclient = zclient_new(master, &zclient_options_default, ripng_handlers,
250 : array_size(ripng_handlers));
251 1 : zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);
252 :
253 1 : zclient->zebra_connected = ripng_zebra_connected;
254 1 : }
255 :
256 1 : void ripng_zebra_stop(void)
257 : {
258 1 : zclient_stop(zclient);
259 1 : zclient_free(zclient);
260 1 : }
|