| 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 |  |