diff options
| author | Roy Marples <roy@marples.name> | 2012-07-05 16:37:41 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2012-07-05 16:37:41 +0000 |
| commit | eebe9a1887bbf2f3bbb4fdb72e8d46ece25cdd0c (patch) | |
| tree | da2e3069767ce09c41eb2b32e6a3b7f01b164eca /if-bsd.c | |
| parent | 359e9d397807079db8d68d5e60eb4396f41d1738 (diff) | |
| download | dhcpcd-eebe9a1887bbf2f3bbb4fdb72e8d46ece25cdd0c.tar.xz | |
Improve IPv6 RA support by allowing dhcpcd to manage the address and routesdhcpcd-5.6.0
instead of the kernel. dhcpcd will only do this if RA is disabled in the kernel
or dhcpcd has been instructed to do this via dhcpcd.conf(5) ipv6ra_own and
ipv6ra_own_default directives.
Send and process IPv6 Neighbor Solicitions and Adverts to prove router
reachability. If a router cannot be reached in this way then it is expired.
When debugging, all ND messages are displayed which will create a lot of log
spam.
To ease packaging, ./configure now accepts LDFLAGS and --enable-static.
Diffstat (limited to 'if-bsd.c')
| -rw-r--r-- | if-bsd.c | 171 |
1 files changed, 153 insertions, 18 deletions
@@ -35,8 +35,12 @@ #include <arpa/inet.h> #include <net/if.h> #include <net/if_dl.h> +#ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */ +# include <net/if_var.h> +#endif #include <net/route.h> #include <netinet/in.h> +#include <netinet6/in6_var.h> #ifdef __DragonFly__ # include <netproto/802_11/ieee80211_ioctl.h> #elif __APPLE__ @@ -59,6 +63,7 @@ #include "configure.h" #include "dhcp.h" #include "if-options.h" +#include "ipv6.h" #include "net.h" #ifndef RT_ROUNDUP @@ -154,7 +159,6 @@ if_address(const struct interface *iface, const struct in_addr *address, const struct in_addr *netmask, const struct in_addr *broadcast, int action) { - int retval; struct ifaliasreq ifa; union { struct sockaddr *sa; @@ -178,23 +182,16 @@ if_address(const struct interface *iface, const struct in_addr *address, } #undef ADDADDR - if (action < 0) - retval = ioctl(socket_afnet, SIOCDIFADDR, &ifa); - else - retval = ioctl(socket_afnet, SIOCAIFADDR, &ifa); - return retval; + return ioctl(socket_afnet, + action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifa); } -/* ARGSUSED4 */ int if_route(const struct rt *rt, int action) { union sockunion { struct sockaddr sa; struct sockaddr_in sin; -#ifdef INET6 - struct sockaddr_in6 sin6; -#endif struct sockaddr_dl sdl; struct sockaddr_storage ss; } su; @@ -207,17 +204,17 @@ if_route(const struct rt *rt, int action) size_t l; int retval = 0; -#define ADDSU(_su) { \ - l = RT_ROUNDUP(_su.sa.sa_len); \ - memcpy(bp, &(_su), l); \ +#define ADDSU { \ + l = RT_ROUNDUP(su.sa.sa_len); \ + memcpy(bp, &su, l); \ bp += l; \ } -#define ADDADDR(_a) { \ - memset (&su, 0, sizeof(su)); \ +#define ADDADDR(addr) { \ + memset(&su, 0, sizeof(su)); \ su.sin.sin_family = AF_INET; \ su.sin.sin_len = sizeof(su.sin); \ - memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr)); \ - ADDSU(su); \ + (&su.sin)->sin_addr = *addr; \ + ADDSU; \ } memset(&rtm, 0, sizeof(rtm)); @@ -255,16 +252,154 @@ if_route(const struct rt *rt, int action) memset(&su, 0, sizeof(su)); su.sdl.sdl_len = sizeof(struct sockaddr_dl); link_addr(rt->iface->name, &su.sdl); - ADDSU(su); + ADDSU; } else ADDADDR(&rt->gate); if (rtm.hdr.rtm_addrs & RTA_NETMASK) ADDADDR(&rt->net); + /* IFP here if we need it */ + if (rtm.hdr.rtm_addrs & RTA_IFA) ADDADDR(&rt->iface->addr); +#undef ADDADDR +#undef ADDSU + + rtm.hdr.rtm_msglen = l = bp - (char *)&rtm; + if (write(r_fd, &rtm, l) == -1) + retval = -1; + return retval; +} + +int +if_address6(const struct interface *ifp, const struct ipv6_addr *a, int action) +{ + struct in6_aliasreq ifa; + struct in6_addr mask; + + memset(&ifa, 0, sizeof(ifa)); + strlcpy(ifa.ifra_name, ifp->name, sizeof(ifa.ifra_name)); + +#define ADDADDR(v, addr) { \ + (v)->sin6_family = AF_INET6; \ + (v)->sin6_len = sizeof(*v); \ + (v)->sin6_addr = *addr; \ + } + + ADDADDR(&ifa.ifra_addr, &a->addr); + ipv6_mask(&mask, a->prefix_len); + ADDADDR(&ifa.ifra_prefixmask, &mask); + ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime; + ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime; +#undef ADDADDR + + return ioctl(socket_afnet6, + action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa); +} + +int +if_route6(const struct rt6 *rt, int action) +{ + union sockunion { + struct sockaddr sa; + struct sockaddr_in6 sin; + struct sockaddr_dl sdl; + struct sockaddr_storage ss; + } su; + struct rtm + { + struct rt_msghdr hdr; + char buffer[sizeof(su) * 4]; + } rtm; + char *bp = rtm.buffer; + size_t l; + int retval = 0; + +/* KAME based systems want to store the scope inside the sin6_addr + * for link local addreses */ +#ifdef __KAME__ +#define SCOPE { \ + if (IN6_IS_ADDR_LINKLOCAL(&su.sin.sin6_addr)) { \ + *(uint16_t *)(void *)&su.sin.sin6_addr.s6_addr[2] = \ + htons(su.sin.sin6_scope_id); \ + su.sin.sin6_scope_id = 0; \ + } \ + } +#else +#define SCOPE +#endif + +#define ADDSU { \ + l = RT_ROUNDUP(su.sa.sa_len); \ + memcpy(bp, &su, l); \ + bp += l; \ + } +#define ADDADDRS(addr, scope) { \ + memset(&su, 0, sizeof(su)); \ + su.sin.sin6_family = AF_INET6; \ + su.sin.sin6_len = sizeof(su.sin); \ + (&su.sin)->sin6_addr = *addr; \ + su.sin.sin6_scope_id = scope; \ + SCOPE; \ + ADDSU; \ + } +#define ADDADDR(addr) ADDADDRS(addr, 0) + + memset(&rtm, 0, sizeof(rtm)); + rtm.hdr.rtm_version = RTM_VERSION; + rtm.hdr.rtm_seq = 1; + if (action == 0) + rtm.hdr.rtm_type = RTM_CHANGE; + else if (action > 0) + rtm.hdr.rtm_type = RTM_ADD; + else + rtm.hdr.rtm_type = RTM_DELETE; + + rtm.hdr.rtm_flags = RTF_UP; + /* None interface subnet routes are static. */ + if (IN6_IS_ADDR_UNSPECIFIED(&rt->dest) && + IN6_IS_ADDR_UNSPECIFIED(&rt->net)) + rtm.hdr.rtm_flags |= RTF_GATEWAY; + else + rtm.hdr.rtm_flags |= RTF_CLONING; + + rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; +// if (action >= 0) +// rtm.hdr.rtm_addrs |= RTA_IFA; + + ADDADDR(&rt->dest); + if (rtm.hdr.rtm_flags & (RTF_HOST | RTF_CLONING)) { + /* Make us a link layer socket for the host gateway */ + memset(&su, 0, sizeof(su)); + su.sdl.sdl_len = sizeof(struct sockaddr_dl); + link_addr(rt->iface->name, &su.sdl); + ADDSU; + } else + ADDADDRS(&rt->gate, rt->iface->index); + + if (rtm.hdr.rtm_addrs & RTA_NETMASK) { + if (rtm.hdr.rtm_flags & RTF_GATEWAY) { + memset(&su, 0, sizeof(su)); + su.sin.sin6_family = AF_INET6; + ADDSU; + } else + ADDADDR(&rt->net); + } + + /* IFP here if we need it */ + /* IFA here if we need it */ + +#undef ADDADDR +#undef ADDSU +#undef SCOPE + + if (action >= 0 && rt->mtu) { + rtm.hdr.rtm_inits |= RTV_MTU; + rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu; + } + rtm.hdr.rtm_msglen = l = bp - (char *)&rtm; if (write(r_fd, &rtm, l) == -1) retval = -1; |
