blob: 82f03e436777b1a2d8ffb198034b70c4ad285410 [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,
62 const unsigned char *gate, int ifindex, unsigned int metric,
63 const unsigned char *newgate, int newifindex,
64 unsigned int newmetric);
65static int
66kernel_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);
70static int
71kernel_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);
76static int
77kernel_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
Paul Jakma57345092011-12-25 17:52:09 +010083int
84kernel_interface_operational(struct interface *interface)
85{
86 return if_is_operative(interface);
87}
88
89int
Paul Jakma57345092011-12-25 17:52:09 +010090kernel_interface_mtu(struct interface *interface)
91{
92 return MIN(interface->mtu, interface->mtu6);
93}
94
95int
96kernel_interface_wireless(struct interface *interface)
97{
98 return 0;
99}
100
Paul Jakma57345092011-12-25 17:52:09 +0100101int
102kernel_route(int operation, const unsigned char *pref, unsigned short plen,
103 const unsigned char *gate, int ifindex, unsigned int metric,
104 const unsigned char *newgate, int newifindex,
105 unsigned int newmetric)
106{
107 int rc;
108 int added;
109 int ipv4;
110
111 /* Check that the protocol family is consistent. */
112 if(plen >= 96 && v4mapped(pref)) {
113 if(!v4mapped(gate)) {
114 errno = EINVAL;
115 return -1;
116 }
117 ipv4 = 1;
118 } else {
119 if(v4mapped(gate)) {
120 errno = EINVAL;
121 return -1;
122 }
123 ipv4 = 0;
124 }
125
126 switch (operation) {
127 case ROUTE_ADD:
128 return ipv4 ?
129 kernel_route_add_v4(pref, plen, gate, ifindex, metric,
130 newgate, newifindex, newmetric):
131 kernel_route_add_v6(pref, plen, gate, ifindex, metric,
132 newgate, newifindex, newmetric);
133 break;
134 case ROUTE_FLUSH:
135 return ipv4 ?
136 kernel_route_delete_v4(pref, plen, gate, ifindex, metric,
137 newgate, newifindex, newmetric):
138 kernel_route_delete_v6(pref, plen, gate, ifindex, metric,
139 newgate, newifindex, newmetric);
140 break;
141 case ROUTE_MODIFY:
142 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
143 newifindex == ifindex)
144 return 0;
145 /* It is better to add the new route before removing the old
146 one, to avoid losing packets. However, if the old and new
147 priorities are equal, this only works if the kernel supports
148 ECMP. So we first try the "right" order, and fall back on
149 the "wrong" order if it fails with EEXIST. */
150 rc = ipv4 ?
151 kernel_route_add_v4(pref, plen,
152 newgate, newifindex, newmetric,
153 NULL, 0, 0):
154 kernel_route_add_v6(pref, plen,
155 newgate, newifindex, newmetric,
156 NULL, 0, 0);
157 if(rc < 0) {
158 if(errno != EEXIST)
159 return rc;
160 added = 0;
161 } else {
162 added = 1;
163 }
164
165 if (ipv4) {
166 kernel_route_delete_v4(pref, plen,
167 gate, ifindex, metric,
168 NULL, 0, 0);
169 } else {
170 kernel_route_delete_v6(pref, plen,
171 gate, ifindex, metric,
172 NULL, 0, 0);
173 }
174
175 if(!added) {
176 rc = ipv4 ?
177 kernel_route_add_v4(pref, plen,
178 newgate, newifindex, newmetric,
179 NULL, 0, 0):
180 kernel_route_add_v6(pref, plen,
181 newgate, newifindex, newmetric,
182 NULL, 0, 0);
183 if(rc < 0) {
184 if(errno == EEXIST)
185 rc = 1;
186 /* In principle, we should try to re-install the flushed
187 route on failure to preserve. However, this should
188 hopefully not matter much in practice. */
189 }
190 }
191
192 return rc;
193 break;
194 default:
195 zlog_err("this should never appens (false value - kernel_route)");
196 assert(0);
197 exit(1);
198 break;
199 }
200}
201
202static int
203kernel_route_add_v4(const unsigned char *pref, unsigned short plen,
204 const unsigned char *gate, int ifindex, unsigned int metric,
205 const unsigned char *newgate, int newifindex,
206 unsigned int newmetric)
207{
208 unsigned int tmp_ifindex = ifindex; /* (for typing) */
209 struct zapi_ipv4 api; /* quagga's communication system */
210 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
211 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
212 struct in_addr nexthop; /* next router to go */
213 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
214
215 /* convert to be comprehensive by quagga */
216 /* convert given addresses */
217 uchar_to_inaddr(&babel_prefix_addr, pref);
218 uchar_to_inaddr(&nexthop, gate);
219
220 /* make prefix structure */
221 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
222 quagga_prefix.family = AF_INET;
223 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
224 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
225 apply_mask_ipv4(&quagga_prefix);
226
227 api.type = ZEBRA_ROUTE_BABEL;
228 api.flags = 0;
229 api.message = 0;
230 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
231 api.nexthop_num = 1;
232 api.nexthop = &nexthop_pointer;
233 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
234 api.ifindex_num = 1;
235 api.ifindex = &tmp_ifindex;
236 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
237 api.metric = metric;
238
239 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv4) to zebra");
240 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
241 &quagga_prefix, &api);
242}
243
244static int
245kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
246 const unsigned char *gate, int ifindex, unsigned int metric,
247 const unsigned char *newgate, int newifindex,
248 unsigned int newmetric)
249{
250 unsigned int tmp_ifindex = ifindex; /* (for typing) */
251 struct zapi_ipv6 api; /* quagga's communication system */
252 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
253 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
254 struct in6_addr nexthop; /* next router to go */
255 struct in6_addr *nexthop_pointer = &nexthop;
256
257 /* convert to be comprehensive by quagga */
258 /* convert given addresses */
259 uchar_to_in6addr(&babel_prefix_addr, pref);
260 uchar_to_in6addr(&nexthop, gate);
261
262 /* make prefix structure */
263 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
264 quagga_prefix.family = AF_INET6;
265 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
266 quagga_prefix.prefixlen = plen;
267 apply_mask_ipv6(&quagga_prefix);
268
269 api.type = ZEBRA_ROUTE_BABEL;
270 api.flags = 0;
271 api.message = 0;
272 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
273 api.nexthop_num = 1;
274 api.nexthop = &nexthop_pointer;
275 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
276 api.ifindex_num = 1;
277 api.ifindex = &tmp_ifindex;
278 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
279 api.metric = metric;
280
281 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
282 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
283 &quagga_prefix, &api);
284}
285
286static int
287kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
288 const unsigned char *gate, int ifindex,
289 unsigned int metric,
290 const unsigned char *newgate, int newifindex,
291 unsigned int newmetric)
292{
293 unsigned int tmp_ifindex = ifindex; /* (for typing) */
294 struct zapi_ipv4 api; /* quagga's communication system */
295 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
296 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
297 struct in_addr nexthop; /* next router to go */
298 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
299
300 /* convert to be comprehensive by quagga */
301 /* convert given addresses */
302 uchar_to_inaddr(&babel_prefix_addr, pref);
303 uchar_to_inaddr(&nexthop, gate);
304
305 /* make prefix structure */
306 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
307 quagga_prefix.family = AF_INET;
308 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
309 quagga_prefix.prefixlen = plen - 96;
310 apply_mask_ipv4(&quagga_prefix);
311
312 api.type = ZEBRA_ROUTE_BABEL;
313 api.flags = 0;
314 api.message = 0;
315 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
316 api.nexthop_num = 1;
317 api.nexthop = &nexthop_pointer;
318 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
319 api.ifindex_num = 1;
320 api.ifindex = &tmp_ifindex;
321 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
322 api.metric = metric;
323
324 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
325 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
326 &quagga_prefix, &api);
327}
328
329static int
330kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
331 const unsigned char *gate, int ifindex,
332 unsigned int metric,
333 const unsigned char *newgate, int newifindex,
334 unsigned int newmetric)
335{
336 unsigned int tmp_ifindex = ifindex; /* (for typing) */
337 struct zapi_ipv6 api; /* quagga's communication system */
338 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
339 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
340 struct in6_addr nexthop; /* next router to go */
341 struct in6_addr *nexthop_pointer = &nexthop;
342
343 /* convert to be comprehensive by quagga */
344 /* convert given addresses */
345 uchar_to_in6addr(&babel_prefix_addr, pref);
346 uchar_to_in6addr(&nexthop, gate);
347
348 /* make prefix structure */
349 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
350 quagga_prefix.family = AF_INET6;
351 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
352 quagga_prefix.prefixlen = plen;
353 apply_mask_ipv6(&quagga_prefix);
354
355 api.type = ZEBRA_ROUTE_BABEL;
356 api.flags = 0;
357 api.message = 0;
358 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
359 api.nexthop_num = 1;
360 api.nexthop = &nexthop_pointer;
361 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
362 api.ifindex_num = 1;
363 api.ifindex = &tmp_ifindex;
364
365 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
366 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
367 &quagga_prefix, &api);
368}
369
370int
Paul Jakma57345092011-12-25 17:52:09 +0100371if_eui64(char *ifname, int ifindex, unsigned char *eui)
372{
373 struct interface *ifp = if_lookup_by_index(ifindex);
374 if (ifp == NULL) {
375 return -1;
376 }
377#ifdef HAVE_STRUCT_SOCKADDR_DL
378 u_char len = ifp->sdl.sdl_alen;
379 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
380#else
381 u_char len = (u_char) ifp->hw_addr_len;
382 char *tmp = (void*) ifp->hw_addr;
383#endif
384 if (len == 8) {
385 memcpy(eui, tmp, 8);
386 eui[0] ^= 2;
387 } else if (len == 6) {
388 memcpy(eui, tmp, 3);
389 eui[3] = 0xFF;
390 eui[4] = 0xFE;
391 memcpy(eui+5, tmp+3, 3);
392 } else if (len > 8) {
393 memcpy(eui, tmp, 8);
394 } else if (len > 0){
395 memset(eui, 0, 8 - len);
396 memcpy(eui + 8 - len, tmp, len);
397 } else {
398 return -1;
399 }
400 return 0;
401}