aboutsummaryrefslogtreecommitdiff
path: root/ipv6.h
blob: a2e3042ccd452a5d603663f45406f40248000324 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/*
 * dhcpcd - DHCP client daemon
 * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
 * All rights reserved

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef IPV6_H
#define IPV6_H

#include <sys/uio.h>
#include <netinet/in.h>

#include "config.h"
#include "dhcpcd.h"

#define ALLROUTERS "ff02::2"

#define ROUNDUP8(a)  (1 + (((a) - 1) |  7))
#define ROUNDUP16(a) (1 + (((a) - 1) | 16))

#define EUI64_GBIT		0x01
#define EUI64_UBIT		0x02
#define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
#define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)

#ifndef ND6_INFINITE_LIFETIME
#  define ND6_INFINITE_LIFETIME		((uint32_t)~0)
#endif

/* RFC4941 constants */
#define TEMP_VALID_LIFETIME	604800	/* 1 week */
#define TEMP_PREFERRED_LIFETIME	86400	/* 1 day */
#define REGEN_ADVANCE		5	/* seconds */
#define MAX_DESYNC_FACTOR	600	/* 10 minutes */

#define TEMP_IDGEN_RETRIES	3
#define GEN_TEMPID_RETRY_MAX	5

/* RFC7217 constants */
#define IDGEN_RETRIES	3
#define IDGEN_DELAY	1 /* second */

/*
 * BSD kernels don't inform userland of DAD results.
 * See the discussion here:
 *    http://mail-index.netbsd.org/tech-net/2013/03/15/msg004019.html
 */
#ifndef __linux__
/* We guard here to avoid breaking a compile on linux ppc-64 headers */
#  include <sys/param.h>
#endif
#ifdef BSD
#  define IPV6_POLLADDRFLAG
#endif

/* This was fixed in NetBSD */
#if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 699002000
#  undef IPV6_POLLADDRFLAG
#endif

/* Linux-3.18 can manage temporary addresses even with RA
 * processing disabled. */
//#undef IFA_F_MANAGETEMPADDR
#if defined(__linux__) && defined(IFA_F_MANAGETEMPADDR)
#define IPV6_MANAGETEMPADDR
#endif

/* Some BSDs do not allow userland to set temporary addresses. */
#if defined(BSD) && defined(IN6_IFF_TEMPORARY)
#define IPV6_MANAGETEMPADDR
#endif

struct ipv6_addr {
	TAILQ_ENTRY(ipv6_addr) next;
	struct interface *iface;
	struct in6_addr prefix;
	uint8_t prefix_len;
	uint32_t prefix_vltime;
	uint32_t prefix_pltime;
	struct timespec created;
	struct timespec acquired;
	struct in6_addr addr;
	int addr_flags;
	short flags;
	char saddr[INET6_ADDRSTRLEN];
	uint8_t iaid[4];
	uint16_t ia_type;
	struct interface *delegating_iface;
	uint8_t prefix_exclude_len;
	struct in6_addr prefix_exclude;

	void (*dadcallback)(void *);
	int dadcounter;
	uint8_t *ns;
	size_t nslen;
	int nsprobes;
};
TAILQ_HEAD(ipv6_addrhead, ipv6_addr);

#define IPV6_AF_ONLINK		0x0001
#define	IPV6_AF_NEW		0x0002
#define IPV6_AF_STALE		0x0004
#define IPV6_AF_ADDED		0x0008
#define IPV6_AF_AUTOCONF	0x0010
#define IPV6_AF_DUPLICATED	0x0020
#define IPV6_AF_DADCOMPLETED	0x0040
#define IPV6_AF_DELEGATED	0x0080
#define IPV6_AF_DELEGATEDPFX	0x0100
#define IPV6_AF_DELEGATEDZERO	0x0200
#define IPV6_AF_REQUEST		0x0400
#ifdef IPV6_MANAGETEMPADDR
#define IPV6_AF_TEMPORARY	0X0800
#endif

struct rt6 {
	TAILQ_ENTRY(rt6) next;
	struct in6_addr dest;
	struct in6_addr net;
	struct in6_addr gate;
	const struct interface *iface;
	unsigned int flags;
#ifdef HAVE_ROUTE_METRIC
	unsigned int metric;
#endif
	unsigned int mtu;
};
TAILQ_HEAD(rt6_head, rt6);

struct ll_callback {
	TAILQ_ENTRY(ll_callback) next;
	void (*callback)(void *);
	void *arg;
};
TAILQ_HEAD(ll_callback_head, ll_callback);

struct ipv6_state {
	struct ipv6_addrhead addrs;
	struct ll_callback_head ll_callbacks;

#ifdef IPV6_MANAGETEMPADDR
	time_t desync_factor;
	uint8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
	uint8_t randomseed1[8]; /* lower 64 bits */
	uint8_t randomid[8];
#endif
};

#define IPV6_STATE(ifp)							       \
	((struct ipv6_state *)(ifp)->if_data[IF_DATA_IPV6])
#define IPV6_CSTATE(ifp)						       \
	((const struct ipv6_state *)(ifp)->if_data[IF_DATA_IPV6])

/* dhcpcd requires CMSG_SPACE to evaluate to a compile time constant. */
#ifdef __QNX__
#undef CMSG_SPACE
#endif

#ifndef ALIGNBYTES
#define ALIGNBYTES (sizeof(int) - 1)
#endif
#ifndef ALIGN
#define	ALIGN(p) (((unsigned int)(p) + ALIGNBYTES) & ~ALIGNBYTES)
#endif
#ifndef CMSG_SPACE
#define	CMSG_SPACE(len)	(ALIGN(sizeof(struct cmsghdr)) + ALIGN(len))
#endif

#define IP6BUFLEN	(CMSG_SPACE(sizeof(struct in6_pktinfo)) + \
			CMSG_SPACE(sizeof(int)))


#ifdef INET6
struct ipv6_ctx {
	struct sockaddr_in6 from;
	struct msghdr sndhdr;
	struct iovec sndiov[2];
	unsigned char sndbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
	struct msghdr rcvhdr;
	struct iovec rcviov[2];
	unsigned char rcvbuf[IP6BUFLEN];
	unsigned char ansbuf[1500];
	char ntopbuf[INET6_ADDRSTRLEN];
	const char *sfrom;

	int nd_fd;
	struct ra_head *ra_routers;
	struct rt6_head *routes;

	struct rt6_head kroutes;

	int dhcp_fd;
};

struct ipv6_ctx *ipv6_init(struct dhcpcd_ctx *);
ssize_t ipv6_printaddr(char *, size_t, const uint8_t *, const char *);
int ipv6_makestableprivate(struct in6_addr *addr,
    const struct in6_addr *prefix, int prefix_len,
    const struct interface *ifp, int *dad_counter);
int ipv6_makeaddr(struct in6_addr *, const struct interface *,
    const struct in6_addr *, int);
int ipv6_makeprefix(struct in6_addr *, const struct in6_addr *, int);
int ipv6_mask(struct in6_addr *, int);
uint8_t ipv6_prefixlen(const struct in6_addr *);
int ipv6_userprefix( const struct in6_addr *, short prefix_len,
    uint64_t user_number, struct in6_addr *result, short result_len);
void ipv6_checkaddrflags(void *);
int ipv6_addaddr(struct ipv6_addr *, const struct timespec *);
ssize_t ipv6_addaddrs(struct ipv6_addrhead *addrs);
void ipv6_freedrop_addrs(struct ipv6_addrhead *, int,
    const struct interface *);
void ipv6_handleifa(struct dhcpcd_ctx *ctx, int, struct if_head *,
    const char *, const struct in6_addr *, uint8_t, int);
int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
    const struct in6_addr *, int);
int ipv6_publicaddr(const struct ipv6_addr *);
const struct ipv6_addr *ipv6_iffindaddr(const struct interface *,
    const struct in6_addr *);
struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *,
    const struct in6_addr *, short);
#define ipv6_linklocal(ifp) ipv6_iffindaddr((ifp), NULL)
int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *);
void ipv6_freeaddr(struct ipv6_addr *);
void ipv6_freedrop(struct interface *, int);
#define ipv6_free(ifp) ipv6_freedrop((ifp), 0)
#define ipv6_drop(ifp) ipv6_freedrop((ifp), 2)

#ifdef IPV6_MANAGETEMPADDR
void ipv6_gentempifid(struct interface *);
void ipv6_settempstale(struct interface *);
struct ipv6_addr *ipv6_createtempaddr(struct ipv6_addr *,
    const struct timespec *);
struct ipv6_addr *ipv6_settemptime(struct ipv6_addr *, int);
void ipv6_addtempaddrs(struct interface *, const struct timespec *);
#else
#define ipv6_gentempifid(a) {}
#define ipv6_settempstale(a) {}
#endif

int ipv6_start(struct interface *);
void ipv6_ctxfree(struct dhcpcd_ctx *);
int ipv6_handlert(struct dhcpcd_ctx *, int cmd, struct rt6 *);
void ipv6_freerts(struct rt6_head *);
void ipv6_buildroutes(struct dhcpcd_ctx *);

#else
#define ipv6_init(a) (NULL)
#define ipv6_start(a) (-1)
#define ipv6_free_ll_callbacks(a) {}
#define ipv6_free(a) {}
#define ipv6_drop(a) {}
#define ipv6_ctxfree(a) {}
#define ipv6_gentempifid(a) {}
#endif

#endif