/* * dhcpcd - DHCP client daemon * Copyright (c) 2006-2015 Roy Marples * 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 #include #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 #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