blob: f23403ecae5dde1ce49dd98cbf4a2d9af2a360e5 [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{
160 unsigned int tmp_ifindex = ifindex; /* (for typing) */
161 struct zapi_ipv4 api; /* quagga's communication system */
162 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
163 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
164 struct in_addr nexthop; /* next router to go */
165 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
166
Matthieu Boutier53b21952012-01-31 17:09:55 +0100167 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100168 /* convert given addresses */
169 uchar_to_inaddr(&babel_prefix_addr, pref);
170 uchar_to_inaddr(&nexthop, gate);
171
172 /* make prefix structure */
173 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
174 quagga_prefix.family = AF_INET;
175 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
176 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
177 apply_mask_ipv4(&quagga_prefix);
178
179 api.type = ZEBRA_ROUTE_BABEL;
180 api.flags = 0;
181 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400182 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100183 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
184 api.nexthop_num = 1;
185 api.nexthop = &nexthop_pointer;
186 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
187 api.ifindex_num = 1;
188 api.ifindex = &tmp_ifindex;
189 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
190 api.metric = metric;
191
192 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv4) to zebra");
193 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
194 &quagga_prefix, &api);
195}
196
197static int
198kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100199 const unsigned char *gate, int ifindex, unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100200{
201 unsigned int tmp_ifindex = ifindex; /* (for typing) */
202 struct zapi_ipv6 api; /* quagga's communication system */
203 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
204 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
205 struct in6_addr nexthop; /* next router to go */
206 struct in6_addr *nexthop_pointer = &nexthop;
207
Matthieu Boutier53b21952012-01-31 17:09:55 +0100208 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100209 /* convert given addresses */
210 uchar_to_in6addr(&babel_prefix_addr, pref);
211 uchar_to_in6addr(&nexthop, gate);
212
213 /* make prefix structure */
214 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
215 quagga_prefix.family = AF_INET6;
216 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
217 quagga_prefix.prefixlen = plen;
218 apply_mask_ipv6(&quagga_prefix);
219
220 api.type = ZEBRA_ROUTE_BABEL;
221 api.flags = 0;
222 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400223 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100224 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
225 api.nexthop_num = 1;
226 api.nexthop = &nexthop_pointer;
227 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
228 api.ifindex_num = 1;
229 api.ifindex = &tmp_ifindex;
230 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
231 api.metric = metric;
232
233 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
234 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
235 &quagga_prefix, &api);
236}
237
238static int
239kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
240 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100241 unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100242{
243 unsigned int tmp_ifindex = ifindex; /* (for typing) */
244 struct zapi_ipv4 api; /* quagga's communication system */
245 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
246 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
247 struct in_addr nexthop; /* next router to go */
248 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
249
Matthieu Boutier53b21952012-01-31 17:09:55 +0100250 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100251 /* convert given addresses */
252 uchar_to_inaddr(&babel_prefix_addr, pref);
253 uchar_to_inaddr(&nexthop, gate);
254
255 /* make prefix structure */
256 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
257 quagga_prefix.family = AF_INET;
258 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
259 quagga_prefix.prefixlen = plen - 96;
260 apply_mask_ipv4(&quagga_prefix);
261
262 api.type = ZEBRA_ROUTE_BABEL;
263 api.flags = 0;
264 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400265 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100266 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
267 api.nexthop_num = 1;
268 api.nexthop = &nexthop_pointer;
269 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
270 api.ifindex_num = 1;
271 api.ifindex = &tmp_ifindex;
272 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
273 api.metric = metric;
274
275 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
276 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
277 &quagga_prefix, &api);
278}
279
280static int
281kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
282 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100283 unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100284{
285 unsigned int tmp_ifindex = ifindex; /* (for typing) */
286 struct zapi_ipv6 api; /* quagga's communication system */
287 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
288 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
289 struct in6_addr nexthop; /* next router to go */
290 struct in6_addr *nexthop_pointer = &nexthop;
291
Matthieu Boutier53b21952012-01-31 17:09:55 +0100292 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100293 /* convert given addresses */
294 uchar_to_in6addr(&babel_prefix_addr, pref);
295 uchar_to_in6addr(&nexthop, gate);
296
297 /* make prefix structure */
298 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
299 quagga_prefix.family = AF_INET6;
300 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
301 quagga_prefix.prefixlen = plen;
302 apply_mask_ipv6(&quagga_prefix);
303
304 api.type = ZEBRA_ROUTE_BABEL;
305 api.flags = 0;
306 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400307 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100308 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
309 api.nexthop_num = 1;
310 api.nexthop = &nexthop_pointer;
311 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
312 api.ifindex_num = 1;
313 api.ifindex = &tmp_ifindex;
314
315 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
316 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
317 &quagga_prefix, &api);
318}
319
320int
Paul Jakma57345092011-12-25 17:52:09 +0100321if_eui64(char *ifname, int ifindex, unsigned char *eui)
322{
323 struct interface *ifp = if_lookup_by_index(ifindex);
324 if (ifp == NULL) {
325 return -1;
326 }
327#ifdef HAVE_STRUCT_SOCKADDR_DL
328 u_char len = ifp->sdl.sdl_alen;
329 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
330#else
331 u_char len = (u_char) ifp->hw_addr_len;
332 char *tmp = (void*) ifp->hw_addr;
333#endif
334 if (len == 8) {
335 memcpy(eui, tmp, 8);
336 eui[0] ^= 2;
337 } else if (len == 6) {
338 memcpy(eui, tmp, 3);
339 eui[3] = 0xFF;
340 eui[4] = 0xFE;
341 memcpy(eui+5, tmp+3, 3);
Paul Jakma57345092011-12-25 17:52:09 +0100342 } else {
343 return -1;
344 }
345 return 0;
346}