]> git.proxmox.com Git - mirror_frr.git/blob - babeld/kernel.c
Merge pull request #8969 from opensourcerouting/msdp-timers
[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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <sys/time.h>
29 #include <sys/param.h>
30 #include <time.h>
31
32 #include "babeld.h"
33
34
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <netdb.h>
39 #include <arpa/inet.h>
40
41 #include <zebra.h>
42 #include "prefix.h"
43 #include "zclient.h"
44 #include "kernel.h"
45 #include "privs.h"
46 #include "command.h"
47 #include "vty.h"
48 #include "memory.h"
49 #include "thread.h"
50 #include "nexthop.h"
51
52 #include "util.h"
53 #include "babel_interface.h"
54 #include "babel_zebra.h"
55
56
57 static int
58 zebra_route(int add, int familt, const unsigned char *pref, unsigned short plen,
59 const unsigned char *gate, int ifindex, 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(enum babel_kernel_routes operation, const unsigned char *pref,
81 unsigned short plen, const unsigned char *gate, int ifindex,
82 unsigned int metric, const unsigned char *newgate, int newifindex,
83 unsigned int newmetric)
84 {
85 int rc;
86 int family;
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 family = AF_INET;
95 } else {
96 if(v4mapped(gate)) {
97 errno = EINVAL;
98 return -1;
99 }
100 family = AF_INET6;
101 }
102
103 switch (operation) {
104 case ROUTE_ADD:
105 return zebra_route(1, family, pref, plen, gate, ifindex, metric);
106 case ROUTE_FLUSH:
107 return zebra_route(0, family, pref, plen, gate, ifindex, metric);
108 case ROUTE_MODIFY:
109 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
110 newifindex == ifindex)
111 return 0;
112 debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
113 rc = zebra_route(0, family, pref, plen, gate, ifindex, metric);
114 if (rc < 0)
115 return -1;
116
117 rc = zebra_route(1, family, pref, plen, newgate, newifindex,
118 newmetric);
119 return rc;
120 }
121
122 return 0;
123 }
124
125 static int
126 zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
127 const unsigned char *gate, int ifindex, unsigned int metric)
128 {
129 struct zapi_route api; /* quagga's communication system */
130 struct prefix quagga_prefix; /* quagga's prefix */
131 union g_addr babel_prefix_addr; /* babeld's prefix addr */
132 struct zapi_nexthop *api_nh; /* next router to go - no ECMP */
133
134 api_nh = &api.nexthops[0];
135
136 /* convert to be understandable by quagga */
137 /* convert given addresses */
138 switch (family) {
139 case AF_INET:
140 uchar_to_inaddr(&babel_prefix_addr.ipv4, pref);
141 break;
142 case AF_INET6:
143 uchar_to_in6addr(&babel_prefix_addr.ipv6, pref);
144 break;
145 }
146
147 /* make prefix structure */
148 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
149 quagga_prefix.family = family;
150 switch (family) {
151 case AF_INET:
152 IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr.ipv4);
153 /* our plen is for v4mapped's addr */
154 quagga_prefix.prefixlen = plen - 96;
155 break;
156 case AF_INET6:
157 IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr.ipv6);
158 quagga_prefix.prefixlen = plen;
159 break;
160 }
161 apply_mask(&quagga_prefix);
162
163 memset(&api, 0, sizeof(api));
164 api.type = ZEBRA_ROUTE_BABEL;
165 api.safi = SAFI_UNICAST;
166 api.vrf_id = VRF_DEFAULT;
167 api.prefix = quagga_prefix;
168
169 if(metric >= KERNEL_INFINITY) {
170 zapi_route_set_blackhole(&api, BLACKHOLE_REJECT);
171 } else {
172 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
173 api.nexthop_num = 1;
174 api_nh->ifindex = ifindex;
175 api_nh->vrf_id = VRF_DEFAULT;
176 switch (family) {
177 case AF_INET:
178 uchar_to_inaddr(&api_nh->gate.ipv4, gate);
179 if (IPV4_ADDR_SAME(&api_nh->gate.ipv4, &quagga_prefix.u.prefix4)
180 && quagga_prefix.prefixlen == IPV4_MAX_BITLEN) {
181 api_nh->type = NEXTHOP_TYPE_IFINDEX;
182 } else {
183 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
184 }
185 break;
186 case AF_INET6:
187 uchar_to_in6addr(&api_nh->gate.ipv6, gate);
188 /* difference to IPv4: always leave the linklocal as nexthop */
189 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
190 break;
191 }
192 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
193 api.metric = metric;
194 }
195
196 debugf(BABEL_DEBUG_ROUTE, "%s route (%s) to zebra",
197 add ? "adding" : "removing",
198 (family == AF_INET) ? "ipv4" : "ipv6");
199 return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
200 zclient, &api);
201 }
202
203 int
204 if_eui64(int ifindex, unsigned char *eui)
205 {
206 struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
207 if (ifp == NULL) {
208 return -1;
209 }
210
211 uint8_t len = (uint8_t)ifp->hw_addr_len;
212 char *tmp = (void*) ifp->hw_addr;
213
214 if (len == 8) {
215 memcpy(eui, tmp, 8);
216 eui[0] ^= 2;
217 } else if (len == 6) {
218 memcpy(eui, tmp, 3);
219 eui[3] = 0xFF;
220 eui[4] = 0xFE;
221 memcpy(eui+5, tmp+3, 3);
222 } else {
223 return -1;
224 }
225 return 0;
226 }
227
228 /* Like gettimeofday, but returns monotonic time. If POSIX clocks are not
229 available, falls back to gettimeofday but enforces monotonicity. */
230 int
231 gettime(struct timeval *tv)
232 {
233 return monotime(tv);
234 }
235
236 /* If /dev/urandom doesn't exist, this will fail with ENOENT, which the
237 caller will deal with gracefully. */
238
239 int
240 read_random_bytes(void *buf, size_t len)
241 {
242 int fd;
243 int rc;
244
245 fd = open("/dev/urandom", O_RDONLY);
246 if(fd < 0) {
247 rc = -1;
248 } else {
249 rc = read(fd, buf, len);
250 if(rc < 0 || (unsigned) rc < len)
251 rc = -1;
252 close(fd);
253 }
254 return rc;
255 }