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