]> git.proxmox.com Git - mirror_frr.git/blob - babeld/kernel.c
fa06f80a5b07d0dc8705b1c5742b652694eb4ac9
[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 #include "nexthop.h"
47
48 #include "util.h"
49 #include "babel_interface.h"
50 #include "babel_zebra.h"
51
52
53 static int
54 kernel_route_v4(int add, const unsigned char *pref, unsigned short plen,
55 const unsigned char *gate, int ifindex,
56 unsigned int metric);
57 static int
58 kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
59 const unsigned char *gate, int ifindex,
60 unsigned int metric);
61
62 int
63 kernel_interface_operational(struct interface *interface)
64 {
65 return if_is_operative(interface);
66 }
67
68 int
69 kernel_interface_mtu(struct interface *interface)
70 {
71 return MIN(interface->mtu, interface->mtu6);
72 }
73
74 int
75 kernel_interface_wireless(struct interface *interface)
76 {
77 return 0;
78 }
79
80 int
81 kernel_route(int operation, const unsigned char *pref, unsigned short plen,
82 const unsigned char *gate, int ifindex, unsigned int metric,
83 const unsigned char *newgate, int newifindex,
84 unsigned int newmetric)
85 {
86 int rc;
87 int ipv4;
88
89 /* Check that the protocol family is consistent. */
90 if(plen >= 96 && v4mapped(pref)) {
91 if(!v4mapped(gate)) {
92 errno = EINVAL;
93 return -1;
94 }
95 ipv4 = 1;
96 } else {
97 if(v4mapped(gate)) {
98 errno = EINVAL;
99 return -1;
100 }
101 ipv4 = 0;
102 }
103
104 switch (operation) {
105 case ROUTE_ADD:
106 return ipv4 ?
107 kernel_route_v4(1, pref, plen, gate, ifindex, metric):
108 kernel_route_v6(1, pref, plen, gate, ifindex, metric);
109 break;
110 case ROUTE_FLUSH:
111 return ipv4 ?
112 kernel_route_v4(0, pref, plen, gate, ifindex, metric):
113 kernel_route_v6(0, pref, plen, gate, ifindex, metric);
114 break;
115 case ROUTE_MODIFY:
116 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
117 newifindex == ifindex)
118 return 0;
119 debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
120 rc = ipv4 ?
121 kernel_route_v4(0, pref, plen, gate, ifindex, metric):
122 kernel_route_v6(0, pref, plen, gate, ifindex, metric);
123
124 if (rc < 0)
125 return -1;
126
127 rc = ipv4 ?
128 kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric):
129 kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric);
130
131 return rc;
132 break;
133 default:
134 zlog_err("this should never appens (false value - kernel_route)");
135 assert(0);
136 exit(1);
137 break;
138 }
139 }
140
141 static int
142 kernel_route_v4(int add,
143 const unsigned char *pref, unsigned short plen,
144 const unsigned char *gate, int ifindex, unsigned int metric)
145 {
146 struct zapi_route api; /* quagga's communication system */
147 struct prefix quagga_prefix; /* quagga's prefix */
148 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
149 struct nexthop nexthop; /* next router to go */
150 struct nexthop *nexthop_pointer = &nexthop; /* it's an array! */
151
152 /* convert to be understandable by quagga */
153 /* convert given addresses */
154 uchar_to_inaddr(&babel_prefix_addr, pref);
155 uchar_to_inaddr(&nexthop.gate.ipv4, gate);
156
157 /* make prefix structure */
158 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
159 quagga_prefix.family = AF_INET;
160 IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr);
161 quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
162 apply_mask(&quagga_prefix);
163
164 memset(&api, 0, sizeof(api));
165 api.type = ZEBRA_ROUTE_BABEL;
166 api.flags = 0;
167 api.message = 0;
168 api.instance = 0;
169 api.safi = SAFI_UNICAST;
170 api.vrf_id = VRF_DEFAULT;
171
172 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
173 if(metric >= KERNEL_INFINITY) {
174 api.flags = ZEBRA_FLAG_REJECT;
175 api.nexthop_num = 0;
176 } else {
177 api.nexthop_num = 1;
178 api.nexthop = &nexthop_pointer;
179 nexthop.ifindex = ifindex;
180 nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
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_route (add ? ZEBRA_IPV4_ROUTE_ADD :
188 ZEBRA_IPV4_ROUTE_DELETE,
189 zclient, &quagga_prefix, NULL, &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 struct zapi_route api; /* quagga's communication system */
197 struct prefix quagga_prefix; /* quagga's prefix */
198 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
199 struct nexthop nexthop; /* next router to go */
200 struct nexthop *nexthop_pointer = &nexthop;
201
202 /* convert to be understandable by quagga */
203 /* convert given addresses */
204 uchar_to_in6addr(&babel_prefix_addr, pref);
205 uchar_to_in6addr(&nexthop.gate.ipv6, gate);
206
207 /* make prefix structure */
208 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
209 quagga_prefix.family = AF_INET6;
210 IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr);
211 quagga_prefix.prefixlen = plen;
212 apply_mask(&quagga_prefix);
213
214 memset(&api, 0, sizeof(api));
215 api.type = ZEBRA_ROUTE_BABEL;
216 api.flags = 0;
217 api.message = 0;
218 api.instance = 0;
219 api.safi = SAFI_UNICAST;
220 api.vrf_id = VRF_DEFAULT;
221
222 if(metric >= KERNEL_INFINITY) {
223 api.flags = ZEBRA_FLAG_REJECT;
224 api.nexthop_num = 0;
225 } else {
226 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
227 api.nexthop_num = 1;
228 api.nexthop = &nexthop_pointer;
229 nexthop.ifindex = ifindex;
230 nexthop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
231 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
232 api.metric = metric;
233 }
234
235 debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra",
236 add ? "adding" : "removing" );
237 return zapi_route (add ? ZEBRA_IPV6_ROUTE_ADD :
238 ZEBRA_IPV6_ROUTE_DELETE,
239 zclient, &quagga_prefix, NULL, &api);
240 }
241
242 int
243 if_eui64(char *ifname, int ifindex, unsigned char *eui)
244 {
245 struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
246 if (ifp == NULL) {
247 return -1;
248 }
249
250 u_char len = (u_char) ifp->hw_addr_len;
251 char *tmp = (void*) ifp->hw_addr;
252
253 if (len == 8) {
254 memcpy(eui, tmp, 8);
255 eui[0] ^= 2;
256 } else if (len == 6) {
257 memcpy(eui, tmp, 3);
258 eui[3] = 0xFF;
259 eui[4] = 0xFE;
260 memcpy(eui+5, tmp+3, 3);
261 } else {
262 return -1;
263 }
264 return 0;
265 }
266
267 /* Like gettimeofday, but returns monotonic time. If POSIX clocks are not
268 available, falls back to gettimeofday but enforces monotonicity. */
269 int
270 gettime(struct timeval *tv)
271 {
272 return monotime(tv);
273 }
274
275 /* If /dev/urandom doesn't exist, this will fail with ENOENT, which the
276 caller will deal with gracefully. */
277
278 int
279 read_random_bytes(void *buf, size_t len)
280 {
281 int fd;
282 int rc;
283
284 fd = open("/dev/urandom", O_RDONLY);
285 if(fd < 0) {
286 rc = -1;
287 } else {
288 rc = read(fd, buf, len);
289 if(rc < 0 || (unsigned) rc < len)
290 rc = -1;
291 close(fd);
292 }
293 return rc;
294 }