blob: 7ddc797dc6e4810b77b5ad8d8365179a4984c757 [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;
209 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
210 api.nexthop_num = 1;
211 api.nexthop = &nexthop_pointer;
212 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
213 api.ifindex_num = 1;
214 api.ifindex = &tmp_ifindex;
215 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
216 api.metric = metric;
217
218 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv4) to zebra");
219 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
220 &quagga_prefix, &api);
221}
222
223static int
224kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
225 const unsigned char *gate, int ifindex, unsigned int metric,
226 const unsigned char *newgate, int newifindex,
227 unsigned int newmetric)
228{
229 unsigned int tmp_ifindex = ifindex; /* (for typing) */
230 struct zapi_ipv6 api; /* quagga's communication system */
231 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
232 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
233 struct in6_addr nexthop; /* next router to go */
234 struct in6_addr *nexthop_pointer = &nexthop;
235
236 /* convert to be comprehensive by quagga */
237 /* convert given addresses */
238 uchar_to_in6addr(&babel_prefix_addr, pref);
239 uchar_to_in6addr(&nexthop, gate);
240
241 /* make prefix structure */
242 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
243 quagga_prefix.family = AF_INET6;
244 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
245 quagga_prefix.prefixlen = plen;
246 apply_mask_ipv6(&quagga_prefix);
247
248 api.type = ZEBRA_ROUTE_BABEL;
249 api.flags = 0;
250 api.message = 0;
251 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
252 api.nexthop_num = 1;
253 api.nexthop = &nexthop_pointer;
254 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
255 api.ifindex_num = 1;
256 api.ifindex = &tmp_ifindex;
257 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
258 api.metric = metric;
259
260 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
261 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
262 &quagga_prefix, &api);
263}
264
265static int
266kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
267 const unsigned char *gate, int ifindex,
268 unsigned int metric,
269 const unsigned char *newgate, int newifindex,
270 unsigned int newmetric)
271{
272 unsigned int tmp_ifindex = ifindex; /* (for typing) */
273 struct zapi_ipv4 api; /* quagga's communication system */
274 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
275 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
276 struct in_addr nexthop; /* next router to go */
277 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
278
279 /* convert to be comprehensive by quagga */
280 /* convert given addresses */
281 uchar_to_inaddr(&babel_prefix_addr, pref);
282 uchar_to_inaddr(&nexthop, gate);
283
284 /* make prefix structure */
285 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
286 quagga_prefix.family = AF_INET;
287 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
288 quagga_prefix.prefixlen = plen - 96;
289 apply_mask_ipv4(&quagga_prefix);
290
291 api.type = ZEBRA_ROUTE_BABEL;
292 api.flags = 0;
293 api.message = 0;
294 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
295 api.nexthop_num = 1;
296 api.nexthop = &nexthop_pointer;
297 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
298 api.ifindex_num = 1;
299 api.ifindex = &tmp_ifindex;
300 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
301 api.metric = metric;
302
303 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
304 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
305 &quagga_prefix, &api);
306}
307
308static int
309kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
310 const unsigned char *gate, int ifindex,
311 unsigned int metric,
312 const unsigned char *newgate, int newifindex,
313 unsigned int newmetric)
314{
315 unsigned int tmp_ifindex = ifindex; /* (for typing) */
316 struct zapi_ipv6 api; /* quagga's communication system */
317 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
318 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
319 struct in6_addr nexthop; /* next router to go */
320 struct in6_addr *nexthop_pointer = &nexthop;
321
322 /* convert to be comprehensive by quagga */
323 /* convert given addresses */
324 uchar_to_in6addr(&babel_prefix_addr, pref);
325 uchar_to_in6addr(&nexthop, gate);
326
327 /* make prefix structure */
328 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
329 quagga_prefix.family = AF_INET6;
330 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
331 quagga_prefix.prefixlen = plen;
332 apply_mask_ipv6(&quagga_prefix);
333
334 api.type = ZEBRA_ROUTE_BABEL;
335 api.flags = 0;
336 api.message = 0;
337 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
338 api.nexthop_num = 1;
339 api.nexthop = &nexthop_pointer;
340 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
341 api.ifindex_num = 1;
342 api.ifindex = &tmp_ifindex;
343
344 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
345 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
346 &quagga_prefix, &api);
347}
348
349int
Paul Jakma57345092011-12-25 17:52:09 +0100350if_eui64(char *ifname, int ifindex, unsigned char *eui)
351{
352 struct interface *ifp = if_lookup_by_index(ifindex);
353 if (ifp == NULL) {
354 return -1;
355 }
356#ifdef HAVE_STRUCT_SOCKADDR_DL
357 u_char len = ifp->sdl.sdl_alen;
358 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
359#else
360 u_char len = (u_char) ifp->hw_addr_len;
361 char *tmp = (void*) ifp->hw_addr;
362#endif
363 if (len == 8) {
364 memcpy(eui, tmp, 8);
365 eui[0] ^= 2;
366 } else if (len == 6) {
367 memcpy(eui, tmp, 3);
368 eui[3] = 0xFF;
369 eui[4] = 0xFE;
370 memcpy(eui+5, tmp+3, 3);
371 } else if (len > 8) {
372 memcpy(eui, tmp, 8);
373 } else if (len > 0){
374 memset(eui, 0, 8 - len);
375 memcpy(eui + 8 - len, tmp, len);
376 } else {
377 return -1;
378 }
379 return 0;
380}