From: Roy Marples Date: Sun, 14 Apr 2019 09:54:16 +0000 (+0300) Subject: sun: Fix carrier detection, MTU detection and plumbing X-Git-Tag: v7.2.0~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8fd49722375c32af29a384a0fe76d010b20adb4d;p=thirdparty%2Fdhcpcd.git sun: Fix carrier detection, MTU detection and plumbing dhcpcd no longer needs ifconfig to do the initial plumbing. --- diff --git a/configure b/configure index d0a80ba2..570e65f2 100755 --- a/configure +++ b/configure @@ -454,7 +454,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 + echo "LDADD+= -ldlpi -lkstat" >>$CONFIG_MK ;; *) echo "DHCPCD_SRCS+= if-bsd.c" >>$CONFIG_MK diff --git a/src/if-sun.c b/src/if-sun.c index 0cf7b1e5..942b2832 100644 --- a/src/if-sun.c +++ b/src/if-sun.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,7 @@ #include #include +#include #include #include #include @@ -162,6 +164,63 @@ if_closesockets_os(struct dhcpcd_ctx *ctx) free(ctx->priv); } +int +if_carrier_os(struct interface *ifp) +{ + kstat_ctl_t *kcp; + kstat_t *ksp; + kstat_named_t *knp; + link_state_t linkstate; + + kcp = kstat_open(); + if (kcp == NULL) + goto err; + ksp = kstat_lookup(kcp, UNCONST("link"), 0, ifp->name); + if (ksp == NULL) + goto err; + if (kstat_read(kcp, ksp, NULL) == -1) + goto err; + knp = kstat_data_lookup(ksp, UNCONST("link_state")); + if (knp == NULL) + goto err; + if (knp->data_type != KSTAT_DATA_UINT32) + goto err; + linkstate = (link_state_t)knp->value.ui32; + kstat_close(kcp); + + switch (linkstate) { + case LINK_STATE_UP: + ifp->flags |= IFF_UP; + return LINK_UP; + case LINK_STATE_DOWN: + return LINK_DOWN; + default: + return LINK_UNKNOWN; + } + +err: + if (kcp != NULL) + kstat_close(kcp); + return LINK_UNKNOWN; +} + +int +if_mtu_os(const struct interface *ifp) +{ + dlpi_handle_t dh; + dlpi_info_t dlinfo; + int mtu; + + if (dlpi_open(ifp->name, &dh, 0) != DLPI_SUCCESS) + return -1; + if (dlpi_info(dh, &dlinfo, 0) == DLPI_SUCCESS) + mtu = dlinfo.di_max_sdu; + else + mtu = -1; + dlpi_close(dh); + return mtu; +} + int if_getssid(struct interface *ifp) { @@ -723,15 +782,18 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) { struct interface *ifp; int state; + unsigned int flags; if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL) return; - if (ifm->ifm_flags & IFF_OFFLINE || !(ifm->ifm_flags & IFF_UP)) + flags = (unsigned int)ifm->ifm_flags; + if (ifm->ifm_flags & IFF_OFFLINE) state = LINK_DOWN; - else + else { state = LINK_UP; - dhcpcd_handlecarrier(ctx, state, - (unsigned int)ifm->ifm_flags, ifp->name); + flags |= IFF_UP; + } + dhcpcd_handlecarrier(ctx, state, flags, ifp->name); } static void @@ -819,6 +881,7 @@ if_addaddr(int fd, const char *ifname, if (ioctl(fd, SIOCSLIFFLAGS, &lifr) == -1) return -1; } + return 0; } @@ -847,15 +910,20 @@ if_plumblif(int cmd, const struct dhcpcd_ctx *ctx, int af, const char *ifname) static int if_plumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname) { - dlpi_handle_t dh; - int fd, af_fd, mux_fd, retval; + dlpi_handle_t dh, dh_arp = NULL; + int fd, af_fd, mux_fd, arp_fd = -1, mux_id, retval; + uint64_t flags; struct lifreq lifr; const char *udp_dev; + struct strioctl ioc; + struct if_spec spec; + + if (if_nametospec(ifname, &spec) == -1) + return -1; - memset(&lifr, 0, sizeof(lifr)); switch (af) { case AF_INET: - lifr.lifr_flags = IFF_IPV4; + flags = IFF_IPV4; af_fd = ctx->pf_inet_fd; udp_dev = UDP_DEV_NAME; break; @@ -864,7 +932,7 @@ if_plumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname) struct priv *priv; /* We will take care of setting the link local address. */ - lifr.lifr_flags = IFF_IPV6 | IFF_NOLINKLOCAL; + flags = IFF_IPV6 | IFF_NOLINKLOCAL; priv = (struct priv *)ctx->priv; af_fd = priv->pf_inet6_fd; udp_dev = UDP6_DEV_NAME; @@ -885,13 +953,17 @@ if_plumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname) mux_fd = -1; if (ioctl(fd, I_PUSH, IP_MOD_NAME) == -1) goto out; + memset(&lifr, 0, sizeof(lifr)); strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name)); + lifr.lifr_ppa = spec.ppa; + lifr.lifr_flags = flags; if (ioctl(fd, SIOCSLIFNAME, &lifr) == -1) goto out; /* Get full flags. */ if (ioctl(af_fd, SIOCGLIFFLAGS, &lifr) == -1) goto out; + flags = lifr.lifr_flags; /* Open UDP as a multiplexor to PLINK the interface stream. * UDP is used because STREAMS will not let you PLINK a driver @@ -903,20 +975,50 @@ if_plumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname) ; if (errno != EINVAL) goto out; + if(ioctl(mux_fd, I_PUSH, ARP_MOD_NAME) == -1) + goto out; - if (lifr.lifr_flags & IFF_IPV4 && !(lifr.lifr_flags & IFF_NOARP)) { - if (ioctl(mux_fd, I_PUSH, ARP_MOD_NAME) == -1) + if (flags & (IFF_NOARP | IFF_IPV6)) { + /* PLINK the interface stream so it persists. */ + if (ioctl(mux_fd, I_PLINK, fd) == -1) goto out; + goto done; } + if (dlpi_open(ifname, &dh_arp, DLPI_NOATTACH) != DLPI_SUCCESS) + goto out; + arp_fd = dlpi_fd(dh_arp); + if (ioctl(arp_fd, I_PUSH, ARP_MOD_NAME) == -1) + goto out; + + memset(&lifr, 0, sizeof(lifr)); + strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name)); + lifr.lifr_ppa = spec.ppa; + lifr.lifr_flags = flags; + memset(&ioc, 0, sizeof(ioc)); + ioc.ic_cmd = SIOCSLIFNAME; + ioc.ic_dp = (char *)&lifr; + ioc.ic_len = sizeof(lifr); + if (ioctl(arp_fd, I_STR, &ioc) == -1) + goto out; + /* PLINK the interface stream so it persists. */ - if (ioctl(mux_fd, I_PLINK, fd) == -1) + mux_id = ioctl(mux_fd, I_PLINK, fd); + if (mux_id == -1) goto out; + if (ioctl(mux_fd, I_PLINK, arp_fd) == -1) { + ioctl(mux_fd, I_PUNLINK, mux_id); + goto out; + } +done: + logerrx("plumb %d %d %d", mux_fd, fd, arp_fd); retval = 0; out: dlpi_close(dh); + if (dh_arp != NULL) + dlpi_close(dh_arp); if (mux_fd != -1) close(mux_fd); return retval; diff --git a/src/if.c b/src/if.c index 95067c77..783a92bb 100644 --- a/src/if.c +++ b/src/if.c @@ -136,9 +136,15 @@ if_carrier(struct interface *ifp) memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); - if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1) + r = ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr); + if (r != -1) + ifp->flags = (unsigned int)ifr.ifr_flags; + +#ifdef __sun + return if_carrier_os(ifp); +#else + if (r == -1) return LINK_UNKNOWN; - ifp->flags = (unsigned int)ifr.ifr_flags; #ifdef SIOCGIFMEDIA memset(&ifmr, 0, sizeof(ifmr)); @@ -155,6 +161,7 @@ if_carrier(struct interface *ifp) #else r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN; #endif +#endif /* __sun */ return r; } @@ -711,6 +718,11 @@ if_domtu(const struct interface *ifp, short int mtu) int r; struct ifreq ifr; +#ifdef __sun + if (mtu == 0) + return if_mtu_os(ifp); +#endif + memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); ifr.ifr_mtu = mtu; diff --git a/src/if.h b/src/if.h index 2f20764c..c8e406da 100644 --- a/src/if.h +++ b/src/if.h @@ -129,6 +129,9 @@ int if_domtu(const struct interface *, short int); #define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu)) int if_carrier(struct interface *); +int if_carrier_os(struct interface *); +int if_mtu_os(const struct interface *); + /* * Helper to decode an interface name of bge0:1 to * devname = bge0, drvname = bge0, ppa = 0, lun = 1.