]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
sun: Fix carrier detection, MTU detection and plumbing
authorRoy Marples <roy@marples.name>
Sun, 14 Apr 2019 09:54:16 +0000 (12:54 +0300)
committerRoy Marples <roy@marples.name>
Sun, 14 Apr 2019 09:54:16 +0000 (12:54 +0300)
dhcpcd no longer needs ifconfig to do the initial plumbing.

configure
src/if-sun.c
src/if.c
src/if.h

index d0a80ba22f2604520adac58073192bb3eb8dcfff..570e65f214f3d585289d95383b612614d0ae0e7f 100755 (executable)
--- 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
index 0cf7b1e5ca94150bacf6feea2bf65ec8fb66abdc..942b283237f74f7e7acdc8e0d19eca5a1041d2b0 100644 (file)
@@ -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>
@@ -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;
index 95067c773eeac4371894f60ea7b1dd5b67013e4e..783a92bb0014d13f1a458de961823f7d0bfb6793 100644 (file)
--- 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;
index 2f20764c01f401830c9565f7e28fe37d4aec0dc0..c8e406da35455360a56563902d92b12d81b84657 100644 (file)
--- 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.