From: Roy Marples Date: Thu, 12 May 2016 16:51:36 +0000 (+0000) Subject: Learn about routing tables on Solaris. X-Git-Tag: v6.11.1~56 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=88fe630a139e3875a99fa3f74d04b4e783e8285b;p=thirdparty%2Fdhcpcd.git Learn about routing tables on Solaris. --- diff --git a/if-sun.c b/if-sun.c index bef4f59a..b7c7a33c 100644 --- a/if-sun.c +++ b/if-sun.c @@ -26,15 +26,20 @@ */ #include +#include #include #include +#include #include #include #include +#include #include #include +#include + #include #include @@ -65,19 +70,23 @@ int if_opensockets_os(struct dhcpcd_ctx *ctx) { - return 0; + ctx->link_fd = socket(PF_ROUTE, + SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + return ctx->link_fd == -1 ? -1 : 0; } void if_closesockets_os(struct dhcpcd_ctx *ctx) { + UNUSED(ctx); } int if_getssid(struct interface *ifp) { + UNUSED(ifp); errno = ENOTSUP; return -1; } @@ -93,6 +102,7 @@ int if_managelink(struct dhcpcd_ctx *ctx) { + UNUSED(ctx); errno = ENOTSUP; return -1; } @@ -101,6 +111,8 @@ int if_machinearch(char *str, size_t len) { + UNUSED(str); + UNUSED(len); errno = ENOTSUP; return -1; } @@ -118,7 +130,7 @@ if_newaddr(const char *ifname, void *arg) dlpi_handle_t dh; dlpi_info_t dlinfo; uint8_t pa[DLPI_PHYSADDR_MAX]; - unsigned int pa_len; + size_t pa_len; struct sockaddr_dl *sdl; ifa = NULL; @@ -182,10 +194,8 @@ failed1: int if_getifaddrs(struct ifaddrs **ifap) { - struct linkwalk lw = { NULL, 0 }; - int error; + struct linkwalk lw = { NULL, 0 }; - error = 0; dlpi_walk(if_newaddr, &lw, 0); if (lw.lw_error != 0) { freeifaddrs(lw.lw_ifa); @@ -197,6 +207,105 @@ if_getifaddrs(struct ifaddrs **ifap) return 0; } +static void +if_octetstr(char *buf, const Octet_t *o, ssize_t len) +{ + int i; + char *p; + + p = buf; + for (i = 0; i < o->o_length; i++) { + if ((p + 1) - buf < len) + *p++ = o->o_bytes[i]; + } + *p = '\0'; +} + +static int +if_parsert(struct dhcpcd_ctx *ctx, unsigned int level, unsigned int name, + int (*walkrt)(struct dhcpcd_ctx *, char *, size_t)) +{ + int s, retval, code, flags; + uintptr_t buf[512 / sizeof(uintptr_t)]; + struct strbuf ctlbuf, databuf; + struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf; + struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf; + struct T_error_ack *tea = (struct T_error_ack *)buf; + struct opthdr *req; + + if ((s = open("/dev/arp", O_RDWR)) == -1) + return -1; + + tor->PRIM_type = T_SVR4_OPTMGMT_REQ; + tor->OPT_offset = sizeof (struct T_optmgmt_req); + tor->OPT_length = sizeof (struct opthdr); + tor->MGMT_flags = T_CURRENT; + + req = (struct opthdr *)&tor[1]; + req->level = EXPER_IP_AND_ALL_IRES; + req->name = 0; + req->len = 1; + + ctlbuf.buf = (char *)buf; + ctlbuf.len = tor->OPT_length + tor->OPT_offset; + if (putmsg(s, &ctlbuf, NULL, 0) == 1) { + close(s); + return -1; + } + + req = (struct opthdr *)&toa[1]; + ctlbuf.maxlen = sizeof(buf); + + retval = -1; + for (;;) { + flags = 0; + if ((code = getmsg(s, &ctlbuf, 0, &flags)) == -1) + break; + if (code == 0 && + toa->PRIM_type == T_OPTMGMT_ACK && + toa->MGMT_flags == T_SUCCESS && + (size_t)ctlbuf.len >= sizeof(struct T_optmgmt_ack)) + { + retval = 0; + break; + } + if (tea->PRIM_type == T_ERROR_ACK) { + errno = tea->TLI_error == TSYSERR ? + tea->UNIX_error : EPROTO; + break; + } + if (code != MOREDATA || + toa->PRIM_type != T_OPTMGMT_ACK || + toa->MGMT_flags != T_SUCCESS) + { + errno = ENOMSG; + break; + } + + databuf.maxlen = req->len; + if ((databuf.buf = malloc(databuf.maxlen)) == NULL) + break; + + flags = 0; + if (getmsg(s, NULL, &databuf, &flags) == -1) { + free(databuf.buf); + break; + } + + if (req->level == level && req->name == name) { + if (walkrt(ctx, databuf.buf, databuf.len) == -1) { + free(databuf.buf); + break; + } + } + + free(databuf.buf); + } + + close(s); + return retval; +} + #ifdef INET const char *if_pfname = "SunOS"; @@ -204,6 +313,8 @@ int if_openrawsocket(struct interface *ifp, uint16_t protocol) { + UNUSED(ifp); + UNUSED(protocol); errno = ENOTSUP; return -1; } @@ -213,6 +324,10 @@ if_sendrawpacket(const struct interface *ifp, uint16_t protocol, const void *data, size_t len) { + UNUSED(ifp); + UNUSED(protocol); + UNUSED(data); + UNUSED(len); errno = ENOTSUP; return -1; } @@ -222,16 +337,26 @@ if_readrawpacket(struct interface *ifp, uint16_t protocol, void *data, size_t len, int *flags) { + UNUSED(ifp); + UNUSED(protocol); + UNUSED(data); + UNUSED(len); + UNUSED(flags); errno = ENOTSUP; return -1; } int -if_address(const struct interface *iface, const struct in_addr *addr, +if_address(const struct interface *ifp, const struct in_addr *addr, const struct in_addr *net, const struct in_addr *bcast, int action) { + UNUSED(ifp); + UNUSED(addr); + UNUSED(net); + UNUSED(bcast); + UNUSED(action); errno = ENOTSUP; return -1; } @@ -240,6 +365,8 @@ int if_addrflags(const struct in_addr *addr, const struct interface *ifp) { + UNUSED(addr); + UNUSED(ifp); errno = ENOTSUP; return -1; } @@ -248,24 +375,72 @@ int if_route(unsigned char cmd, const struct rt *rt) { + UNUSED(cmd); + UNUSED(rt); errno = ENOTSUP; return -1; } +static int +if_walkrt(struct dhcpcd_ctx *ctx, char *data, size_t len) +{ + mib2_ipRouteEntry_t *re, *e; + struct rt rt; + char ifname[IF_NAMESIZE]; + + if (len % sizeof(*re) != 0) { + errno = EINVAL; + return -1; + } + + re = (mib2_ipRouteEntry_t *)data; + e = (mib2_ipRouteEntry_t *)(data + len); + do { + /* Skip route types we don't want. */ + switch (re->ipRouteInfo.re_ire_type) { + case IRE_IF_CLONE: + case IRE_BROADCAST: + case IRE_MULTICAST: + case IRE_NOROUTE: + case IRE_LOCAL: + continue; + default: + break; + } + memset(&rt, 0, sizeof(rt)); + rt.dest.s_addr = re->ipRouteDest; + rt.net.s_addr = re->ipRouteMask; + rt.gate.s_addr = re->ipRouteNextHop; + rt.flags = re->ipRouteInfo.re_flags; + rt.src.s_addr = re->ipRouteInfo.re_src_addr; + rt.mtu = re->ipRouteInfo.re_max_frag; + + if_octetstr(ifname, &re->ipRouteIfIndex, sizeof(ifname)); + rt.iface = if_find(ctx->ifaces, ifname); + if (rt.iface != NULL) + ipv4_handlert(ctx, RTM_ADD, &rt, 1); + else + printf ("XX %s\n", ifname); + } while (++re < e); + return 0; +} + int -if_initrt(struct interface *ifp) +if_initrt(struct dhcpcd_ctx *ctx) { - errno = ENOTSUP; - return -1; + ipv4_freerts(ctx->ipv4_kroutes); + return if_parsert(ctx, MIB2_IP,MIB2_IP_ROUTE, if_walkrt); } #endif #ifdef INET6 int -if_address6(const struct ipv6_addr *a, int action) +if_address6(const struct ipv6_addr *addr, int action) { + UNUSED(addr); + UNUSED(action); errno = ENOTSUP; return -1; } @@ -274,6 +449,8 @@ int if_addrflags6(const struct in6_addr *addr, const struct interface *ifp) { + UNUSED(addr); + UNUSED(ifp); errno = ENOTSUP; return -1; } @@ -282,6 +459,7 @@ int if_getlifetime6(struct ipv6_addr *addr) { + UNUSED(addr); errno = ENOTSUP; return -1; } @@ -290,23 +468,68 @@ int if_route6(unsigned char cmd, const struct rt6 *rt) { + UNUSED(cmd); + UNUSED(rt); errno = ENOTSUP; return -1; } +static int +if_walkrt6(struct dhcpcd_ctx *ctx, char *data, size_t len) +{ + mib2_ipv6RouteEntry_t *re, *e; + struct rt6 rt; + char ifname[IF_NAMESIZE]; + + if (len % sizeof(*re) != 0) { + errno = EINVAL; + return -1; + } + + re = (mib2_ipv6RouteEntry_t *)data; + e = (mib2_ipv6RouteEntry_t *)(data + len); + + do { + /* Skip route types we don't want. */ + switch (re->ipv6RouteInfo.re_ire_type) { + case IRE_IF_CLONE: + case IRE_BROADCAST: + case IRE_MULTICAST: + case IRE_NOROUTE: + case IRE_LOCAL: + continue; + default: + break; + } + memset(&rt, 0, sizeof(rt)); + rt.dest = re->ipv6RouteDest; + ipv6_mask(&rt.net, re->ipv6RoutePfxLength); + rt.gate = re->ipv6RouteNextHop; + rt.mtu = re->ipv6RouteInfo.re_max_frag; + + if_octetstr(ifname, &re->ipv6RouteIfIndex, sizeof(ifname)); + rt.iface = if_find(ctx->ifaces, ifname); + if (rt.iface != NULL) + ipv6_handlert(ctx, RTM_ADD, &rt); + else + printf ("XX %s\n", ifname); + } while (++re < e); + return 0; +} + int -if_initrt6(struct interface *ifp) +if_initrt6(struct dhcpcd_ctx *ctx) { - errno = ENOTSUP; - return -1; + ipv6_freerts(&ctx->ipv6->kroutes); + return if_parsert(ctx, MIB2_IP6, MIB2_IP6_ROUTE, if_walkrt6); } int -if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own) +if_checkipv6(__unused struct dhcpcd_ctx *ctx, + __unused const struct interface *ifp, int __unused own) { - errno = ENOTSUP; - return -1; + return 0; } #endif