blob: d262a86b846cca003de01ad1fd18bb101994a1f7 [file] [log] [blame]
Paul Jakma57345092011-12-25 17:52:09 +01001/*
2 * This file is free software: you may copy, redistribute and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation, either version 2 of the License, or (at your
5 * option) any later version.
6 *
7 * This file is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 * This file incorporates work covered by the following copyright and
16 * permission notice:
17 *
18Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
19
20Permission is hereby granted, free of charge, to any person obtaining a copy
21of this software and associated documentation files (the "Software"), to deal
22in the Software without restriction, including without limitation the rights
23to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24copies of the Software, and to permit persons to whom the Software is
25furnished to do so, subject to the following conditions:
26
27The above copyright notice and this permission notice shall be included in
28all copies or substantial portions of the Software.
29
30THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36THE SOFTWARE.
37*/
38
39#include <sys/types.h>
40#include <sys/socket.h>
41#include <netinet/in.h>
42#include <netdb.h>
43#include <arpa/inet.h>
44
45#include <zebra.h>
46#include "prefix.h"
47#include "zclient.h"
48#include "kernel.h"
49#include "privs.h"
50#include "command.h"
51#include "vty.h"
52#include "memory.h"
53#include "thread.h"
54
55#include "util.h"
56#include "babel_interface.h"
57#include "babel_zebra.h"
58
59
60static int
61kernel_route_add_v4(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +010062 const unsigned char *gate, int ifindex,
63 unsigned int metric);
Paul Jakma57345092011-12-25 17:52:09 +010064static int
65kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +010066 const unsigned char *gate, int ifindex,
67 unsigned int metric);
Paul Jakma57345092011-12-25 17:52:09 +010068static int
69kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
70 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +010071 unsigned int metric);
Paul Jakma57345092011-12-25 17:52:09 +010072static int
73kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
74 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +010075 unsigned int metric);
Paul Jakma57345092011-12-25 17:52:09 +010076
Paul Jakma57345092011-12-25 17:52:09 +010077int
78kernel_interface_operational(struct interface *interface)
79{
80 return if_is_operative(interface);
81}
82
83int
Paul Jakma57345092011-12-25 17:52:09 +010084kernel_interface_mtu(struct interface *interface)
85{
86 return MIN(interface->mtu, interface->mtu6);
87}
88
89int
90kernel_interface_wireless(struct interface *interface)
91{
92 return 0;
93}
94
Paul Jakma57345092011-12-25 17:52:09 +010095int
96kernel_route(int operation, const unsigned char *pref, unsigned short plen,
97 const unsigned char *gate, int ifindex, unsigned int metric,
98 const unsigned char *newgate, int newifindex,
99 unsigned int newmetric)
100{
101 int rc;
Paul Jakma57345092011-12-25 17:52:09 +0100102 int ipv4;
103
104 /* Check that the protocol family is consistent. */
105 if(plen >= 96 && v4mapped(pref)) {
106 if(!v4mapped(gate)) {
107 errno = EINVAL;
108 return -1;
109 }
110 ipv4 = 1;
111 } else {
112 if(v4mapped(gate)) {
113 errno = EINVAL;
114 return -1;
115 }
116 ipv4 = 0;
117 }
118
119 switch (operation) {
120 case ROUTE_ADD:
121 return ipv4 ?
Matthieu Boutier53b21952012-01-31 17:09:55 +0100122 kernel_route_add_v4(pref, plen, gate, ifindex, metric):
123 kernel_route_add_v6(pref, plen, gate, ifindex, metric);
Paul Jakma57345092011-12-25 17:52:09 +0100124 break;
125 case ROUTE_FLUSH:
126 return ipv4 ?
Matthieu Boutier53b21952012-01-31 17:09:55 +0100127 kernel_route_delete_v4(pref, plen, gate, ifindex, metric):
128 kernel_route_delete_v6(pref, plen, gate, ifindex, metric);
Paul Jakma57345092011-12-25 17:52:09 +0100129 break;
130 case ROUTE_MODIFY:
131 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
132 newifindex == ifindex)
133 return 0;
Matthieu Boutierec8d8d52012-01-20 15:32:16 +0100134 debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
Matthieu Boutier53b21952012-01-31 17:09:55 +0100135 rc = ipv4 ?
136 kernel_route_delete_v4(pref, plen, gate, ifindex, metric):
137 kernel_route_delete_v6(pref, plen, gate, ifindex, metric);
138
139 if (rc < 0)
140 return -1;
Paul Jakma57345092011-12-25 17:52:09 +0100141
Matthieu Boutierec8d8d52012-01-20 15:32:16 +0100142 rc = ipv4 ?
Matthieu Boutier53b21952012-01-31 17:09:55 +0100143 kernel_route_add_v4(pref, plen, newgate, newifindex, newmetric):
144 kernel_route_add_v6(pref, plen, newgate, newifindex, newmetric);
Paul Jakma57345092011-12-25 17:52:09 +0100145
146 return rc;
147 break;
148 default:
149 zlog_err("this should never appens (false value - kernel_route)");
150 assert(0);
151 exit(1);
152 break;
153 }
154}
155
156static int
157kernel_route_add_v4(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100158 const unsigned char *gate, int ifindex, unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100159{
Paul Jakma57345092011-12-25 17:52:09 +0100160 struct zapi_ipv4 api; /* quagga's communication system */
161 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
162 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
163 struct in_addr nexthop; /* next router to go */
164 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
165
Matthieu Boutier53b21952012-01-31 17:09:55 +0100166 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100167 /* convert given addresses */
168 uchar_to_inaddr(&babel_prefix_addr, pref);
169 uchar_to_inaddr(&nexthop, gate);
170
171 /* make prefix structure */
172 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
173 quagga_prefix.family = AF_INET;
174 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
175 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
176 apply_mask_ipv4(&quagga_prefix);
177
178 api.type = ZEBRA_ROUTE_BABEL;
179 api.flags = 0;
180 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400181 api.safi = SAFI_UNICAST;
Juliusz Chroboczekb6475ec2012-02-09 12:29:10 +0100182
183 /* Unlike the native Linux and BSD interfaces, Quagga doesn't like
184 there to be both and IPv4 nexthop and an ifindex. Omit the
185 ifindex, and assume that the connected prefixes be set up
186 correctly. */
187
Paul Jakma57345092011-12-25 17:52:09 +0100188 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
Juliusz Chroboczekb6475ec2012-02-09 12:29:10 +0100189 api.ifindex_num = 0;
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100190 if(metric >= KERNEL_INFINITY) {
191 api.flags = ZEBRA_FLAG_BLACKHOLE;
192 api.nexthop_num = 0;
193 } else {
194 api.nexthop_num = 1;
195 api.nexthop = &nexthop_pointer;
196 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
197 api.metric = metric;
198 }
Paul Jakma57345092011-12-25 17:52:09 +0100199
200 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv4) to zebra");
201 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
202 &quagga_prefix, &api);
203}
204
205static int
206kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100207 const unsigned char *gate, int ifindex, unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100208{
209 unsigned int tmp_ifindex = ifindex; /* (for typing) */
210 struct zapi_ipv6 api; /* quagga's communication system */
211 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
212 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
213 struct in6_addr nexthop; /* next router to go */
214 struct in6_addr *nexthop_pointer = &nexthop;
215
Matthieu Boutier53b21952012-01-31 17:09:55 +0100216 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100217 /* convert given addresses */
218 uchar_to_in6addr(&babel_prefix_addr, pref);
219 uchar_to_in6addr(&nexthop, gate);
220
221 /* make prefix structure */
222 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
223 quagga_prefix.family = AF_INET6;
224 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
225 quagga_prefix.prefixlen = plen;
226 apply_mask_ipv6(&quagga_prefix);
227
228 api.type = ZEBRA_ROUTE_BABEL;
229 api.flags = 0;
230 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400231 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100232 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100233 if(metric >= KERNEL_INFINITY) {
234 api.nexthop_num = 0;
235 api.ifindex_num = 0;
236 } else {
237 api.nexthop_num = 1;
238 api.nexthop = &nexthop_pointer;
239 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
240 api.ifindex_num = 1;
241 api.ifindex = &tmp_ifindex;
242 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
243 api.metric = metric;
244 }
Paul Jakma57345092011-12-25 17:52:09 +0100245
246 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
247 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
248 &quagga_prefix, &api);
249}
250
251static int
252kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
253 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100254 unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100255{
Paul Jakma57345092011-12-25 17:52:09 +0100256 struct zapi_ipv4 api; /* quagga's communication system */
257 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
258 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
259 struct in_addr nexthop; /* next router to go */
260 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
261
Matthieu Boutier53b21952012-01-31 17:09:55 +0100262 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100263 /* convert given addresses */
264 uchar_to_inaddr(&babel_prefix_addr, pref);
265 uchar_to_inaddr(&nexthop, gate);
266
267 /* make prefix structure */
268 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
269 quagga_prefix.family = AF_INET;
270 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
271 quagga_prefix.prefixlen = plen - 96;
272 apply_mask_ipv4(&quagga_prefix);
273
274 api.type = ZEBRA_ROUTE_BABEL;
275 api.flags = 0;
276 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400277 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100278 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
Juliusz Chroboczekb6475ec2012-02-09 12:29:10 +0100279 api.ifindex_num = 0;
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100280 if(metric >= KERNEL_INFINITY) {
281 api.flags = ZEBRA_FLAG_BLACKHOLE;
282 api.nexthop_num = 0;
283 } else {
284 api.nexthop_num = 1;
285 api.nexthop = &nexthop_pointer;
286 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
287 api.metric = metric;
288 }
Paul Jakma57345092011-12-25 17:52:09 +0100289
290 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
291 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
292 &quagga_prefix, &api);
293}
294
295static int
296kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
297 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100298 unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100299{
300 unsigned int tmp_ifindex = ifindex; /* (for typing) */
301 struct zapi_ipv6 api; /* quagga's communication system */
302 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
303 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
304 struct in6_addr nexthop; /* next router to go */
305 struct in6_addr *nexthop_pointer = &nexthop;
306
Matthieu Boutier53b21952012-01-31 17:09:55 +0100307 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100308 /* convert given addresses */
309 uchar_to_in6addr(&babel_prefix_addr, pref);
310 uchar_to_in6addr(&nexthop, gate);
311
312 /* make prefix structure */
313 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
314 quagga_prefix.family = AF_INET6;
315 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
316 quagga_prefix.prefixlen = plen;
317 apply_mask_ipv6(&quagga_prefix);
318
319 api.type = ZEBRA_ROUTE_BABEL;
320 api.flags = 0;
321 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400322 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100323 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100324 if(metric >= KERNEL_INFINITY) {
325 api.flags = ZEBRA_FLAG_BLACKHOLE;
326 api.nexthop_num = 0;
327 api.ifindex_num = 0;
328 } else {
329 api.nexthop_num = 1;
330 api.nexthop = &nexthop_pointer;
331 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
332 api.ifindex_num = 1;
333 api.ifindex = &tmp_ifindex;
334 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
335 api.metric = metric;
336 }
Paul Jakma57345092011-12-25 17:52:09 +0100337
338 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
339 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
340 &quagga_prefix, &api);
341}
342
343int
Paul Jakma57345092011-12-25 17:52:09 +0100344if_eui64(char *ifname, int ifindex, unsigned char *eui)
345{
346 struct interface *ifp = if_lookup_by_index(ifindex);
347 if (ifp == NULL) {
348 return -1;
349 }
350#ifdef HAVE_STRUCT_SOCKADDR_DL
351 u_char len = ifp->sdl.sdl_alen;
352 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
353#else
354 u_char len = (u_char) ifp->hw_addr_len;
355 char *tmp = (void*) ifp->hw_addr;
356#endif
357 if (len == 8) {
358 memcpy(eui, tmp, 8);
359 eui[0] ^= 2;
360 } else if (len == 6) {
361 memcpy(eui, tmp, 3);
362 eui[3] = 0xFF;
363 eui[4] = 0xFE;
364 memcpy(eui+5, tmp+3, 3);
Paul Jakma57345092011-12-25 17:52:09 +0100365 } else {
366 return -1;
367 }
368 return 0;
369}