Mercurial > hg > dhcpcd
changeset 4433:4262dbc903e8 draft
sun: Fix carrier detection, MTU detection and plumbing
dhcpcd no longer needs ifconfig to do the initial plumbing.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Sun, 14 Apr 2019 12:54:16 +0300 |
| parents | 693209ca41db |
| children | 7d588b6cb52d |
| files | configure src/if-sun.c src/if.c src/if.h |
| diffstat | 4 files changed, 133 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/configure Sun Apr 14 12:53:25 2019 +0300 +++ b/configure Sun Apr 14 12:54:16 2019 +0300 @@ -454,7 +454,7 @@ 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
--- a/src/if-sun.c Sun Apr 14 12:53:25 2019 +0300 +++ b/src/if-sun.c Sun Apr 14 12:54:16 2019 +0300 @@ -30,6 +30,7 @@ #include <fcntl.h> #include <ifaddrs.h> #include <libdlpi.h> +#include <kstat.h> #include <stddef.h> #include <stdlib.h> #include <stropts.h> @@ -45,6 +46,7 @@ #include <netinet/udp.h> #include <sys/ioctl.h> +#include <sys/mac.h> #include <sys/pfmod.h> #include <sys/tihdr.h> #include <sys/utsname.h> @@ -163,6 +165,63 @@ } 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 @@ { 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 (ioctl(fd, SIOCSLIFFLAGS, &lifr) == -1) return -1; } + return 0; } @@ -847,15 +910,20 @@ 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; - memset(&lifr, 0, sizeof(lifr)); + if (if_nametospec(ifname, &spec) == -1) + return -1; + 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 @@ 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 @@ 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 (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; } - /* PLINK the interface stream so it persists. */ - if (ioctl(mux_fd, I_PLINK, fd) == -1) + 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. */ + 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;
--- a/src/if.c Sun Apr 14 12:53:25 2019 +0300 +++ b/src/if.c Sun Apr 14 12:54:16 2019 +0300 @@ -136,9 +136,15 @@ 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 @@ #else r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN; #endif +#endif /* __sun */ return r; } @@ -711,6 +718,11 @@ 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;
--- a/src/if.h Sun Apr 14 12:53:25 2019 +0300 +++ b/src/if.h Sun Apr 14 12:54:16 2019 +0300 @@ -129,6 +129,9 @@ #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.
