]> git.proxmox.com Git - mirror_frr.git/blob - babeld/kernel_zebra.c
babeld: Initial import, for Babel routing protocol.
[mirror_frr.git] / babeld / kernel_zebra.c
1 /*
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 *
18 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
19
20 Permission is hereby granted, free of charge, to any person obtaining a copy
21 of this software and associated documentation files (the "Software"), to deal
22 in the Software without restriction, including without limitation the rights
23 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 copies of the Software, and to permit persons to whom the Software is
25 furnished to do so, subject to the following conditions:
26
27 The above copyright notice and this permission notice shall be included in
28 all copies or substantial portions of the Software.
29
30 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 THE 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
60 static int
61 kernel_route_add_v4(const unsigned char *pref, unsigned short plen,
62 const unsigned char *gate, int ifindex, unsigned int metric,
63 const unsigned char *newgate, int newifindex,
64 unsigned int newmetric);
65 static int
66 kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
67 const unsigned char *gate, int ifindex, unsigned int metric,
68 const unsigned char *newgate, int newifindex,
69 unsigned int newmetric);
70 static int
71 kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
72 const unsigned char *gate, int ifindex,
73 unsigned int metric,
74 const unsigned char *newgate, int newifindex,
75 unsigned int newmetric);
76 static int
77 kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
78 const unsigned char *gate, int ifindex,
79 unsigned int metric,
80 const unsigned char *newgate, int newifindex,
81 unsigned int newmetric);
82
83
84 int export_table = -1, import_table = -1; /* just for compatibility */
85
86 int
87 kernel_setup(int setup)
88 {
89 return 0;
90 }
91
92 /* get a connection with zebra client, at all costs */
93 int
94 kernel_setup_socket(int setup)
95 {
96 return -1;
97 }
98
99 int
100 kernel_setup_interface(int setup, struct interface *interface)
101 {
102 return 1;
103 }
104
105 int
106 kernel_interface_operational(struct interface *interface)
107 {
108 return if_is_operative(interface);
109 }
110
111 int
112 kernel_interface_ipv4(struct interface *interface, unsigned char *addr_r)
113 {
114 assert(0); /* function not used */
115 return -1;
116 }
117
118 int
119 kernel_interface_mtu(struct interface *interface)
120 {
121 return MIN(interface->mtu, interface->mtu6);
122 }
123
124 int
125 kernel_interface_wireless(struct interface *interface)
126 {
127 return 0;
128 }
129
130 extern int
131 zapi_ipv6_route (u_char cmd, struct zclient *zclient,
132 struct prefix_ipv6 *p, struct zapi_ipv6 *api);
133
134 int
135 kernel_route(int operation, const unsigned char *pref, unsigned short plen,
136 const unsigned char *gate, int ifindex, unsigned int metric,
137 const unsigned char *newgate, int newifindex,
138 unsigned int newmetric)
139 {
140 int rc;
141 int added;
142 int ipv4;
143
144 /* Check that the protocol family is consistent. */
145 if(plen >= 96 && v4mapped(pref)) {
146 if(!v4mapped(gate)) {
147 errno = EINVAL;
148 return -1;
149 }
150 ipv4 = 1;
151 } else {
152 if(v4mapped(gate)) {
153 errno = EINVAL;
154 return -1;
155 }
156 ipv4 = 0;
157 }
158
159 switch (operation) {
160 case ROUTE_ADD:
161 return ipv4 ?
162 kernel_route_add_v4(pref, plen, gate, ifindex, metric,
163 newgate, newifindex, newmetric):
164 kernel_route_add_v6(pref, plen, gate, ifindex, metric,
165 newgate, newifindex, newmetric);
166 break;
167 case ROUTE_FLUSH:
168 return ipv4 ?
169 kernel_route_delete_v4(pref, plen, gate, ifindex, metric,
170 newgate, newifindex, newmetric):
171 kernel_route_delete_v6(pref, plen, gate, ifindex, metric,
172 newgate, newifindex, newmetric);
173 break;
174 case ROUTE_MODIFY:
175 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
176 newifindex == ifindex)
177 return 0;
178 /* It is better to add the new route before removing the old
179 one, to avoid losing packets. However, if the old and new
180 priorities are equal, this only works if the kernel supports
181 ECMP. So we first try the "right" order, and fall back on
182 the "wrong" order if it fails with EEXIST. */
183 rc = ipv4 ?
184 kernel_route_add_v4(pref, plen,
185 newgate, newifindex, newmetric,
186 NULL, 0, 0):
187 kernel_route_add_v6(pref, plen,
188 newgate, newifindex, newmetric,
189 NULL, 0, 0);
190 if(rc < 0) {
191 if(errno != EEXIST)
192 return rc;
193 added = 0;
194 } else {
195 added = 1;
196 }
197
198 if (ipv4) {
199 kernel_route_delete_v4(pref, plen,
200 gate, ifindex, metric,
201 NULL, 0, 0);
202 } else {
203 kernel_route_delete_v6(pref, plen,
204 gate, ifindex, metric,
205 NULL, 0, 0);
206 }
207
208 if(!added) {
209 rc = ipv4 ?
210 kernel_route_add_v4(pref, plen,
211 newgate, newifindex, newmetric,
212 NULL, 0, 0):
213 kernel_route_add_v6(pref, plen,
214 newgate, newifindex, newmetric,
215 NULL, 0, 0);
216 if(rc < 0) {
217 if(errno == EEXIST)
218 rc = 1;
219 /* In principle, we should try to re-install the flushed
220 route on failure to preserve. However, this should
221 hopefully not matter much in practice. */
222 }
223 }
224
225 return rc;
226 break;
227 default:
228 zlog_err("this should never appens (false value - kernel_route)");
229 assert(0);
230 exit(1);
231 break;
232 }
233 }
234
235 static int
236 kernel_route_add_v4(const unsigned char *pref, unsigned short plen,
237 const unsigned char *gate, int ifindex, unsigned int metric,
238 const unsigned char *newgate, int newifindex,
239 unsigned int newmetric)
240 {
241 unsigned int tmp_ifindex = ifindex; /* (for typing) */
242 struct zapi_ipv4 api; /* quagga's communication system */
243 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
244 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
245 struct in_addr nexthop; /* next router to go */
246 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
247
248 /* convert to be comprehensive by quagga */
249 /* convert given addresses */
250 uchar_to_inaddr(&babel_prefix_addr, pref);
251 uchar_to_inaddr(&nexthop, gate);
252
253 /* make prefix structure */
254 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
255 quagga_prefix.family = AF_INET;
256 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
257 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
258 apply_mask_ipv4(&quagga_prefix);
259
260 api.type = ZEBRA_ROUTE_BABEL;
261 api.flags = 0;
262 api.message = 0;
263 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
264 api.nexthop_num = 1;
265 api.nexthop = &nexthop_pointer;
266 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
267 api.ifindex_num = 1;
268 api.ifindex = &tmp_ifindex;
269 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
270 api.metric = metric;
271
272 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv4) to zebra");
273 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
274 &quagga_prefix, &api);
275 }
276
277 static int
278 kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
279 const unsigned char *gate, int ifindex, unsigned int metric,
280 const unsigned char *newgate, int newifindex,
281 unsigned int newmetric)
282 {
283 unsigned int tmp_ifindex = ifindex; /* (for typing) */
284 struct zapi_ipv6 api; /* quagga's communication system */
285 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
286 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
287 struct in6_addr nexthop; /* next router to go */
288 struct in6_addr *nexthop_pointer = &nexthop;
289
290 /* convert to be comprehensive by quagga */
291 /* convert given addresses */
292 uchar_to_in6addr(&babel_prefix_addr, pref);
293 uchar_to_in6addr(&nexthop, gate);
294
295 /* make prefix structure */
296 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
297 quagga_prefix.family = AF_INET6;
298 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
299 quagga_prefix.prefixlen = plen;
300 apply_mask_ipv6(&quagga_prefix);
301
302 api.type = ZEBRA_ROUTE_BABEL;
303 api.flags = 0;
304 api.message = 0;
305 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
306 api.nexthop_num = 1;
307 api.nexthop = &nexthop_pointer;
308 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
309 api.ifindex_num = 1;
310 api.ifindex = &tmp_ifindex;
311 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
312 api.metric = metric;
313
314 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
315 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
316 &quagga_prefix, &api);
317 }
318
319 static int
320 kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
321 const unsigned char *gate, int ifindex,
322 unsigned int metric,
323 const unsigned char *newgate, int newifindex,
324 unsigned int newmetric)
325 {
326 unsigned int tmp_ifindex = ifindex; /* (for typing) */
327 struct zapi_ipv4 api; /* quagga's communication system */
328 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
329 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
330 struct in_addr nexthop; /* next router to go */
331 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
332
333 /* convert to be comprehensive by quagga */
334 /* convert given addresses */
335 uchar_to_inaddr(&babel_prefix_addr, pref);
336 uchar_to_inaddr(&nexthop, gate);
337
338 /* make prefix structure */
339 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
340 quagga_prefix.family = AF_INET;
341 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
342 quagga_prefix.prefixlen = plen - 96;
343 apply_mask_ipv4(&quagga_prefix);
344
345 api.type = ZEBRA_ROUTE_BABEL;
346 api.flags = 0;
347 api.message = 0;
348 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
349 api.nexthop_num = 1;
350 api.nexthop = &nexthop_pointer;
351 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
352 api.ifindex_num = 1;
353 api.ifindex = &tmp_ifindex;
354 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
355 api.metric = metric;
356
357 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
358 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
359 &quagga_prefix, &api);
360 }
361
362 static int
363 kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
364 const unsigned char *gate, int ifindex,
365 unsigned int metric,
366 const unsigned char *newgate, int newifindex,
367 unsigned int newmetric)
368 {
369 unsigned int tmp_ifindex = ifindex; /* (for typing) */
370 struct zapi_ipv6 api; /* quagga's communication system */
371 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
372 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
373 struct in6_addr nexthop; /* next router to go */
374 struct in6_addr *nexthop_pointer = &nexthop;
375
376 /* convert to be comprehensive by quagga */
377 /* convert given addresses */
378 uchar_to_in6addr(&babel_prefix_addr, pref);
379 uchar_to_in6addr(&nexthop, gate);
380
381 /* make prefix structure */
382 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
383 quagga_prefix.family = AF_INET6;
384 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
385 quagga_prefix.prefixlen = plen;
386 apply_mask_ipv6(&quagga_prefix);
387
388 api.type = ZEBRA_ROUTE_BABEL;
389 api.flags = 0;
390 api.message = 0;
391 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
392 api.nexthop_num = 1;
393 api.nexthop = &nexthop_pointer;
394 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
395 api.ifindex_num = 1;
396 api.ifindex = &tmp_ifindex;
397
398 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
399 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
400 &quagga_prefix, &api);
401 }
402
403 int
404 kernel_routes(struct kernel_route *routes, int maxroutes)
405 {
406 fprintf(stderr, "\tkernel_routes --- not implemented\n");
407 return 0;
408 }
409
410 int
411 kernel_callback(int (*fn)(int, void*), void *closure)
412 {
413 struct thread thread;
414 fprintf(stderr, "\tkernel_callback\n");
415 /* do a little work on threads */
416 if (thread_fetch(master, &thread) != NULL) {
417 thread_call (&thread);
418 }
419 return 0;
420 }
421
422 int
423 kernel_addresses(struct interface *interface, int ll,
424 struct kernel_route *routes, int maxroutes)
425 {
426 fprintf(stderr, "\tkernel_addresses --- not implemented\n");
427 return 0;
428 }
429
430 int
431 if_eui64(char *ifname, int ifindex, unsigned char *eui)
432 {
433 struct interface *ifp = if_lookup_by_index(ifindex);
434 if (ifp == NULL) {
435 return -1;
436 }
437 #ifdef HAVE_STRUCT_SOCKADDR_DL
438 u_char len = ifp->sdl.sdl_alen;
439 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
440 #else
441 u_char len = (u_char) ifp->hw_addr_len;
442 char *tmp = (void*) ifp->hw_addr;
443 #endif
444 if (len == 8) {
445 memcpy(eui, tmp, 8);
446 eui[0] ^= 2;
447 } else if (len == 6) {
448 memcpy(eui, tmp, 3);
449 eui[3] = 0xFF;
450 eui[4] = 0xFE;
451 memcpy(eui+5, tmp+3, 3);
452 } else if (len > 8) {
453 memcpy(eui, tmp, 8);
454 } else if (len > 0){
455 memset(eui, 0, 8 - len);
456 memcpy(eui + 8 - len, tmp, len);
457 } else {
458 return -1;
459 }
460 return 0;
461 }