]> git.proxmox.com Git - mirror_frr.git/blob - babeld/kernel.c
lib/zserv: introduce address-family independent ZAPI message types
[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 zapi_nexthop *api_nh; /* next router to go - no ECMP */
148 struct prefix quagga_prefix; /* quagga's prefix */
149 struct in_addr babel_prefix_addr; /* babeld's prefix addr */
150
151 api_nh = &api.nexthops[0];
152
153 /* convert to be understandable by quagga */
154 /* convert given addresses */
155 uchar_to_inaddr(&babel_prefix_addr, pref);
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 api.prefix = quagga_prefix;
172
173 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
174 if(metric >= KERNEL_INFINITY) {
175 api.flags = ZEBRA_FLAG_REJECT;
176 api.nexthop_num = 0;
177 } else {
178 api.nexthop_num = 1;
179 api_nh->ifindex = ifindex;
180 uchar_to_inaddr(&api_nh->gate.ipv4, gate);
181 if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) &&
182 quagga_prefix.prefixlen == 32) {
183 api_nh->type = NEXTHOP_TYPE_IFINDEX;
184 } else {
185 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
186 }
187 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
188 api.metric = metric;
189 }
190
191 debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra",
192 add ? "adding" : "removing" );
193 return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
194 zclient, &api);
195 }
196
197 static int
198 kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
199 const unsigned char *gate, int ifindex, unsigned int metric)
200 {
201 struct zapi_route api; /* quagga's communication system */
202 struct zapi_nexthop *api_nh; /* next router to go - no ECMP */
203 struct prefix quagga_prefix; /* quagga's prefix */
204 struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
205
206 api_nh = &api.nexthops[0];
207
208 /* convert to be understandable by quagga */
209 /* convert given addresses */
210 uchar_to_in6addr(&babel_prefix_addr, pref);
211
212 /* make prefix structure */
213 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
214 quagga_prefix.family = AF_INET6;
215 IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr);
216 quagga_prefix.prefixlen = plen;
217 apply_mask(&quagga_prefix);
218
219 memset(&api, 0, sizeof(api));
220 api.type = ZEBRA_ROUTE_BABEL;
221 api.flags = 0;
222 api.message = 0;
223 api.instance = 0;
224 api.safi = SAFI_UNICAST;
225 api.vrf_id = VRF_DEFAULT;
226 api.prefix = quagga_prefix;
227
228 if(metric >= KERNEL_INFINITY) {
229 api.flags = ZEBRA_FLAG_REJECT;
230 api.nexthop_num = 0;
231 } else {
232 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
233 api.nexthop_num = 1;
234 api_nh->ifindex = ifindex;
235 uchar_to_in6addr(&api_nh->gate.ipv6, gate);
236 /* difference to IPv4: always leave the linklocal as nexthop */
237 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
238 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
239 api.metric = metric;
240 }
241
242 debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra",
243 add ? "adding" : "removing" );
244 return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
245 zclient, &api);
246 }
247
248 int
249 if_eui64(char *ifname, int ifindex, unsigned char *eui)
250 {
251 struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
252 if (ifp == NULL) {
253 return -1;
254 }
255
256 u_char len = (u_char) ifp->hw_addr_len;
257 char *tmp = (void*) ifp->hw_addr;
258
259 if (len == 8) {
260 memcpy(eui, tmp, 8);
261 eui[0] ^= 2;
262 } else if (len == 6) {
263 memcpy(eui, tmp, 3);
264 eui[3] = 0xFF;
265 eui[4] = 0xFE;
266 memcpy(eui+5, tmp+3, 3);
267 } else {
268 return -1;
269 }
270 return 0;
271 }
272
273 /* Like gettimeofday, but returns monotonic time. If POSIX clocks are not
274 available, falls back to gettimeofday but enforces monotonicity. */
275 int
276 gettime(struct timeval *tv)
277 {
278 return monotime(tv);
279 }
280
281 /* If /dev/urandom doesn't exist, this will fail with ENOENT, which the
282 caller will deal with gracefully. */
283
284 int
285 read_random_bytes(void *buf, size_t len)
286 {
287 int fd;
288 int rc;
289
290 fd = open("/dev/urandom", O_RDONLY);
291 if(fd < 0) {
292 rc = -1;
293 } else {
294 rc = read(fd, buf, len);
295 if(rc < 0 || (unsigned) rc < len)
296 rc = -1;
297 close(fd);
298 }
299 return rc;
300 }