blob: 85ee1f8d4e8fda4a49255c58e5a5b0d0b72c70c1 [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,
Matthieu Boutier53b21952012-01-31 17:09:55 +010062 const unsigned char *gate, int ifindex,
63 unsigned int metric);
Paul Jakma57345092011-12-25 17:52:09 +010064static int
65kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +010066 const unsigned char *gate, int ifindex,
67 unsigned int metric);
Paul Jakma57345092011-12-25 17:52:09 +010068static int
69kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
70 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +010071 unsigned int metric);
Paul Jakma57345092011-12-25 17:52:09 +010072static int
73kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
74 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +010075 unsigned int metric);
Paul Jakma57345092011-12-25 17:52:09 +010076
Paul Jakma57345092011-12-25 17:52:09 +010077int
78kernel_interface_operational(struct interface *interface)
79{
80 return if_is_operative(interface);
81}
82
83int
Paul Jakma57345092011-12-25 17:52:09 +010084kernel_interface_mtu(struct interface *interface)
85{
86 return MIN(interface->mtu, interface->mtu6);
87}
88
89int
90kernel_interface_wireless(struct interface *interface)
91{
92 return 0;
93}
94
Paul Jakma57345092011-12-25 17:52:09 +010095int
96kernel_route(int operation, const unsigned char *pref, unsigned short plen,
97 const unsigned char *gate, int ifindex, unsigned int metric,
98 const unsigned char *newgate, int newifindex,
99 unsigned int newmetric)
100{
101 int rc;
Paul Jakma57345092011-12-25 17:52:09 +0100102 int ipv4;
103
104 /* Check that the protocol family is consistent. */
105 if(plen >= 96 && v4mapped(pref)) {
106 if(!v4mapped(gate)) {
107 errno = EINVAL;
108 return -1;
109 }
110 ipv4 = 1;
111 } else {
112 if(v4mapped(gate)) {
113 errno = EINVAL;
114 return -1;
115 }
116 ipv4 = 0;
117 }
118
119 switch (operation) {
120 case ROUTE_ADD:
121 return ipv4 ?
Matthieu Boutier53b21952012-01-31 17:09:55 +0100122 kernel_route_add_v4(pref, plen, gate, ifindex, metric):
123 kernel_route_add_v6(pref, plen, gate, ifindex, metric);
Paul Jakma57345092011-12-25 17:52:09 +0100124 break;
125 case ROUTE_FLUSH:
126 return ipv4 ?
Matthieu Boutier53b21952012-01-31 17:09:55 +0100127 kernel_route_delete_v4(pref, plen, gate, ifindex, metric):
128 kernel_route_delete_v6(pref, plen, gate, ifindex, metric);
Paul Jakma57345092011-12-25 17:52:09 +0100129 break;
130 case ROUTE_MODIFY:
131 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
132 newifindex == ifindex)
133 return 0;
Matthieu Boutierec8d8d52012-01-20 15:32:16 +0100134 debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
Matthieu Boutier53b21952012-01-31 17:09:55 +0100135 rc = ipv4 ?
136 kernel_route_delete_v4(pref, plen, gate, ifindex, metric):
137 kernel_route_delete_v6(pref, plen, gate, ifindex, metric);
138
139 if (rc < 0)
140 return -1;
Paul Jakma57345092011-12-25 17:52:09 +0100141
Matthieu Boutierec8d8d52012-01-20 15:32:16 +0100142 rc = ipv4 ?
Matthieu Boutier53b21952012-01-31 17:09:55 +0100143 kernel_route_add_v4(pref, plen, newgate, newifindex, newmetric):
144 kernel_route_add_v6(pref, plen, newgate, newifindex, newmetric);
Paul Jakma57345092011-12-25 17:52:09 +0100145
146 return rc;
147 break;
148 default:
149 zlog_err("this should never appens (false value - kernel_route)");
150 assert(0);
151 exit(1);
152 break;
153 }
154}
155
156static int
157kernel_route_add_v4(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100158 const unsigned char *gate, int ifindex, unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100159{
Paul Jakma57345092011-12-25 17:52:09 +0100160 struct zapi_ipv4 api; /* quagga's communication system */
161 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
162 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
163 struct in_addr nexthop; /* next router to go */
164 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
165
Matthieu Boutier53b21952012-01-31 17:09:55 +0100166 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100167 /* convert given addresses */
168 uchar_to_inaddr(&babel_prefix_addr, pref);
169 uchar_to_inaddr(&nexthop, gate);
170
171 /* make prefix structure */
172 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
173 quagga_prefix.family = AF_INET;
174 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
175 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
176 apply_mask_ipv4(&quagga_prefix);
177
178 api.type = ZEBRA_ROUTE_BABEL;
179 api.flags = 0;
180 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400181 api.safi = SAFI_UNICAST;
Juliusz Chroboczekb6475ec2012-02-09 12:29:10 +0100182
183 /* Unlike the native Linux and BSD interfaces, Quagga doesn't like
184 there to be both and IPv4 nexthop and an ifindex. Omit the
185 ifindex, and assume that the connected prefixes be set up
186 correctly. */
187
Paul Jakma57345092011-12-25 17:52:09 +0100188 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
Juliusz Chroboczekb6475ec2012-02-09 12:29:10 +0100189 api.ifindex_num = 0;
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100190 if(metric >= KERNEL_INFINITY) {
191 api.flags = ZEBRA_FLAG_BLACKHOLE;
192 api.nexthop_num = 0;
193 } else {
194 api.nexthop_num = 1;
195 api.nexthop = &nexthop_pointer;
196 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
197 api.metric = metric;
198 }
Paul Jakma57345092011-12-25 17:52:09 +0100199
200 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv4) to zebra");
201 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
202 &quagga_prefix, &api);
203}
204
205static int
206kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100207 const unsigned char *gate, int ifindex, unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100208{
209 unsigned int tmp_ifindex = ifindex; /* (for typing) */
210 struct zapi_ipv6 api; /* quagga's communication system */
211 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
212 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
213 struct in6_addr nexthop; /* next router to go */
214 struct in6_addr *nexthop_pointer = &nexthop;
215
Matthieu Boutier53b21952012-01-31 17:09:55 +0100216 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100217 /* convert given addresses */
218 uchar_to_in6addr(&babel_prefix_addr, pref);
219 uchar_to_in6addr(&nexthop, gate);
220
221 /* make prefix structure */
222 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
223 quagga_prefix.family = AF_INET6;
224 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
225 quagga_prefix.prefixlen = plen;
226 apply_mask_ipv6(&quagga_prefix);
227
228 api.type = ZEBRA_ROUTE_BABEL;
229 api.flags = 0;
230 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400231 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100232 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100233 if(metric >= KERNEL_INFINITY) {
Juliusz Chroboczekb63b4482012-02-14 11:17:32 +0100234 api.flags = ZEBRA_FLAG_BLACKHOLE;
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100235 api.nexthop_num = 0;
236 api.ifindex_num = 0;
237 } else {
238 api.nexthop_num = 1;
239 api.nexthop = &nexthop_pointer;
240 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
241 api.ifindex_num = 1;
242 api.ifindex = &tmp_ifindex;
243 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
244 api.metric = metric;
245 }
Paul Jakma57345092011-12-25 17:52:09 +0100246
247 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
248 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
249 &quagga_prefix, &api);
250}
251
252static int
253kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
254 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100255 unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100256{
Paul Jakma57345092011-12-25 17:52:09 +0100257 struct zapi_ipv4 api; /* quagga's communication system */
258 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
259 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
260 struct in_addr nexthop; /* next router to go */
261 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
262
Matthieu Boutier53b21952012-01-31 17:09:55 +0100263 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100264 /* convert given addresses */
265 uchar_to_inaddr(&babel_prefix_addr, pref);
266 uchar_to_inaddr(&nexthop, gate);
267
268 /* make prefix structure */
269 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
270 quagga_prefix.family = AF_INET;
271 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
272 quagga_prefix.prefixlen = plen - 96;
273 apply_mask_ipv4(&quagga_prefix);
274
275 api.type = ZEBRA_ROUTE_BABEL;
276 api.flags = 0;
277 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400278 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100279 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
Juliusz Chroboczekb6475ec2012-02-09 12:29:10 +0100280 api.ifindex_num = 0;
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100281 if(metric >= KERNEL_INFINITY) {
282 api.flags = ZEBRA_FLAG_BLACKHOLE;
283 api.nexthop_num = 0;
284 } else {
285 api.nexthop_num = 1;
286 api.nexthop = &nexthop_pointer;
287 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
288 api.metric = metric;
289 }
Paul Jakma57345092011-12-25 17:52:09 +0100290
291 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
292 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
293 &quagga_prefix, &api);
294}
295
296static int
297kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
298 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100299 unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100300{
301 unsigned int tmp_ifindex = ifindex; /* (for typing) */
302 struct zapi_ipv6 api; /* quagga's communication system */
303 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
304 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
305 struct in6_addr nexthop; /* next router to go */
306 struct in6_addr *nexthop_pointer = &nexthop;
307
Matthieu Boutier53b21952012-01-31 17:09:55 +0100308 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100309 /* convert given addresses */
310 uchar_to_in6addr(&babel_prefix_addr, pref);
311 uchar_to_in6addr(&nexthop, gate);
312
313 /* make prefix structure */
314 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
315 quagga_prefix.family = AF_INET6;
316 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
317 quagga_prefix.prefixlen = plen;
318 apply_mask_ipv6(&quagga_prefix);
319
320 api.type = ZEBRA_ROUTE_BABEL;
321 api.flags = 0;
322 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400323 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100324 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
Juliusz Chroboczekd70ab9d2012-02-09 17:23:09 +0100325 if(metric >= KERNEL_INFINITY) {
326 api.flags = ZEBRA_FLAG_BLACKHOLE;
327 api.nexthop_num = 0;
328 api.ifindex_num = 0;
329 } else {
330 api.nexthop_num = 1;
331 api.nexthop = &nexthop_pointer;
332 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
333 api.ifindex_num = 1;
334 api.ifindex = &tmp_ifindex;
335 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
336 api.metric = metric;
337 }
Paul Jakma57345092011-12-25 17:52:09 +0100338
339 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
340 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
341 &quagga_prefix, &api);
342}
343
344int
Paul Jakma57345092011-12-25 17:52:09 +0100345if_eui64(char *ifname, int ifindex, unsigned char *eui)
346{
347 struct interface *ifp = if_lookup_by_index(ifindex);
348 if (ifp == NULL) {
349 return -1;
350 }
351#ifdef HAVE_STRUCT_SOCKADDR_DL
352 u_char len = ifp->sdl.sdl_alen;
353 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
354#else
355 u_char len = (u_char) ifp->hw_addr_len;
356 char *tmp = (void*) ifp->hw_addr;
357#endif
358 if (len == 8) {
359 memcpy(eui, tmp, 8);
360 eui[0] ^= 2;
361 } else if (len == 6) {
362 memcpy(eui, tmp, 3);
363 eui[3] = 0xFF;
364 eui[4] = 0xFE;
365 memcpy(eui+5, tmp+3, 3);
Paul Jakma57345092011-12-25 17:52:09 +0100366 } else {
367 return -1;
368 }
369 return 0;
370}