blob: 53da5f4021a9116f5fb1b855491f78568856c1f4 [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;
Matthieu Boutierec8d8d52012-01-20 15:32:16 +0100145 debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
Paul Jakma57345092011-12-25 17:52:09 +0100146 if (ipv4) {
147 kernel_route_delete_v4(pref, plen,
148 gate, ifindex, metric,
149 NULL, 0, 0);
150 } else {
151 kernel_route_delete_v6(pref, plen,
152 gate, ifindex, metric,
153 NULL, 0, 0);
154 }
155
Matthieu Boutierec8d8d52012-01-20 15:32:16 +0100156 rc = ipv4 ?
157 kernel_route_add_v4(pref, plen,
158 newgate, newifindex, newmetric,
159 NULL, 0, 0):
160 kernel_route_add_v6(pref, plen,
161 newgate, newifindex, newmetric,
162 NULL, 0, 0);
163 if(rc < 0) {
164 if(errno == EEXIST)
165 rc = 1;
166 /* In principle, we should try to re-install the flushed
167 route on failure to preserve. However, this should
168 hopefully not matter much in practice. */
Paul Jakma57345092011-12-25 17:52:09 +0100169 }
170
171 return rc;
172 break;
173 default:
174 zlog_err("this should never appens (false value - kernel_route)");
175 assert(0);
176 exit(1);
177 break;
178 }
179}
180
181static int
182kernel_route_add_v4(const unsigned char *pref, unsigned short plen,
183 const unsigned char *gate, int ifindex, unsigned int metric,
184 const unsigned char *newgate, int newifindex,
185 unsigned int newmetric)
186{
187 unsigned int tmp_ifindex = ifindex; /* (for typing) */
188 struct zapi_ipv4 api; /* quagga's communication system */
189 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
190 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
191 struct in_addr nexthop; /* next router to go */
192 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
193
194 /* convert to be comprehensive by quagga */
195 /* convert given addresses */
196 uchar_to_inaddr(&babel_prefix_addr, pref);
197 uchar_to_inaddr(&nexthop, gate);
198
199 /* make prefix structure */
200 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
201 quagga_prefix.family = AF_INET;
202 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
203 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
204 apply_mask_ipv4(&quagga_prefix);
205
206 api.type = ZEBRA_ROUTE_BABEL;
207 api.flags = 0;
208 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400209 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100210 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
211 api.nexthop_num = 1;
212 api.nexthop = &nexthop_pointer;
213 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
214 api.ifindex_num = 1;
215 api.ifindex = &tmp_ifindex;
216 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
217 api.metric = metric;
218
219 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv4) to zebra");
220 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
221 &quagga_prefix, &api);
222}
223
224static int
225kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
226 const unsigned char *gate, int ifindex, unsigned int metric,
227 const unsigned char *newgate, int newifindex,
228 unsigned int newmetric)
229{
230 unsigned int tmp_ifindex = ifindex; /* (for typing) */
231 struct zapi_ipv6 api; /* quagga's communication system */
232 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
233 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
234 struct in6_addr nexthop; /* next router to go */
235 struct in6_addr *nexthop_pointer = &nexthop;
236
237 /* convert to be comprehensive by quagga */
238 /* convert given addresses */
239 uchar_to_in6addr(&babel_prefix_addr, pref);
240 uchar_to_in6addr(&nexthop, gate);
241
242 /* make prefix structure */
243 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
244 quagga_prefix.family = AF_INET6;
245 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
246 quagga_prefix.prefixlen = plen;
247 apply_mask_ipv6(&quagga_prefix);
248
249 api.type = ZEBRA_ROUTE_BABEL;
250 api.flags = 0;
251 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400252 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100253 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
254 api.nexthop_num = 1;
255 api.nexthop = &nexthop_pointer;
256 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
257 api.ifindex_num = 1;
258 api.ifindex = &tmp_ifindex;
259 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
260 api.metric = metric;
261
262 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
263 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
264 &quagga_prefix, &api);
265}
266
267static int
268kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
269 const unsigned char *gate, int ifindex,
270 unsigned int metric,
271 const unsigned char *newgate, int newifindex,
272 unsigned int newmetric)
273{
274 unsigned int tmp_ifindex = ifindex; /* (for typing) */
275 struct zapi_ipv4 api; /* quagga's communication system */
276 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
277 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
278 struct in_addr nexthop; /* next router to go */
279 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
280
281 /* convert to be comprehensive by quagga */
282 /* convert given addresses */
283 uchar_to_inaddr(&babel_prefix_addr, pref);
284 uchar_to_inaddr(&nexthop, gate);
285
286 /* make prefix structure */
287 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
288 quagga_prefix.family = AF_INET;
289 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
290 quagga_prefix.prefixlen = plen - 96;
291 apply_mask_ipv4(&quagga_prefix);
292
293 api.type = ZEBRA_ROUTE_BABEL;
294 api.flags = 0;
295 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400296 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100297 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
298 api.nexthop_num = 1;
299 api.nexthop = &nexthop_pointer;
300 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
301 api.ifindex_num = 1;
302 api.ifindex = &tmp_ifindex;
303 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
304 api.metric = metric;
305
306 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
307 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
308 &quagga_prefix, &api);
309}
310
311static int
312kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
313 const unsigned char *gate, int ifindex,
314 unsigned int metric,
315 const unsigned char *newgate, int newifindex,
316 unsigned int newmetric)
317{
318 unsigned int tmp_ifindex = ifindex; /* (for typing) */
319 struct zapi_ipv6 api; /* quagga's communication system */
320 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
321 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
322 struct in6_addr nexthop; /* next router to go */
323 struct in6_addr *nexthop_pointer = &nexthop;
324
325 /* convert to be comprehensive by quagga */
326 /* convert given addresses */
327 uchar_to_in6addr(&babel_prefix_addr, pref);
328 uchar_to_in6addr(&nexthop, gate);
329
330 /* make prefix structure */
331 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
332 quagga_prefix.family = AF_INET6;
333 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
334 quagga_prefix.prefixlen = plen;
335 apply_mask_ipv6(&quagga_prefix);
336
337 api.type = ZEBRA_ROUTE_BABEL;
338 api.flags = 0;
339 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400340 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100341 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
342 api.nexthop_num = 1;
343 api.nexthop = &nexthop_pointer;
344 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
345 api.ifindex_num = 1;
346 api.ifindex = &tmp_ifindex;
347
348 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
349 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
350 &quagga_prefix, &api);
351}
352
353int
Paul Jakma57345092011-12-25 17:52:09 +0100354if_eui64(char *ifname, int ifindex, unsigned char *eui)
355{
356 struct interface *ifp = if_lookup_by_index(ifindex);
357 if (ifp == NULL) {
358 return -1;
359 }
360#ifdef HAVE_STRUCT_SOCKADDR_DL
361 u_char len = ifp->sdl.sdl_alen;
362 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
363#else
364 u_char len = (u_char) ifp->hw_addr_len;
365 char *tmp = (void*) ifp->hw_addr;
366#endif
367 if (len == 8) {
368 memcpy(eui, tmp, 8);
369 eui[0] ^= 2;
370 } else if (len == 6) {
371 memcpy(eui, tmp, 3);
372 eui[3] = 0xFF;
373 eui[4] = 0xFE;
374 memcpy(eui+5, tmp+3, 3);
375 } else if (len > 8) {
376 memcpy(eui, tmp, 8);
377 } else if (len > 0){
378 memset(eui, 0, 8 - len);
379 memcpy(eui + 8 - len, tmp, len);
380 } else {
381 return -1;
382 }
383 return 0;
384}