blob: efbb700050dea77f2265a272c4c31a3a600903fb [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 *
18
19Copyright 2007, 2008 by Grégoire Henry, Julien Cristau and Juliusz Chroboczek
Juliusz Chroboczek27f68972012-03-12 13:52:42 +010020Copyright 2011, 2012 by Matthieu Boutier and Juliusz Chroboczek
Paul Jakma57345092011-12-25 17:52:09 +010021
22Permission is hereby granted, free of charge, to any person obtaining a copy
23of this software and associated documentation files (the "Software"), to deal
24in the Software without restriction, including without limitation the rights
25to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26copies of the Software, and to permit persons to whom the Software is
27furnished to do so, subject to the following conditions:
28
29The above copyright notice and this permission notice shall be included in
30all copies or substantial portions of the Software.
31
32THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38THE SOFTWARE.
39*/
40
41#include <sys/time.h>
42#include <sys/param.h>
43#include <time.h>
44
45#include "babeld.h"
46
Juliusz Chroboczek27f68972012-03-12 13:52:42 +010047
48#include <sys/types.h>
49#include <sys/socket.h>
50#include <netinet/in.h>
51#include <netdb.h>
52#include <arpa/inet.h>
53
54#include <zebra.h>
55#include "prefix.h"
56#include "zclient.h"
57#include "kernel.h"
58#include "privs.h"
59#include "command.h"
60#include "vty.h"
61#include "memory.h"
62#include "thread.h"
63
64#include "util.h"
65#include "babel_interface.h"
66#include "babel_zebra.h"
67
68
69static int
70kernel_route_v4(int add, const unsigned char *pref, unsigned short plen,
71 const unsigned char *gate, int ifindex,
72 unsigned int metric);
73static int
74kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
75 const unsigned char *gate, int ifindex,
76 unsigned int metric);
77
78int
79kernel_interface_operational(struct interface *interface)
80{
81 return if_is_operative(interface);
82}
83
84int
85kernel_interface_mtu(struct interface *interface)
86{
87 return MIN(interface->mtu, interface->mtu6);
88}
89
90int
91kernel_interface_wireless(struct interface *interface)
92{
93 return 0;
94}
95
96int
97kernel_route(int operation, const unsigned char *pref, unsigned short plen,
98 const unsigned char *gate, int ifindex, unsigned int metric,
99 const unsigned char *newgate, int newifindex,
100 unsigned int newmetric)
101{
102 int rc;
103 int ipv4;
104
105 /* Check that the protocol family is consistent. */
106 if(plen >= 96 && v4mapped(pref)) {
107 if(!v4mapped(gate)) {
108 errno = EINVAL;
109 return -1;
110 }
111 ipv4 = 1;
112 } else {
113 if(v4mapped(gate)) {
114 errno = EINVAL;
115 return -1;
116 }
117 ipv4 = 0;
118 }
119
120 switch (operation) {
121 case ROUTE_ADD:
122 return ipv4 ?
123 kernel_route_v4(1, pref, plen, gate, ifindex, metric):
124 kernel_route_v6(1, pref, plen, gate, ifindex, metric);
125 break;
126 case ROUTE_FLUSH:
127 return ipv4 ?
128 kernel_route_v4(0, pref, plen, gate, ifindex, metric):
129 kernel_route_v6(0, pref, plen, gate, ifindex, metric);
130 break;
131 case ROUTE_MODIFY:
132 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
133 newifindex == ifindex)
134 return 0;
135 debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
136 rc = ipv4 ?
137 kernel_route_v4(0, pref, plen, gate, ifindex, metric):
138 kernel_route_v6(0, pref, plen, gate, ifindex, metric);
139
140 if (rc < 0)
141 return -1;
142
143 rc = ipv4 ?
144 kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric):
145 kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric);
146
147 return rc;
148 break;
149 default:
150 zlog_err("this should never appens (false value - kernel_route)");
151 assert(0);
152 exit(1);
153 break;
154 }
155}
156
157static int
158kernel_route_v4(int add,
159 const unsigned char *pref, unsigned short plen,
160 const unsigned char *gate, int ifindex, unsigned int metric)
161{
162 struct zapi_ipv4 api; /* quagga's communication system */
163 struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
164 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
165 struct in_addr nexthop; /* next router to go */
166 struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
167
168 /* convert to be understandable by quagga */
169 /* convert given addresses */
170 uchar_to_inaddr(&babel_prefix_addr, pref);
171 uchar_to_inaddr(&nexthop, gate);
172
173 /* make prefix structure */
174 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
175 quagga_prefix.family = AF_INET;
176 IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
177 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
178 apply_mask_ipv4(&quagga_prefix);
179
180 api.type = ZEBRA_ROUTE_BABEL;
181 api.flags = 0;
182 api.message = 0;
183 api.safi = SAFI_UNICAST;
184
185 /* Unlike the native Linux and BSD interfaces, Quagga doesn't like
186 there to be both and IPv4 nexthop and an ifindex. Omit the
187 ifindex, and assume that the connected prefixes be set up
188 correctly. */
189
190 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
191 api.ifindex_num = 0;
192 if(metric >= KERNEL_INFINITY) {
193 api.flags = ZEBRA_FLAG_BLACKHOLE;
194 api.nexthop_num = 0;
195 } else {
196 api.nexthop_num = 1;
197 api.nexthop = &nexthop_pointer;
198 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
199 api.metric = metric;
200 }
201
202 debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra",
203 add ? "adding" : "removing" );
204 return zapi_ipv4_route (add ? ZEBRA_IPV4_ROUTE_ADD :
205 ZEBRA_IPV4_ROUTE_DELETE,
206 zclient, &quagga_prefix, &api);
207}
208
209static int
210kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
211 const unsigned char *gate, int ifindex, unsigned int metric)
212{
213 unsigned int tmp_ifindex = ifindex; /* (for typing) */
214 struct zapi_ipv6 api; /* quagga's communication system */
215 struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
216 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
217 struct in6_addr nexthop; /* next router to go */
218 struct in6_addr *nexthop_pointer = &nexthop;
219
220 /* convert to be understandable by quagga */
221 /* convert given addresses */
222 uchar_to_in6addr(&babel_prefix_addr, pref);
223 uchar_to_in6addr(&nexthop, gate);
224
225 /* make prefix structure */
226 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
227 quagga_prefix.family = AF_INET6;
228 IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
229 quagga_prefix.prefixlen = plen;
230 apply_mask_ipv6(&quagga_prefix);
231
232 api.type = ZEBRA_ROUTE_BABEL;
233 api.flags = 0;
234 api.message = 0;
235 api.safi = SAFI_UNICAST;
236 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
237 if(metric >= KERNEL_INFINITY) {
238 api.flags = ZEBRA_FLAG_BLACKHOLE;
239 api.nexthop_num = 0;
240 api.ifindex_num = 0;
241 } else {
242 api.nexthop_num = 1;
243 api.nexthop = &nexthop_pointer;
244 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
245 api.ifindex_num = 1;
246 api.ifindex = &tmp_ifindex;
247 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
248 api.metric = metric;
249 }
250
251 debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra",
252 add ? "adding" : "removing" );
253 return zapi_ipv6_route (add ? ZEBRA_IPV6_ROUTE_ADD :
254 ZEBRA_IPV6_ROUTE_DELETE,
255 zclient, &quagga_prefix, &api);
256}
257
258int
259if_eui64(char *ifname, int ifindex, unsigned char *eui)
260{
261 struct interface *ifp = if_lookup_by_index(ifindex);
262 if (ifp == NULL) {
263 return -1;
264 }
265#ifdef HAVE_STRUCT_SOCKADDR_DL
266 u_char len = ifp->sdl.sdl_alen;
267 char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
268#else
269 u_char len = (u_char) ifp->hw_addr_len;
270 char *tmp = (void*) ifp->hw_addr;
271#endif
272 if (len == 8) {
273 memcpy(eui, tmp, 8);
274 eui[0] ^= 2;
275 } else if (len == 6) {
276 memcpy(eui, tmp, 3);
277 eui[3] = 0xFF;
278 eui[4] = 0xFE;
279 memcpy(eui+5, tmp+3, 3);
280 } else {
281 return -1;
282 }
283 return 0;
284}
Paul Jakma57345092011-12-25 17:52:09 +0100285
286/* Like gettimeofday, but returns monotonic time. If POSIX clocks are not
287 available, falls back to gettimeofday but enforces monotonicity. */
288int
289gettime(struct timeval *tv)
290{
Juliusz Chroboczek82509bf2012-02-09 13:35:27 +0100291 return quagga_gettime(QUAGGA_CLK_MONOTONIC, tv);
Paul Jakma57345092011-12-25 17:52:09 +0100292}
293
294/* If /dev/urandom doesn't exist, this will fail with ENOENT, which the
295 caller will deal with gracefully. */
296
297int
298read_random_bytes(void *buf, size_t len)
299{
300 int fd;
301 int rc;
302
303 fd = open("/dev/urandom", O_RDONLY);
304 if(fd < 0) {
305 rc = -1;
306 } else {
307 rc = read(fd, buf, len);
308 if(rc < 0 || (unsigned) rc < len)
309 rc = -1;
310 close(fd);
311 }
312 return rc;
313}
314