From: Roy Marples Date: Mon, 2 May 2016 01:55:50 +0000 (+0000) Subject: Solaris does not return AF_LINK addresses in getifaddrs(3), so X-Git-Tag: v6.11.0~55 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7de8947f6016216020ce25c1545c1279e0defef2;p=thirdparty%2Fdhcpcd.git Solaris does not return AF_LINK addresses in getifaddrs(3), so link to dlpi, walk the interfaces and obtain the physical address of each interface. --- diff --git a/configure b/configure index eaa6db2b..0090c034 100755 --- a/configure +++ b/configure @@ -406,6 +406,7 @@ sunos*) echo "CPPFLAGS+= -D_XPG4_2 -D__EXTENSIONS__ -DBSD_COMP" \ >>$CONFIG_MK echo "DHCPCD_SRCS+= if-sun.c" >>$CONFIG_MK + echo "LDADD+= -ldlpi" >>$CONFIG_MK # IPv6 won't work, but it will at least compile. echo "CPPFLAGS+= -DIN6_IFF_DETACHED=0" >>$CONFIG_MK diff --git a/if-sun.c b/if-sun.c index 68986a42..bef4f59a 100644 --- a/if-sun.c +++ b/if-sun.c @@ -25,12 +25,19 @@ * SUCH DAMAGE. */ +#include #include #include -#include +#include +#include +#include +#include #include +#include +#include + #include "config.h" #include "common.h" #include "dhcp.h" @@ -58,8 +65,7 @@ int if_opensockets_os(struct dhcpcd_ctx *ctx) { - errno = ENOTSUP; - return -1; + return 0; } void @@ -91,6 +97,7 @@ if_managelink(struct dhcpcd_ctx *ctx) return -1; } +int if_machinearch(char *str, size_t len) { @@ -98,6 +105,98 @@ if_machinearch(char *str, size_t len) return -1; } +struct linkwalk { + struct ifaddrs *lw_ifa; + int lw_error; +}; + +static boolean_t +if_newaddr(const char *ifname, void *arg) +{ + struct linkwalk *lw = arg; + struct ifaddrs *ifa; + dlpi_handle_t dh; + dlpi_info_t dlinfo; + uint8_t pa[DLPI_PHYSADDR_MAX]; + unsigned int pa_len; + struct sockaddr_dl *sdl; + + ifa = NULL; + if (dlpi_open(ifname, &dh, 0) != DLPI_SUCCESS) + goto failed1; + if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) + goto failed; + + /* For some reason, dlpi_info won't return the + * physical address, it's all zero's. + * So cal dlpi_get_physaddr. */ + pa_len = DLPI_PHYSADDR_MAX; + if (dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, + pa, &pa_len) != DLPI_SUCCESS) + goto failed; + + if ((ifa = calloc(1, sizeof(*ifa))) == NULL) + goto failed; + if ((ifa->ifa_addr = calloc(1, sizeof(struct sockaddr_dl))) == NULL) + goto failed; + + if ((ifa->ifa_name = strdup(ifname)) == NULL) + goto failed; + + sdl = (struct sockaddr_dl *)ifa->ifa_addr; + + sdl->sdl_family = AF_LINK; + switch (dlinfo.di_mactype) { + case DL_ETHER: + sdl->sdl_type = IFT_ETHER; + break; + case DL_IB: + sdl->sdl_type = IFT_IB; + break; + default: + sdl->sdl_type = IFT_OTHER; + break; + } + + sdl->sdl_alen = pa_len; + memcpy(sdl->sdl_data, pa, pa_len); + + ifa->ifa_next = lw->lw_ifa; + lw->lw_ifa = ifa; + dlpi_close(dh); + return (B_FALSE); + +failed: + dlpi_close(dh); + if (ifa != NULL) { + free(ifa->ifa_name); + free(ifa->ifa_addr); + free(ifa); + } +failed1: + lw->lw_error = errno; + return (B_TRUE); +} + +/* all getifaddrs(3) should support AF_LINK, but hey ho */ +int +if_getifaddrs(struct ifaddrs **ifap) +{ + struct linkwalk lw = { NULL, 0 }; + int error; + + error = 0; + dlpi_walk(if_newaddr, &lw, 0); + if (lw.lw_error != 0) { + freeifaddrs(lw.lw_ifa); + errno = lw.lw_error; + return -1; + } + + *ifap = lw.lw_ifa; + return 0; +} + #ifdef INET const char *if_pfname = "SunOS"; diff --git a/if.c b/if.c index b51b2d28..7fe4132b 100644 --- a/if.c +++ b/if.c @@ -271,8 +271,13 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) const struct sockaddr_ll *sll; #endif +#ifdef GETIFADDRS_AFLINK if (getifaddrs(&ifaddrs) == -1) return NULL; +#else + if (if_getifaddrs(&ifaddrs) == -1) + return NULL; +#endif ifs = malloc(sizeof(*ifs)); if (ifs == NULL) return NULL; @@ -549,8 +554,15 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) TAILQ_INSERT_TAIL(ifs, ifp, next); } - if_learnaddrs(ctx, ifs, ifaddrs); +#ifdef GETIFADDRS_AFLINK + { +#else freeifaddrs(ifaddrs); + if (getifaddrs(&ifaddrs) != -1) { +#endif + if_learnaddrs(ctx, ifs, ifaddrs); + freeifaddrs(ifaddrs); + } return ifs; } diff --git a/if.h b/if.h index aaf74f1d..f174ee4c 100644 --- a/if.h +++ b/if.h @@ -83,6 +83,14 @@ #define RAW_EOF 1 << 0 #define RAW_PARTIALCSUM 2 << 0 +#ifdef __sun +/* platform does not supply AF_LINK with getifaddrs. */ +struct ifaddrs; +int if_getifaddrs(struct ifaddrs **); +#else +#define GETIFADDRS_AFLINK +#endif + int if_setflag(struct interface *ifp, short flag); #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING)) struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);