blob: 1df4217f0fa3de53cd98c41e1317bb7c9ffe5cb4 [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);
189 api.nexthop_num = 1;
190 api.nexthop = &nexthop_pointer;
Juliusz Chroboczekb6475ec2012-02-09 12:29:10 +0100191 api.ifindex_num = 0;
192
Paul Jakma57345092011-12-25 17:52:09 +0100193 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
194 api.metric = metric;
195
196 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv4) to zebra");
197 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
198 &quagga_prefix, &api);
199}
200
201static int
202kernel_route_add_v6(const unsigned char *pref, unsigned short plen,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100203 const unsigned char *gate, int ifindex, unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100204{
205 unsigned int tmp_ifindex = ifindex; /* (for typing) */
206 struct zapi_ipv6 api; /* quagga's communication system */
207 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
208 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
209 struct in6_addr nexthop; /* next router to go */
210 struct in6_addr *nexthop_pointer = &nexthop;
211
Matthieu Boutier53b21952012-01-31 17:09:55 +0100212 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100213 /* convert given addresses */
214 uchar_to_in6addr(&babel_prefix_addr, pref);
215 uchar_to_in6addr(&nexthop, gate);
216
217 /* make prefix structure */
218 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
219 quagga_prefix.family = AF_INET6;
220 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
221 quagga_prefix.prefixlen = plen;
222 apply_mask_ipv6(&quagga_prefix);
223
224 api.type = ZEBRA_ROUTE_BABEL;
225 api.flags = 0;
226 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400227 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100228 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
229 api.nexthop_num = 1;
230 api.nexthop = &nexthop_pointer;
231 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
232 api.ifindex_num = 1;
233 api.ifindex = &tmp_ifindex;
234 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
235 api.metric = metric;
236
237 debugf(BABEL_DEBUG_ROUTE, "adding route (ipv6) to zebra");
238 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
239 &quagga_prefix, &api);
240}
241
242static int
243kernel_route_delete_v4(const unsigned char *pref, unsigned short plen,
244 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100245 unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100246{
Paul Jakma57345092011-12-25 17:52:09 +0100247 struct zapi_ipv4 api; /* quagga's communication system */
248 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
249 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
250 struct in_addr nexthop; /* next router to go */
251 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
252
Matthieu Boutier53b21952012-01-31 17:09:55 +0100253 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100254 /* convert given addresses */
255 uchar_to_inaddr(&babel_prefix_addr, pref);
256 uchar_to_inaddr(&nexthop, gate);
257
258 /* make prefix structure */
259 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
260 quagga_prefix.family = AF_INET;
261 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
262 quagga_prefix.prefixlen = plen - 96;
263 apply_mask_ipv4(&quagga_prefix);
264
265 api.type = ZEBRA_ROUTE_BABEL;
266 api.flags = 0;
267 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400268 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100269 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
270 api.nexthop_num = 1;
271 api.nexthop = &nexthop_pointer;
Juliusz Chroboczekb6475ec2012-02-09 12:29:10 +0100272 api.ifindex_num = 0;
Paul Jakma57345092011-12-25 17:52:09 +0100273 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
274 api.metric = metric;
275
276 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv4) to zebra");
277 return zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
278 &quagga_prefix, &api);
279}
280
281static int
282kernel_route_delete_v6(const unsigned char *pref, unsigned short plen,
283 const unsigned char *gate, int ifindex,
Matthieu Boutier53b21952012-01-31 17:09:55 +0100284 unsigned int metric)
Paul Jakma57345092011-12-25 17:52:09 +0100285{
286 unsigned int tmp_ifindex = ifindex; /* (for typing) */
287 struct zapi_ipv6 api; /* quagga's communication system */
288 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
289 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
290 struct in6_addr nexthop; /* next router to go */
291 struct in6_addr *nexthop_pointer = &nexthop;
292
Matthieu Boutier53b21952012-01-31 17:09:55 +0100293 /* convert to be understandable by quagga */
Paul Jakma57345092011-12-25 17:52:09 +0100294 /* convert given addresses */
295 uchar_to_in6addr(&babel_prefix_addr, pref);
296 uchar_to_in6addr(&nexthop, gate);
297
298 /* make prefix structure */
299 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
300 quagga_prefix.family = AF_INET6;
301 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
302 quagga_prefix.prefixlen = plen;
303 apply_mask_ipv6(&quagga_prefix);
304
305 api.type = ZEBRA_ROUTE_BABEL;
306 api.flags = 0;
307 api.message = 0;
Denis Ovsienkoa19a3bf2012-01-21 23:16:00 +0400308 api.safi = SAFI_UNICAST;
Paul Jakma57345092011-12-25 17:52:09 +0100309 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
310 api.nexthop_num = 1;
311 api.nexthop = &nexthop_pointer;
312 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
313 api.ifindex_num = 1;
314 api.ifindex = &tmp_ifindex;
315
316 debugf(BABEL_DEBUG_ROUTE, "removing route (ipv6) to zebra");
317 return zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
318 &quagga_prefix, &api);
319}
320
321int
Paul Jakma57345092011-12-25 17:52:09 +0100322if_eui64(char *ifname, int ifindex, unsigned char *eui)
323{
324 struct interface *ifp = if_lookup_by_index(ifindex);
325 if (ifp == NULL) {
326 return -1;
327 }
328#ifdef HAVE_STRUCT_SOCKADDR_DL
329 u_char len = ifp->sdl.sdl_alen;
330 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
331#else
332 u_char len = (u_char) ifp->hw_addr_len;
333 char *tmp = (void*) ifp->hw_addr;
334#endif
335 if (len == 8) {
336 memcpy(eui, tmp, 8);
337 eui[0] ^= 2;
338 } else if (len == 6) {
339 memcpy(eui, tmp, 3);
340 eui[3] = 0xFF;
341 eui[4] = 0xFE;
342 memcpy(eui+5, tmp+3, 3);
Paul Jakma57345092011-12-25 17:52:09 +0100343 } else {
344 return -1;
345 }
346 return 0;
347}