1 | /* |
2 | * dhcpcd - DHCP client daemon |
3 | * Copyright (c) 2006-2019 Roy Marples <roy@marples.name> |
4 | * All rights reserved |
5 | |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
14 | * |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 | * SUCH DAMAGE. |
26 | */ |
27 | |
28 | #ifndef IPV6_H |
29 | #define IPV6_H |
30 | |
31 | #include <sys/uio.h> |
32 | #include <netinet/in.h> |
33 | |
34 | #include "config.h" |
35 | #include "if.h" |
36 | |
37 | #ifndef __linux__ |
38 | # if !defined(__QNX__) && !defined(__sun) |
39 | # include <sys/endian.h> |
40 | # endif |
41 | # include <net/if.h> |
42 | # ifndef __sun |
43 | # include <netinet6/in6_var.h> |
44 | # endif |
45 | #endif |
46 | |
47 | #define EUI64_GBIT 0x01 |
48 | #define EUI64_UBIT 0x02 |
49 | #define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0) |
50 | #define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT) |
51 | |
52 | #ifndef ND6_INFINITE_LIFETIME |
53 | # define ND6_INFINITE_LIFETIME ((uint32_t)~0) |
54 | #endif |
55 | |
56 | /* RFC4941 constants */ |
57 | #define TEMP_VALID_LIFETIME 604800 /* 1 week */ |
58 | #define TEMP_PREFERRED_LIFETIME 86400 /* 1 day */ |
59 | #define REGEN_ADVANCE 5 /* seconds */ |
60 | #define MAX_DESYNC_FACTOR 600 /* 10 minutes */ |
61 | |
62 | #define TEMP_IDGEN_RETRIES 3 |
63 | #define GEN_TEMPID_RETRY_MAX 5 |
64 | |
65 | /* RFC7217 constants */ |
66 | #define IDGEN_RETRIES 3 |
67 | #define IDGEN_DELAY 1 /* second */ |
68 | |
69 | #ifndef IN6_ARE_MASKED_ADDR_EQUAL |
70 | #define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \ |
71 | (((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \ |
72 | (((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \ |
73 | (((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \ |
74 | (((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 ) |
75 | #endif |
76 | |
77 | #ifndef IN6ADDR_LINKLOCAL_ALLNODES_INIT |
78 | #define IN6ADDR_LINKLOCAL_ALLNODES_INIT \ |
79 | {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ |
80 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} |
81 | #endif |
82 | #ifndef IN6ADDR_LINKLOCAL_ALLROUTERS_INIT |
83 | #define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \ |
84 | {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ |
85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}} |
86 | #endif |
87 | |
88 | /* |
89 | * BSD kernels don't inform userland of DAD results. |
90 | * See the discussion here: |
91 | * http://mail-index.netbsd.org/tech-net/2013/03/15/msg004019.html |
92 | */ |
93 | #ifndef __linux__ |
94 | /* We guard here to avoid breaking a compile on linux ppc-64 headers */ |
95 | # include <sys/param.h> |
96 | #endif |
97 | #ifdef BSD |
98 | # define IPV6_POLLADDRFLAG |
99 | #endif |
100 | |
101 | /* This was fixed in NetBSD */ |
102 | #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 699002000 |
103 | # undef IPV6_POLLADDRFLAG |
104 | #endif |
105 | |
106 | #ifdef __sun |
107 | /* Solaris lacks these defines. |
108 | * While it supports DaD, to seems to only expose IFF_DUPLICATE |
109 | * so we have no way of knowing if it's tentative or not. |
110 | * I don't even know if Solaris has any special treatment for tentative. */ |
111 | # define IN6_IFF_TENTATIVE 0 |
112 | # define IN6_IFF_DUPLICATED 0x04 |
113 | # define IN6_IFF_DETACHED 0 |
114 | #endif |
115 | |
116 | #define IN6_IFF_NOTUSEABLE \ |
117 | (IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_DETACHED) |
118 | |
119 | /* |
120 | * If dhcpcd handles RA processing instead of the kernel, the kernel needs |
121 | * to either allow userland to set temporary addresses or mark an address |
122 | * for the kernel to manage temporary addresses from. |
123 | * If the kernel allows the former, a global #define is needed, otherwise |
124 | * the address marking will be handled in the platform specific address handler. |
125 | * |
126 | * Some BSDs do not allow userland to set temporary addresses. |
127 | * Linux-3.18 allows the marking of addresses from which to manage temp addrs. |
128 | */ |
129 | #if defined(IN6_IFF_TEMPORARY) && !defined(__linux__) |
130 | #define IPV6_MANAGETEMPADDR |
131 | #endif |
132 | |
133 | #ifdef __linux__ |
134 | /* Match Linux defines to BSD */ |
135 | # ifdef IFA_F_TEMPORARY |
136 | # define IN6_IFF_TEMPORARY IFA_F_TEMPORARY |
137 | # endif |
138 | # ifdef IFA_F_OPTIMISTIC |
139 | # define IN6_IFF_TENTATIVE (IFA_F_TENTATIVE | IFA_F_OPTIMISTIC) |
140 | # else |
141 | # define IN6_IFF_TENTATIVE (IFA_F_TENTATIVE | 0x04) |
142 | # endif |
143 | # ifdef IF_F_DADFAILED |
144 | # define IN6_IFF_DUPLICATED IFA_F_DADFAILED |
145 | # else |
146 | # define IN6_IFF_DUPLICATED 0x08 |
147 | # endif |
148 | # define IN6_IFF_DETACHED 0 |
149 | #endif |
150 | |
151 | #ifdef INET6 |
152 | TAILQ_HEAD(ipv6_addrhead, ipv6_addr); |
153 | struct ipv6_addr { |
154 | TAILQ_ENTRY(ipv6_addr) next; |
155 | struct interface *iface; |
156 | struct in6_addr prefix; |
157 | uint8_t prefix_len; |
158 | uint32_t prefix_vltime; |
159 | uint32_t prefix_pltime; |
160 | struct timespec created; |
161 | struct timespec acquired; |
162 | struct in6_addr addr; |
163 | int addr_flags; |
164 | unsigned int flags; |
165 | char saddr[INET6_ADDRSTRLEN]; |
166 | uint8_t iaid[4]; |
167 | uint16_t ia_type; |
168 | int dhcp6_fd; |
169 | |
170 | #ifndef SMALL |
171 | struct ipv6_addr *delegating_prefix; |
172 | struct ipv6_addrhead pd_pfxs; |
173 | TAILQ_ENTRY(ipv6_addr) pd_next; |
174 | |
175 | uint8_t prefix_exclude_len; |
176 | struct in6_addr prefix_exclude; |
177 | #endif |
178 | |
179 | void (*dadcallback)(void *); |
180 | int dadcounter; |
181 | |
182 | struct nd_neighbor_advert *na; |
183 | size_t na_len; |
184 | int na_count; |
185 | |
186 | #ifdef ALIAS_ADDR |
187 | char alias[IF_NAMESIZE]; |
188 | #endif |
189 | }; |
190 | |
191 | #define IPV6_AF_ONLINK (1U << 0) |
192 | #define IPV6_AF_NEW (1U << 1) |
193 | #define IPV6_AF_STALE (1U << 2) |
194 | #define IPV6_AF_ADDED (1U << 3) |
195 | #define IPV6_AF_AUTOCONF (1U << 4) |
196 | #define IPV6_AF_DUPLICATED (1U << 5) |
197 | #define IPV6_AF_DADCOMPLETED (1U << 6) |
198 | #define IPV6_AF_DELEGATED (1U << 7) |
199 | #define IPV6_AF_DELEGATEDPFX (1U << 8) |
200 | #define IPV6_AF_NOREJECT (1U << 9) |
201 | #define IPV6_AF_REQUEST (1U << 10) |
202 | #define IPV6_AF_STATIC (1U << 11) |
203 | #define IPV6_AF_DELEGATEDLOG (1U << 12) |
204 | #define IPV6_AF_RAPFX (1U << 13) |
205 | #define IPV6_AF_EXTENDED (1U << 14) |
206 | #ifdef IPV6_MANAGETEMPADDR |
207 | #define IPV6_AF_TEMPORARY (1U << 15) |
208 | #endif |
209 | |
210 | struct ll_callback { |
211 | TAILQ_ENTRY(ll_callback) next; |
212 | void (*callback)(void *); |
213 | void *arg; |
214 | }; |
215 | TAILQ_HEAD(ll_callback_head, ll_callback); |
216 | |
217 | struct ipv6_state { |
218 | struct ipv6_addrhead addrs; |
219 | struct ll_callback_head ll_callbacks; |
220 | |
221 | #ifdef IPV6_MANAGETEMPADDR |
222 | time_t desync_factor; |
223 | uint8_t randomseed0[8]; /* upper 64 bits of MD5 digest */ |
224 | uint8_t randomseed1[8]; /* lower 64 bits */ |
225 | uint8_t randomid[8]; |
226 | #endif |
227 | }; |
228 | |
229 | #define IPV6_STATE(ifp) \ |
230 | ((struct ipv6_state *)(ifp)->if_data[IF_DATA_IPV6]) |
231 | #define IPV6_CSTATE(ifp) \ |
232 | ((const struct ipv6_state *)(ifp)->if_data[IF_DATA_IPV6]) |
233 | #define IPV6_STATE_RUNNING(ifp) ipv6_staticdadcompleted((ifp)) |
234 | |
235 | |
236 | int ipv6_init(struct dhcpcd_ctx *); |
237 | int ipv6_makestableprivate(struct in6_addr *addr, |
238 | const struct in6_addr *prefix, int prefix_len, |
239 | const struct interface *ifp, int *dad_counter); |
240 | int ipv6_makeaddr(struct in6_addr *, struct interface *, |
241 | const struct in6_addr *, int); |
242 | int ipv6_mask(struct in6_addr *, int); |
243 | uint8_t ipv6_prefixlen(const struct in6_addr *); |
244 | int ipv6_userprefix( const struct in6_addr *, short prefix_len, |
245 | uint64_t user_number, struct in6_addr *result, short result_len); |
246 | void ipv6_checkaddrflags(void *); |
247 | void (struct interface *, unsigned int); |
248 | void ipv6_deletestaleaddrs(struct interface *); |
249 | int ipv6_addaddr(struct ipv6_addr *, const struct timespec *); |
250 | ssize_t ipv6_addaddrs(struct ipv6_addrhead *addrs); |
251 | void ipv6_deleteaddr(struct ipv6_addr *); |
252 | void ipv6_freedrop_addrs(struct ipv6_addrhead *, int, |
253 | const struct interface *); |
254 | void ipv6_handleifa(struct dhcpcd_ctx *ctx, int, struct if_head *, |
255 | const char *, const struct in6_addr *, uint8_t, int, pid_t); |
256 | int ipv6_handleifa_addrs(int, struct ipv6_addrhead *, const struct ipv6_addr *, |
257 | pid_t); |
258 | struct ipv6_addr *ipv6_iffindaddr(struct interface *, |
259 | const struct in6_addr *, int); |
260 | int ipv6_hasaddr(const struct interface *); |
261 | int ipv6_findaddrmatch(const struct ipv6_addr *, const struct in6_addr *, |
262 | unsigned int); |
263 | struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *, |
264 | const struct in6_addr *, unsigned int); |
265 | struct ipv6_addr *ipv6_findmaskaddr(struct dhcpcd_ctx *, |
266 | const struct in6_addr *); |
267 | #define ipv6_linklocal(ifp) ipv6_iffindaddr((ifp), NULL, IN6_IFF_NOTUSEABLE) |
268 | int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *); |
269 | struct ipv6_addr *ipv6_newaddr(struct interface *, const struct in6_addr *, uint8_t, |
270 | unsigned int); |
271 | void ipv6_freeaddr(struct ipv6_addr *); |
272 | void ipv6_freedrop(struct interface *, int); |
273 | #define ipv6_free(ifp) ipv6_freedrop((ifp), 0) |
274 | #define ipv6_drop(ifp) ipv6_freedrop((ifp), 2) |
275 | |
276 | #ifdef IPV6_MANAGETEMPADDR |
277 | void ipv6_gentempifid(struct interface *); |
278 | struct ipv6_addr *ipv6_createtempaddr(struct ipv6_addr *, |
279 | const struct timespec *); |
280 | struct ipv6_addr *ipv6_settemptime(struct ipv6_addr *, int); |
281 | void ipv6_addtempaddrs(struct interface *, const struct timespec *); |
282 | #else |
283 | #define ipv6_gentempifid(a) {} |
284 | #define ipv6_settempstale(a) {} |
285 | #endif |
286 | |
287 | int ipv6_start(struct interface *); |
288 | int ipv6_staticdadcompleted(const struct interface *); |
289 | int ipv6_startstatic(struct interface *); |
290 | ssize_t ipv6_env(char **, const char *, const struct interface *); |
291 | void ipv6_ctxfree(struct dhcpcd_ctx *); |
292 | bool inet6_getroutes(struct dhcpcd_ctx *, struct rt_head *); |
293 | #endif /* INET6 */ |
294 | |
295 | #endif /* INET6_H */ |
296 | |