]> git.proxmox.com Git - mirror_frr.git/blame - babeld/kernel.c
Merge pull request #11838 from Pdoijode/v6-gua-nh-bgp-update
[mirror_frr.git] / babeld / kernel.c
CommitLineData
ca10883e
DS
1/*
2Copyright 2007, 2008 by Grégoire Henry, Julien Cristau and Juliusz Chroboczek
3Copyright 2011, 2012 by Matthieu Boutier and Juliusz Chroboczek
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22*/
23
b45ac5f5
DL
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
ca10883e
DS
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"
98c02f4c 50#include "nexthop.h"
ca10883e
DS
51
52#include "util.h"
53#include "babel_interface.h"
54#include "babel_zebra.h"
55
56
57static int
c8f9e916
RW
58zebra_route(int add, int familt, const unsigned char *pref, unsigned short plen,
59 const unsigned char *gate, int ifindex, unsigned int metric);
ca10883e
DS
60
61int
62kernel_interface_operational(struct interface *interface)
63{
64 return if_is_operative(interface);
65}
66
67int
68kernel_interface_mtu(struct interface *interface)
69{
70 return MIN(interface->mtu, interface->mtu6);
71}
72
73int
74kernel_interface_wireless(struct interface *interface)
75{
76 return 0;
77}
78
79int
e8c8f2e0
DS
80kernel_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,
ca10883e
DS
83 unsigned int newmetric)
84{
85 int rc;
c8f9e916 86 int family;
ca10883e
DS
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 }
c8f9e916 94 family = AF_INET;
ca10883e
DS
95 } else {
96 if(v4mapped(gate)) {
97 errno = EINVAL;
98 return -1;
99 }
c8f9e916 100 family = AF_INET6;
ca10883e
DS
101 }
102
103 switch (operation) {
104 case ROUTE_ADD:
c8f9e916 105 return zebra_route(1, family, pref, plen, gate, ifindex, metric);
ca10883e 106 case ROUTE_FLUSH:
c8f9e916 107 return zebra_route(0, family, pref, plen, gate, ifindex, metric);
ca10883e
DS
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.");
c8f9e916 113 rc = zebra_route(0, family, pref, plen, gate, ifindex, metric);
ca10883e
DS
114 if (rc < 0)
115 return -1;
116
c8f9e916
RW
117 rc = zebra_route(1, family, pref, plen, newgate, newifindex,
118 newmetric);
ca10883e 119 return rc;
ca10883e 120 }
e8c8f2e0
DS
121
122 return 0;
ca10883e
DS
123}
124
125static int
c8f9e916
RW
126zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
127 const unsigned char *gate, int ifindex, unsigned int metric)
ca10883e 128{
98c02f4c
DS
129 struct zapi_route api; /* quagga's communication system */
130 struct prefix quagga_prefix; /* quagga's prefix */
c8f9e916
RW
131 union g_addr babel_prefix_addr; /* babeld's prefix addr */
132 struct zapi_nexthop *api_nh; /* next router to go - no ECMP */
bb1b9c47
RW
133
134 api_nh = &api.nexthops[0];
ca10883e
DS
135
136 /* convert to be understandable by quagga */
137 /* convert given addresses */
c8f9e916
RW
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;
ca10883e
DS
145 }
146
ca10883e
DS
147 /* make prefix structure */
148 memset (&quagga_prefix, 0, sizeof(quagga_prefix));
c8f9e916
RW
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 }
98c02f4c 161 apply_mask(&quagga_prefix);
ca10883e 162
e4d9c771 163 memset(&api, 0, sizeof(api));
ca10883e 164 api.type = ZEBRA_ROUTE_BABEL;
ca10883e 165 api.safi = SAFI_UNICAST;
e4d9c771 166 api.vrf_id = VRF_DEFAULT;
bb1b9c47 167 api.prefix = quagga_prefix;
e4d9c771 168
ca10883e 169 if(metric >= KERNEL_INFINITY) {
09a484dd 170 zapi_route_set_blackhole(&api, BLACKHOLE_REJECT);
ca10883e
DS
171 } else {
172 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
173 api.nexthop_num = 1;
bb1b9c47 174 api_nh->ifindex = ifindex;
4a7371e9
DS
175 api_nh->vrf_id = VRF_DEFAULT;
176 switch (family) {
c8f9e916
RW
177 case AF_INET:
178 uchar_to_inaddr(&api_nh->gate.ipv4, gate);
12256b84
DA
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;
c8f9e916
RW
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 }
ca10883e
DS
192 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
193 api.metric = metric;
194 }
195
c8f9e916
RW
196 debugf(BABEL_DEBUG_ROUTE, "%s route (%s) to zebra",
197 add ? "adding" : "removing",
198 (family == AF_INET) ? "ipv4" : "ipv6");
0e51b4a3
RW
199 return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
200 zclient, &api);
ca10883e
DS
201}
202
203int
edb1d4a0 204if_eui64(int ifindex, unsigned char *eui)
ca10883e
DS
205{
206 struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
207 if (ifp == NULL) {
208 return -1;
209 }
7217de2d 210
d7c0a89a 211 uint8_t len = (uint8_t)ifp->hw_addr_len;
ca10883e 212 char *tmp = (void*) ifp->hw_addr;
7217de2d 213
ca10883e
DS
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. */
c392d9f4 230void
ca10883e
DS
231gettime(struct timeval *tv)
232{
c392d9f4 233 monotime(tv);
ca10883e
DS
234}
235
236/* If /dev/urandom doesn't exist, this will fail with ENOENT, which the
237 caller will deal with gracefully. */
238
239int
240read_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}