xref: /minix/external/bsd/dhcpcd/dist/ipv6.h (revision bb9622b5)
1 /* $NetBSD: ipv6.h,v 1.14 2015/07/09 10:15:34 roy Exp $ */
2 
3 /*
4  * dhcpcd - DHCP client daemon
5  * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
6  * All rights reserved
7 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #ifndef IPV6_H
31 #define IPV6_H
32 
33 #include <sys/uio.h>
34 #include <netinet/in.h>
35 
36 #ifndef __linux__
37 #  ifndef __QNX__
38 #    include <sys/endian.h>
39 #  endif
40 #  include <net/if.h>
41 #  ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */
42 #    include <net/if_var.h>
43 #  endif
44 #  ifndef __sun
45 #    include <netinet6/in6_var.h>
46 #  endif
47 #endif
48 
49 #include "config.h"
50 #include "dhcpcd.h"
51 
52 #define ALLROUTERS "ff02::2"
53 
54 #define ROUNDUP8(a)  (1 + (((a) - 1) |  7))
55 #define ROUNDUP16(a) (1 + (((a) - 1) | 16))
56 
57 #define EUI64_GBIT		0x01
58 #define EUI64_UBIT		0x02
59 #define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
60 #define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)
61 
62 #ifndef ND6_INFINITE_LIFETIME
63 #  define ND6_INFINITE_LIFETIME		((uint32_t)~0)
64 #endif
65 
66 /* RFC4941 constants */
67 #define TEMP_VALID_LIFETIME	604800	/* 1 week */
68 #define TEMP_PREFERRED_LIFETIME	86400	/* 1 day */
69 #define REGEN_ADVANCE		5	/* seconds */
70 #define MAX_DESYNC_FACTOR	600	/* 10 minutes */
71 
72 #define TEMP_IDGEN_RETRIES	3
73 #define GEN_TEMPID_RETRY_MAX	5
74 
75 /* RFC7217 constants */
76 #define IDGEN_RETRIES	3
77 #define IDGEN_DELAY	1 /* second */
78 
79 /*
80  * BSD kernels don't inform userland of DAD results.
81  * See the discussion here:
82  *    http://mail-index.netbsd.org/tech-net/2013/03/15/msg004019.html
83  */
84 #ifndef __linux__
85 /* We guard here to avoid breaking a compile on linux ppc-64 headers */
86 #  include <sys/param.h>
87 #endif
88 #ifdef BSD
89 #  define IPV6_POLLADDRFLAG
90 #endif
91 
92 /* This was fixed in NetBSD */
93 #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 699002000
94 #  undef IPV6_POLLADDRFLAG
95 #endif
96 
97 /* Linux-3.18 can manage temporary addresses even with RA
98  * processing disabled. */
99 //#undef IFA_F_MANAGETEMPADDR
100 #if defined(__linux__) && defined(IFA_F_MANAGETEMPADDR)
101 #define IPV6_MANAGETEMPADDR
102 #endif
103 
104 /* Some BSDs do not allow userland to set temporary addresses. */
105 #if defined(BSD) && defined(IN6_IFF_TEMPORARY)
106 #define IPV6_MANAGETEMPADDR
107 #endif
108 
109 struct ipv6_addr {
110 	TAILQ_ENTRY(ipv6_addr) next;
111 	struct interface *iface;
112 	struct in6_addr prefix;
113 	uint8_t prefix_len;
114 	uint32_t prefix_vltime;
115 	uint32_t prefix_pltime;
116 	struct timespec created;
117 	struct timespec acquired;
118 	struct in6_addr addr;
119 	int addr_flags;
120 	short flags;
121 	char saddr[INET6_ADDRSTRLEN];
122 	uint8_t iaid[4];
123 	uint16_t ia_type;
124 	struct interface *delegating_iface;
125 	uint8_t prefix_exclude_len;
126 	struct in6_addr prefix_exclude;
127 
128 	void (*dadcallback)(void *);
129 	int dadcounter;
130 	uint8_t *ns;
131 	size_t nslen;
132 	int nsprobes;
133 };
134 TAILQ_HEAD(ipv6_addrhead, ipv6_addr);
135 
136 #define IPV6_AF_ONLINK		0x0001
137 #define	IPV6_AF_NEW		0x0002
138 #define IPV6_AF_STALE		0x0004
139 #define IPV6_AF_ADDED		0x0008
140 #define IPV6_AF_AUTOCONF	0x0010
141 #define IPV6_AF_DUPLICATED	0x0020
142 #define IPV6_AF_DADCOMPLETED	0x0040
143 #define IPV6_AF_DELEGATED	0x0080
144 #define IPV6_AF_DELEGATEDPFX	0x0100
145 #define IPV6_AF_DELEGATEDZERO	0x0200
146 #define IPV6_AF_REQUEST		0x0400
147 #ifdef IPV6_MANAGETEMPADDR
148 #define IPV6_AF_TEMPORARY	0X0800
149 #endif
150 
151 struct rt6 {
152 	TAILQ_ENTRY(rt6) next;
153 	struct in6_addr dest;
154 	struct in6_addr net;
155 	struct in6_addr gate;
156 	const struct interface *iface;
157 	unsigned int flags;
158 #ifdef HAVE_ROUTE_METRIC
159 	unsigned int metric;
160 #endif
161 	unsigned int mtu;
162 };
163 TAILQ_HEAD(rt6_head, rt6);
164 
165 struct ll_callback {
166 	TAILQ_ENTRY(ll_callback) next;
167 	void (*callback)(void *);
168 	void *arg;
169 };
170 TAILQ_HEAD(ll_callback_head, ll_callback);
171 
172 struct ipv6_state {
173 	struct ipv6_addrhead addrs;
174 	struct ll_callback_head ll_callbacks;
175 
176 #ifdef IPV6_MANAGETEMPADDR
177 	time_t desync_factor;
178 	uint8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
179 	uint8_t randomseed1[8]; /* lower 64 bits */
180 	uint8_t randomid[8];
181 #endif
182 };
183 
184 #define IPV6_STATE(ifp)							       \
185 	((struct ipv6_state *)(ifp)->if_data[IF_DATA_IPV6])
186 #define IPV6_CSTATE(ifp)						       \
187 	((const struct ipv6_state *)(ifp)->if_data[IF_DATA_IPV6])
188 
189 /* dhcpcd requires CMSG_SPACE to evaluate to a compile time constant. */
190 #ifdef __QNX__
191 #undef CMSG_SPACE
192 #endif
193 
194 #ifndef ALIGNBYTES
195 #define ALIGNBYTES (sizeof(int) - 1)
196 #endif
197 #ifndef ALIGN
198 #define	ALIGN(p) (((unsigned int)(p) + ALIGNBYTES) & ~ALIGNBYTES)
199 #endif
200 #ifndef CMSG_SPACE
201 #define	CMSG_SPACE(len)	(ALIGN(sizeof(struct cmsghdr)) + ALIGN(len))
202 #endif
203 
204 #define IP6BUFLEN	(CMSG_SPACE(sizeof(struct in6_pktinfo)) + \
205 			CMSG_SPACE(sizeof(int)))
206 
207 
208 #ifdef INET6
209 struct ipv6_ctx {
210 	struct sockaddr_in6 from;
211 	struct msghdr sndhdr;
212 	struct iovec sndiov[2];
213 	unsigned char sndbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
214 	struct msghdr rcvhdr;
215 	struct iovec rcviov[2];
216 	unsigned char rcvbuf[IP6BUFLEN];
217 	unsigned char ansbuf[1500];
218 	char ntopbuf[INET6_ADDRSTRLEN];
219 	const char *sfrom;
220 
221 	int nd_fd;
222 	struct ra_head *ra_routers;
223 	struct rt6_head *routes;
224 
225 	struct rt6_head kroutes;
226 
227 	int dhcp_fd;
228 };
229 
230 struct ipv6_ctx *ipv6_init(struct dhcpcd_ctx *);
231 ssize_t ipv6_printaddr(char *, size_t, const uint8_t *, const char *);
232 int ipv6_makestableprivate(struct in6_addr *addr,
233     const struct in6_addr *prefix, int prefix_len,
234     const struct interface *ifp, int *dad_counter);
235 int ipv6_makeaddr(struct in6_addr *, const struct interface *,
236     const struct in6_addr *, int);
237 int ipv6_makeprefix(struct in6_addr *, const struct in6_addr *, int);
238 int ipv6_mask(struct in6_addr *, int);
239 uint8_t ipv6_prefixlen(const struct in6_addr *);
240 int ipv6_userprefix( const struct in6_addr *, short prefix_len,
241     uint64_t user_number, struct in6_addr *result, short result_len);
242 void ipv6_checkaddrflags(void *);
243 int ipv6_addaddr(struct ipv6_addr *, const struct timespec *);
244 ssize_t ipv6_addaddrs(struct ipv6_addrhead *addrs);
245 void ipv6_freedrop_addrs(struct ipv6_addrhead *, int,
246     const struct interface *);
247 void ipv6_handleifa(struct dhcpcd_ctx *ctx, int, struct if_head *,
248     const char *, const struct in6_addr *, uint8_t, int);
249 int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
250     const struct in6_addr *, int);
251 int ipv6_publicaddr(const struct ipv6_addr *);
252 const struct ipv6_addr *ipv6_iffindaddr(const struct interface *,
253     const struct in6_addr *);
254 int ipv6_hasaddr(const struct interface *);
255 int ipv6_findaddrmatch(const struct ipv6_addr *, const struct in6_addr *,
256     short);
257 struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *,
258     const struct in6_addr *, short);
259 #define ipv6_linklocal(ifp) ipv6_iffindaddr((ifp), NULL)
260 int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *);
261 void ipv6_freeaddr(struct ipv6_addr *);
262 void ipv6_freedrop(struct interface *, int);
263 #define ipv6_free(ifp) ipv6_freedrop((ifp), 0)
264 #define ipv6_drop(ifp) ipv6_freedrop((ifp), 2)
265 
266 #ifdef IPV6_MANAGETEMPADDR
267 void ipv6_gentempifid(struct interface *);
268 void ipv6_settempstale(struct interface *);
269 struct ipv6_addr *ipv6_createtempaddr(struct ipv6_addr *,
270     const struct timespec *);
271 struct ipv6_addr *ipv6_settemptime(struct ipv6_addr *, int);
272 void ipv6_addtempaddrs(struct interface *, const struct timespec *);
273 #else
274 #define ipv6_gentempifid(a) {}
275 #define ipv6_settempstale(a) {}
276 #endif
277 
278 int ipv6_start(struct interface *);
279 void ipv6_ctxfree(struct dhcpcd_ctx *);
280 int ipv6_handlert(struct dhcpcd_ctx *, int cmd, struct rt6 *);
281 void ipv6_freerts(struct rt6_head *);
282 void ipv6_buildroutes(struct dhcpcd_ctx *);
283 
284 #else
285 #define ipv6_init(a) (NULL)
286 #define ipv6_start(a) (-1)
287 #define ipv6_hasaddr(a) (0)
288 #define ipv6_free_ll_callbacks(a) {}
289 #define ipv6_free(a) {}
290 #define ipv6_drop(a) {}
291 #define ipv6_ctxfree(a) {}
292 #define ipv6_gentempifid(a) {}
293 #endif
294 
295 #endif
296