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