blob: 97b7c5846840e318547c9decd093aca6f25eded5 [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;
Paul Jakma57345092011-12-25 17:52:09 +0100108 int ipv4;
109
110 /* Check that the protocol family is consistent. */
111 if(plen >= 96 && v4mapped(pref)) {
112 if(!v4mapped(gate)) {
113 errno = EINVAL;
114 return -1;
115 }
116 ipv4 = 1;
117 } else {
118 if(v4mapped(gate)) {
119 errno = EINVAL;
120 return -1;
121 }
122 ipv4 = 0;
123 }
124
125 switch (operation) {
126 case ROUTE_ADD:
127 return ipv4 ?
128 kernel_route_add_v4(pref, plen, gate, ifindex, metric,
129 newgate, newifindex, newmetric):
130 kernel_route_add_v6(pref, plen, gate, ifindex, metric,
131 newgate, newifindex, newmetric);
132 break;
133 case ROUTE_FLUSH:
134 return ipv4 ?
135 kernel_route_delete_v4(pref, plen, gate, ifindex, metric,
136 newgate, newifindex, newmetric):
137 kernel_route_delete_v6(pref, plen, gate, ifindex, metric,
138 newgate, newifindex, newmetric);
139 break;
140 case ROUTE_MODIFY:
141 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
142 newifindex == ifindex)
143 return 0;
Matthieu Boutierec8d8d52012-01-20 15:32:16 +0100144 debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
Paul Jakma57345092011-12-25 17:52:09 +0100145 if (ipv4) {
146 kernel_route_delete_v4(pref, plen,
147 gate, ifindex, metric,
148 NULL, 0, 0);
149 } else {
150 kernel_route_delete_v6(pref, plen,
151 gate, ifindex, metric,
152 NULL, 0, 0);
153 }
154
Matthieu Boutierec8d8d52012-01-20 15:32:16 +0100155 rc = ipv4 ?
156 kernel_route_add_v4(pref, plen,
157 newgate, newifindex, newmetric,
158 NULL, 0, 0):
159 kernel_route_add_v6(pref, plen,
160 newgate, newifindex, newmetric,
161 NULL, 0, 0);
162 if(rc < 0) {
163 if(errno == EEXIST)
164 rc = 1;
165 /* In principle, we should try to re-install the flushed
166 route on failure to preserve. However, this should
167 hopefully not matter much in practice. */
Paul Jakma57345092011-12-25 17:52:09 +0100168 }
169
170 return rc;
171 break;
172 default:
173 zlog_err("this should never appens (false value - kernel_route)");
174 assert(0);
175 exit(1);
176 break;
177 }
178}
179
180static int
181kernel_route_add_v4(const unsigned char *pref, unsigned short plen,
182 const unsigned char *gate, int ifindex, unsigned int metric,
183 const unsigned char *newgate, int newifindex,
184 unsigned int newmetric)
185{
186 unsigned int tmp_ifindex = ifindex; /* (for typing) */
187 struct zapi_ipv4 api; /* quagga's communication system */
188 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
189 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
190 struct in_addr nexthop; /* next router to go */
191 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
192
193 /* convert to be comprehensive by quagga */
194 /* convert given addresses */
195 uchar_to_inaddr(&babel_prefix_addr, pref);
196 uchar_to_inaddr(&nexthop, gate);
197
198 /* make prefix structure */
199 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
200 quagga_prefix.family = AF_INET;
201 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
202 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
203 apply_mask_ipv4(&quagga_prefix);
204
205 api.type = ZEBRA_ROUTE_BABEL;
206 api.flags = 0;
207 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400208 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100209 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;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400251 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100252 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
253 api.nexthop_num = 1;
254 api.nexthop = &nexthop_pointer;
255 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
256 api.ifindex_num = 1;
257 api.ifindex = &tmp_ifindex;
258 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
259 api.metric = metric;
260
261 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
262 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
263 &quagga_prefix, &api);
264}
265
266static int
267kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
268 const unsigned char *gate, int ifindex,
269 unsigned int metric,
270 const unsigned char *newgate, int newifindex,
271 unsigned int newmetric)
272{
273 unsigned int tmp_ifindex = ifindex; /* (for typing) */
274 struct zapi_ipv4 api; /* quagga's communication system */
275 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
276 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
277 struct in_addr nexthop; /* next router to go */
278 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
279
280 /* convert to be comprehensive by quagga */
281 /* convert given addresses */
282 uchar_to_inaddr(&babel_prefix_addr, pref);
283 uchar_to_inaddr(&nexthop, gate);
284
285 /* make prefix structure */
286 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
287 quagga_prefix.family = AF_INET;
288 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
289 quagga_prefix.prefixlen = plen - 96;
290 apply_mask_ipv4(&quagga_prefix);
291
292 api.type = ZEBRA_ROUTE_BABEL;
293 api.flags = 0;
294 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400295 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100296 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
297 api.nexthop_num = 1;
298 api.nexthop = &nexthop_pointer;
299 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
300 api.ifindex_num = 1;
301 api.ifindex = &tmp_ifindex;
302 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
303 api.metric = metric;
304
305 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
306 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
307 &quagga_prefix, &api);
308}
309
310static int
311kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
312 const unsigned char *gate, int ifindex,
313 unsigned int metric,
314 const unsigned char *newgate, int newifindex,
315 unsigned int newmetric)
316{
317 unsigned int tmp_ifindex = ifindex; /* (for typing) */
318 struct zapi_ipv6 api; /* quagga's communication system */
319 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
320 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
321 struct in6_addr nexthop; /* next router to go */
322 struct in6_addr *nexthop_pointer = &nexthop;
323
324 /* convert to be comprehensive by quagga */
325 /* convert given addresses */
326 uchar_to_in6addr(&babel_prefix_addr, pref);
327 uchar_to_in6addr(&nexthop, gate);
328
329 /* make prefix structure */
330 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
331 quagga_prefix.family = AF_INET6;
332 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
333 quagga_prefix.prefixlen = plen;
334 apply_mask_ipv6(&quagga_prefix);
335
336 api.type = ZEBRA_ROUTE_BABEL;
337 api.flags = 0;
338 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400339 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100340 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
341 api.nexthop_num = 1;
342 api.nexthop = &nexthop_pointer;
343 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
344 api.ifindex_num = 1;
345 api.ifindex = &tmp_ifindex;
346
347 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
348 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
349 &quagga_prefix, &api);
350}
351
352int
Paul Jakma57345092011-12-25 17:52:09 +0100353if_eui64(char *ifname, int ifindex, unsigned char *eui)
354{
355 struct interface *ifp = if_lookup_by_index(ifindex);
356 if (ifp == NULL) {
357 return -1;
358 }
359#ifdef HAVE_STRUCT_SOCKADDR_DL
360 u_char len = ifp->sdl.sdl_alen;
361 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
362#else
363 u_char len = (u_char) ifp->hw_addr_len;
364 char *tmp = (void*) ifp->hw_addr;
365#endif
366 if (len == 8) {
367 memcpy(eui, tmp, 8);
368 eui[0] ^= 2;
369 } else if (len == 6) {
370 memcpy(eui, tmp, 3);
371 eui[3] = 0xFF;
372 eui[4] = 0xFE;
373 memcpy(eui+5, tmp+3, 3);
Paul Jakma57345092011-12-25 17:52:09 +0100374 } else {
375 return -1;
376 }
377 return 0;
378}