Author: brooks
Date: Thu Apr  5 22:14:55 2018
New Revision: 332088
URL: https://svnweb.freebsd.org/changeset/base/332088

Log:
  Add 32-bit compat for ioctls that take struct ifgroupreq.
  
  Use an accessor to access ifgr_group and ifgr_groups.
  
  Use an macro CASE_IOC_IFGROUPREQ(cmd) in place of case statements such
  as "case SIOCAIFGROUP:". This avoids poluting the switch statements
  with large numbers of #ifdefs.
  
  Reviewed by:  kib
  Obtained from:        CheriBSD
  MFC after:    1 week
  Sponsored by: DARPA, AFRL
  Differential Revision:        https://reviews.freebsd.org/D14960

Modified:
  head/sys/net/if.c
  head/sys/net/if.h

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c   Thu Apr  5 21:58:28 2018        (r332087)
+++ head/sys/net/if.c   Thu Apr  5 22:14:55 2018        (r332088)
@@ -142,8 +142,25 @@ struct ifreq32 {
 CTASSERT(sizeof(struct ifreq) == sizeof(struct ifreq32));
 CTASSERT(__offsetof(struct ifreq, ifr_ifru) ==
     __offsetof(struct ifreq32, ifr_ifru));
-#endif
 
+struct ifgroupreq32 {
+       char    ifgr_name[IFNAMSIZ];
+       u_int   ifgr_len;
+       union {
+               char            ifgru_group[IFNAMSIZ];
+               uint32_t        ifgru_groups;
+       } ifgr_ifgru;
+};
+#define        _CASE_IOC_IFGROUPREQ_32(cmd)                            \
+    case _IOC_NEWTYPE((cmd), struct ifgroupreq32):
+#else
+#define _CASE_IOC_IFGROUPREQ_32(cmd)
+#endif /* COMPAT_FREEBSD32 */
+
+#define CASE_IOC_IFGROUPREQ(cmd)       \
+    _CASE_IOC_IFGROUPREQ_32(cmd)       \
+    case (cmd)
+
 union ifreq_union {
        struct ifreq    ifr;
 #ifdef COMPAT_FREEBSD32
@@ -151,6 +168,13 @@ union ifreq_union {
 #endif
 };
 
+union ifgroupreq_union {
+       struct ifgroupreq ifgr;
+#ifdef COMPAT_FREEBSD32
+       struct ifgroupreq32 ifgr32;
+#endif
+};
+
 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
 
@@ -1500,17 +1524,42 @@ if_delgroups(struct ifnet *ifp)
        IFNET_WUNLOCK();
 }
 
+static char *
+ifgr_group_get(void *ifgrp)
+{
+       union ifgroupreq_union *ifgrup;
+
+       ifgrup = ifgrp;
+#ifdef COMPAT_FREEBSD32
+       if (SV_CURPROC_FLAG(SV_ILP32))
+               return (&ifgrup->ifgr32.ifgr_ifgru.ifgru_group[0]);
+#endif
+       return (&ifgrup->ifgr.ifgr_ifgru.ifgru_group[0]);
+}
+
+static struct ifg_req *
+ifgr_groups_get(void *ifgrp)
+{
+       union ifgroupreq_union *ifgrup;
+
+       ifgrup = ifgrp;
+#ifdef COMPAT_FREEBSD32
+       if (SV_CURPROC_FLAG(SV_ILP32))
+               return ((struct ifg_req *)(uintptr_t)
+                   ifgrup->ifgr32.ifgr_ifgru.ifgru_groups);
+#endif
+       return (ifgrup->ifgr.ifgr_ifgru.ifgru_groups);
+}
+
 /*
- * Stores all groups from an interface in memory pointed
- * to by data
+ * Stores all groups from an interface in memory pointed to by ifgr.
  */
 static int
-if_getgroup(struct ifgroupreq *data, struct ifnet *ifp)
+if_getgroup(struct ifgroupreq *ifgr, struct ifnet *ifp)
 {
        int                      len, error;
        struct ifg_list         *ifgl;
        struct ifg_req           ifgrq, *ifgp;
-       struct ifgroupreq       *ifgr = data;
 
        if (ifgr->ifgr_len == 0) {
                IF_ADDR_RLOCK(ifp);
@@ -1521,7 +1570,7 @@ if_getgroup(struct ifgroupreq *data, struct ifnet *ifp
        }
 
        len = ifgr->ifgr_len;
-       ifgp = ifgr->ifgr_groups;
+       ifgp = ifgr_groups_get(ifgr);
        /* XXX: wire */
        IF_ADDR_RLOCK(ifp);
        TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
@@ -1545,12 +1594,11 @@ if_getgroup(struct ifgroupreq *data, struct ifnet *ifp
 }
 
 /*
- * Stores all members of a group in memory pointed to by data
+ * Stores all members of a group in memory pointed to by igfr
  */
 static int
-if_getgroupmembers(struct ifgroupreq *data)
+if_getgroupmembers(struct ifgroupreq *ifgr)
 {
-       struct ifgroupreq       *ifgr = data;
        struct ifg_group        *ifg;
        struct ifg_member       *ifgm;
        struct ifg_req           ifgrq, *ifgp;
@@ -1573,7 +1621,7 @@ if_getgroupmembers(struct ifgroupreq *data)
        }
 
        len = ifgr->ifgr_len;
-       ifgp = ifgr->ifgr_groups;
+       ifgp = ifgr_groups_get(ifgr);
        TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
                if (len < sizeof(ifgrq)) {
                        IFNET_RUNLOCK();
@@ -2803,34 +2851,28 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data,
                error = if_gethwaddr(ifp, ifr);
                break;
 
-       case SIOCAIFGROUP:
-       {
-               struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
-
+       CASE_IOC_IFGROUPREQ(SIOCAIFGROUP):
                error = priv_check(td, PRIV_NET_ADDIFGROUP);
                if (error)
                        return (error);
-               if ((error = if_addgroup(ifp, ifgr->ifgr_group)))
+               if ((error = if_addgroup(ifp,
+                   ifgr_group_get((struct ifgroupreq *)data))))
                        return (error);
                break;
-       }
 
-       case SIOCGIFGROUP:
-               if ((error = if_getgroup((struct ifgroupreq *)ifr, ifp)))
+       CASE_IOC_IFGROUPREQ(SIOCGIFGROUP):
+               if ((error = if_getgroup((struct ifgroupreq *)data, ifp)))
                        return (error);
                break;
 
-       case SIOCDIFGROUP:
-       {
-               struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
-
+       CASE_IOC_IFGROUPREQ(SIOCDIFGROUP):
                error = priv_check(td, PRIV_NET_DELIFGROUP);
                if (error)
                        return (error);
-               if ((error = if_delgroup(ifp, ifgr->ifgr_group)))
+               if ((error = if_delgroup(ifp,
+                   ifgr_group_get((struct ifgroupreq *)data))))
                        return (error);
                break;
-       }
 
        default:
                error = ENOIOCTL;
@@ -2932,7 +2974,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, s
                error = if_clone_list((struct if_clonereq *)data);
                CURVNET_RESTORE();
                return (error);
-       case SIOCGIFGMEMB:
+       CASE_IOC_IFGROUPREQ(SIOCGIFGMEMB):
                error = if_getgroupmembers((struct ifgroupreq *)data);
                CURVNET_RESTORE();
                return (error);

Modified: head/sys/net/if.h
==============================================================================
--- head/sys/net/if.h   Thu Apr  5 21:58:28 2018        (r332087)
+++ head/sys/net/if.h   Thu Apr  5 22:14:55 2018        (r332088)
@@ -517,8 +517,10 @@ struct ifgroupreq {
                char    ifgru_group[IFNAMSIZ];
                struct  ifg_req *ifgru_groups;
        } ifgr_ifgru;
+#ifndef _KERNEL
 #define ifgr_group     ifgr_ifgru.ifgru_group
 #define ifgr_groups    ifgr_ifgru.ifgru_groups
+#endif
 };
 
 /*
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to