Author: bz
Date: Sat Feb 11 06:02:16 2012
New Revision: 231505
URL: http://svn.freebsd.org/changeset/base/231505

Log:
  Introduce a new NET_RT_IFLISTL API to query the address list.  It works
  on extended and extensible structs if_msghdrl and ifa_msghdrl.  This
  will allow us to extend both the msghdrl structs and eventually if_data
  in the future without breaking the ABI.
  
  Bump __FreeBSD_version to allow ports to more easily detect the new API.
  
  Reviewed by:  glebius, brooks
  MFC after:    3 days

Modified:
  head/lib/libc/gen/sysctl.3
  head/sys/net/if.h
  head/sys/net/rtsock.c
  head/sys/sys/param.h
  head/sys/sys/socket.h

Modified: head/lib/libc/gen/sysctl.3
==============================================================================
--- head/lib/libc/gen/sysctl.3  Sat Feb 11 05:59:54 2012        (r231504)
+++ head/lib/libc/gen/sysctl.3  Sat Feb 11 06:02:16 2012        (r231505)
@@ -28,7 +28,7 @@
 .\"    @(#)sysctl.3    8.4 (Berkeley) 5/9/95
 .\" $FreeBSD$
 .\"
-.Dd April 25, 2010
+.Dd February 11, 2012
 .Dt SYSCTL 3
 .Os
 .Sh NAME
@@ -554,6 +554,7 @@ The fifth and sixth level names are as f
 .It "NET_RT_DUMP       None"
 .It "NET_RT_IFLIST     0 or if_index"
 .It "NET_RT_IFMALIST   0 or if_index"
+.It "NET_RT_IFLISTL    0 or if_index"
 .El
 .Pp
 The
@@ -561,6 +562,19 @@ The
 name returns information about multicast group memberships on all interfaces
 if 0 is specified, or for the interface specified by
 .Va if_index .
+.Pp
+The
+.Dv NET_RT_IFLISTL
+is like
+.Dv NET_RT_IFLIST ,
+just returning message header structs with additional fields allowing the
+interface to be extended without breaking binary compatibility.
+The
+.Dv NET_RT_IFLISTL
+uses 'l' versions of the message header structures:
+.Va struct if_msghdrl
+and
+.Va struct ifa_msghdrl .
 .It Li PF_INET
 Get or set various global information about the IPv4
 (Internet Protocol version 4).

Modified: head/sys/net/if.h
==============================================================================
--- head/sys/net/if.h   Sat Feb 11 05:59:54 2012        (r231504)
+++ head/sys/net/if.h   Sat Feb 11 06:02:16 2012        (r231505)
@@ -244,6 +244,7 @@ struct if_data {
 /*
  * Message format for use in obtaining information about interfaces
  * from getkerninfo and the routing socket
+ * For the new, extensible interface see struct if_msghdrl below.
  */
 struct if_msghdr {
        u_short ifm_msglen;     /* to skip over non-understood messages */
@@ -256,8 +257,34 @@ struct if_msghdr {
 };
 
 /*
+ * The 'l' version shall be used by new interfaces, like NET_RT_IFLISTL.  It is
+ * extensible after ifm_data_off or within ifm_data.  Both the if_msghdr and
+ * if_data now have a member field detailing the struct length in addition to
+ * the routing message length.  Macros are provided to find the start of
+ * ifm_data and the start of the socket address strucutres immediately 
following
+ * struct if_msghdrl given a pointer to struct if_msghdrl.
+ */
+#define        IF_MSGHDRL_IFM_DATA(_l) \
+    (struct if_data *)((char *)(_l) + (_l)->ifm_data_off)
+#define        IF_MSGHDRL_RTA(_l) \
+    (void *)((uintptr_t)(_l) + (_l)->ifm_len)
+struct if_msghdrl {
+       u_short ifm_msglen;     /* to skip over non-understood messages */
+       u_char  ifm_version;    /* future binary compatibility */
+       u_char  ifm_type;       /* message type */
+       int     ifm_addrs;      /* like rtm_addrs */
+       int     ifm_flags;      /* value of if_flags */
+       u_short ifm_index;      /* index for associated ifp */
+       u_short _ifm_spare1;    /* spare space to grow if_index, see if_var.h */
+       u_short ifm_len;        /* length of if_msghdrl incl. if_data */
+       u_short ifm_data_off;   /* offset of if_data from beginning */
+       struct  if_data ifm_data;/* statistics and other data about if */
+};
+
+/*
  * Message format for use in obtaining information about interface addresses
  * from getkerninfo and the routing socket
+ * For the new, extensible interface see struct ifa_msghdrl below.
  */
 struct ifa_msghdr {
        u_short ifam_msglen;    /* to skip over non-understood messages */
@@ -270,6 +297,33 @@ struct ifa_msghdr {
 };
 
 /*
+ * The 'l' version shall be used by new interfaces, like NET_RT_IFLISTL.  It is
+ * extensible after ifam_metric or within ifam_data.  Both the ifa_msghdrl and
+ * if_data now have a member field detailing the struct length in addition to
+ * the routing message length.  Macros are provided to find the start of
+ * ifm_data and the start of the socket address strucutres immediately 
following
+ * struct ifa_msghdrl given a pointer to struct ifa_msghdrl.
+ */
+#define        IFA_MSGHDRL_IFAM_DATA(_l) \
+    (struct if_data *)((char *)(_l) + (_l)->ifam_data_off)
+#define        IFA_MSGHDRL_RTA(_l) \
+    (void *)((uintptr_t)(_l) + (_l)->ifam_len)
+struct ifa_msghdrl {
+       u_short ifam_msglen;    /* to skip over non-understood messages */
+       u_char  ifam_version;   /* future binary compatibility */
+       u_char  ifam_type;      /* message type */
+       int     ifam_addrs;     /* like rtm_addrs */
+       int     ifam_flags;     /* value of ifa_flags */
+       u_short ifam_index;     /* index for associated ifp */
+       u_short _ifam_spare1;   /* spare space to grow if_index, see if_var.h */
+       u_short ifam_len;       /* length of ifa_msghdrl incl. if_data */
+       u_short ifam_data_off;  /* offset of if_data from beginning */
+       int     ifam_metric;    /* value of ifa_metric */
+       struct  if_data ifam_data;/* statistics and other data about if or
+                                * address */
+};
+
+/*
  * Message format for use in obtaining information about multicast addresses
  * from the routing socket
  */

Modified: head/sys/net/rtsock.c
==============================================================================
--- head/sys/net/rtsock.c       Sat Feb 11 05:59:54 2012        (r231504)
+++ head/sys/net/rtsock.c       Sat Feb 11 06:02:16 2012        (r231505)
@@ -115,7 +115,34 @@ struct if_msghdr32 {
        uint16_t ifm_index;
        struct  if_data32 ifm_data;
 };
-#endif
+
+struct if_msghdrl32 {
+       uint16_t ifm_msglen;
+       uint8_t ifm_version;
+       uint8_t ifm_type;
+       int32_t ifm_addrs;
+       int32_t ifm_flags;
+       uint16_t ifm_index;
+       uint16_t _ifm_spare1;
+       uint16_t ifm_len;
+       uint16_t ifm_data_off;
+       struct  if_data32 ifm_data;
+};
+
+struct ifa_msghdrl32 {
+       uint16_t ifam_msglen;
+       uint8_t ifam_version;
+       uint8_t ifam_type;
+       int32_t ifam_addrs;
+       int32_t ifam_flags;
+       uint16_t ifam_index;
+       uint16_t _ifam_spare1;
+       uint16_t ifam_len;
+       uint16_t ifam_data_off;
+       int32_t ifam_metric;
+       struct  if_data32 ifam_data;
+};
+#endif /* COMPAT_FREEBSD32 */
 
 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
 
@@ -1014,6 +1041,9 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, str
        return (0);
 }
 
+/*
+ * Used by the routing socket.
+ */
 static struct mbuf *
 rt_msg1(int type, struct rt_addrinfo *rtinfo)
 {
@@ -1081,6 +1111,9 @@ rt_msg1(int type, struct rt_addrinfo *rt
        return (m);
 }
 
+/*
+ * Used by the sysctl code and routing socket.
+ */
 static int
 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
 {
@@ -1094,17 +1127,31 @@ again:
 
        case RTM_DELADDR:
        case RTM_NEWADDR:
-               len = sizeof(struct ifa_msghdr);
+               if (w != NULL && w->w_op == NET_RT_IFLISTL) {
+#ifdef COMPAT_FREEBSD32
+                       if (w->w_req->flags & SCTL_MASK32)
+                               len = sizeof(struct ifa_msghdrl32);
+                       else
+#endif
+                               len = sizeof(struct ifa_msghdrl);
+               } else
+                       len = sizeof(struct ifa_msghdr);
                break;
 
        case RTM_IFINFO:
 #ifdef COMPAT_FREEBSD32
                if (w != NULL && w->w_req->flags & SCTL_MASK32) {
-                       len = sizeof(struct if_msghdr32);
+                       if (w->w_op == NET_RT_IFLISTL)
+                               len = sizeof(struct if_msghdrl32);
+                       else
+                               len = sizeof(struct if_msghdr32);
                        break;
                }
 #endif
-               len = sizeof(struct if_msghdr);
+               if (w != NULL && w->w_op == NET_RT_IFLISTL)
+                       len = sizeof(struct if_msghdrl);
+               else
+                       len = sizeof(struct if_msghdr);
                break;
 
        case RTM_NEWMADDR:
@@ -1535,6 +1582,147 @@ copy_ifdata32(struct if_data *src, struc
 #endif
 
 static int
+sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info,
+    struct walkarg *w, int len)
+{
+       struct if_msghdrl *ifm;
+
+#ifdef COMPAT_FREEBSD32
+       if (w->w_req->flags & SCTL_MASK32) {
+               struct if_msghdrl32 *ifm32;
+
+               ifm32 = (struct if_msghdrl32 *)w->w_tmem;
+               ifm32->ifm_addrs = info->rti_addrs;
+               ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+               ifm32->ifm_index = ifp->if_index;
+               ifm32->_ifm_spare1 = 0;
+               ifm32->ifm_len = sizeof(*ifm32);
+               ifm32->ifm_data_off = offsetof(struct if_msghdrl32, ifm_data);
+
+               copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
+               /* Fixup if_data carp(4) vhid. */
+               if (carp_get_vhid_p != NULL)
+                       ifm32->ifm_data.ifi_vhid =
+                           (*carp_get_vhid_p)(ifp->if_addr);
+
+               return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len));
+       }
+#endif
+       ifm = (struct if_msghdrl *)w->w_tmem;
+       ifm->ifm_addrs = info->rti_addrs;
+       ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+       ifm->ifm_index = ifp->if_index;
+       ifm->_ifm_spare1 = 0;
+       ifm->ifm_len = sizeof(*ifm);
+       ifm->ifm_data_off = offsetof(struct if_msghdrl, ifm_data);
+
+       ifm->ifm_data = ifp->if_data;
+       /* Fixup if_data carp(4) vhid. */
+       if (carp_get_vhid_p != NULL)
+               ifm->ifm_data.ifi_vhid = (*carp_get_vhid_p)(ifp->if_addr);
+
+       return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
+}
+
+static int
+sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info,
+    struct walkarg *w, int len)
+{
+       struct if_msghdr *ifm;
+
+#ifdef COMPAT_FREEBSD32
+       if (w->w_req->flags & SCTL_MASK32) {
+               struct if_msghdr32 *ifm32;
+
+               ifm32 = (struct if_msghdr32 *)w->w_tmem;
+               ifm32->ifm_addrs = info->rti_addrs;
+               ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+               ifm32->ifm_index = ifp->if_index;
+
+               copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
+               /* Fixup if_data carp(4) vhid. */
+               if (carp_get_vhid_p != NULL)
+                       ifm32->ifm_data.ifi_vhid =
+                           (*carp_get_vhid_p)(ifp->if_addr);
+
+               return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len));
+       }
+#endif
+       ifm = (struct if_msghdr *)w->w_tmem;
+       ifm->ifm_addrs = info->rti_addrs;
+       ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+       ifm->ifm_index = ifp->if_index;
+
+       ifm->ifm_data = ifp->if_data;
+       /* Fixup if_data carp(4) vhid. */
+       if (carp_get_vhid_p != NULL)
+               ifm->ifm_data.ifi_vhid = (*carp_get_vhid_p)(ifp->if_addr);
+
+       return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
+}
+
+static int
+sysctl_iflist_ifaml(struct ifaddr *ifa, struct rt_addrinfo *info,
+    struct walkarg *w, int len)
+{
+       struct ifa_msghdrl *ifam;
+
+#ifdef COMPAT_FREEBSD32
+       if (w->w_req->flags & SCTL_MASK32) {
+               struct ifa_msghdrl32 *ifam32;
+
+               ifam32 = (struct ifa_msghdrl32 *)w->w_tmem;
+               ifam32->ifam_addrs = info->rti_addrs;
+               ifam32->ifam_flags = ifa->ifa_flags;
+               ifam32->ifam_index = ifa->ifa_ifp->if_index;
+               ifam32->_ifam_spare1 = 0;
+               ifam32->ifam_len = sizeof(*ifam32);
+               ifam32->ifam_data_off =
+                   offsetof(struct ifa_msghdrl32, ifam_data);
+               ifam32->ifam_metric = ifa->ifa_metric;
+
+               copy_ifdata32(&ifa->ifa_ifp->if_data, &ifam32->ifam_data);
+               /* Fixup if_data carp(4) vhid. */
+               if (carp_get_vhid_p != NULL)
+                       ifam32->ifam_data.ifi_vhid = (*carp_get_vhid_p)(ifa);
+
+               return (SYSCTL_OUT(w->w_req, (caddr_t)ifam32, len));
+       }
+#endif
+
+       ifam = (struct ifa_msghdrl *)w->w_tmem;
+       ifam->ifam_addrs = info->rti_addrs;
+       ifam->ifam_flags = ifa->ifa_flags;
+       ifam->ifam_index = ifa->ifa_ifp->if_index;
+       ifam->_ifam_spare1 = 0;
+       ifam->ifam_len = sizeof(*ifam);
+       ifam->ifam_data_off = offsetof(struct ifa_msghdrl, ifam_data);
+       ifam->ifam_metric = ifa->ifa_metric;
+
+       ifam->ifam_data = ifa->if_data;
+       /* Fixup if_data carp(4) vhid. */
+       if (carp_get_vhid_p != NULL)
+               ifam->ifam_data.ifi_vhid = (*carp_get_vhid_p)(ifa);
+
+       return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
+}
+
+static int
+sysctl_iflist_ifam(struct ifaddr *ifa, struct rt_addrinfo *info,
+    struct walkarg *w, int len)
+{
+       struct ifa_msghdr *ifam;
+
+       ifam = (struct ifa_msghdr *)w->w_tmem;
+       ifam->ifam_addrs = info->rti_addrs;
+       ifam->ifam_flags = ifa->ifa_flags;
+       ifam->ifam_index = ifa->ifa_ifp->if_index;
+       ifam->ifam_metric = ifa->ifa_metric;
+
+       return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
+}
+
+static int
 sysctl_iflist(int af, struct walkarg *w)
 {
        struct ifnet *ifp;
@@ -1553,38 +1741,10 @@ sysctl_iflist(int af, struct walkarg *w)
                len = rt_msg2(RTM_IFINFO, &info, NULL, w);
                info.rti_info[RTAX_IFP] = NULL;
                if (w->w_req && w->w_tmem) {
-                       struct if_msghdr *ifm;
-
-#ifdef COMPAT_FREEBSD32
-                       if (w->w_req->flags & SCTL_MASK32) {
-                               struct if_msghdr32 *ifm32;
-
-                               ifm32 = (struct if_msghdr32 *)w->w_tmem;
-                               ifm32->ifm_index = ifp->if_index;
-                               ifm32->ifm_flags = ifp->if_flags |
-                                   ifp->if_drv_flags;
-                               copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
-                               if (carp_get_vhid_p != NULL)
-                                       ifm32->ifm_data.ifi_vhid =
-                                           (*carp_get_vhid_p)(ifa);
-                               ifm32->ifm_addrs = info.rti_addrs;
-                               error = SYSCTL_OUT(w->w_req, (caddr_t)ifm32,
-                                   len);
-                               goto sysctl_out;
-                       }
-#endif
-                       ifm = (struct if_msghdr *)w->w_tmem;
-                       ifm->ifm_index = ifp->if_index;
-                       ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
-                       ifm->ifm_data = ifp->if_data;
-                       if (carp_get_vhid_p != NULL)
-                               ifm->ifm_data.ifi_vhid =
-                                   (*carp_get_vhid_p)(ifa);
-                       ifm->ifm_addrs = info.rti_addrs;
-                       error = SYSCTL_OUT(w->w_req, (caddr_t)ifm, len);
-#ifdef COMPAT_FREEBSD32
-               sysctl_out:
-#endif
+                       if (w->w_op == NET_RT_IFLISTL)
+                               error = sysctl_iflist_ifml(ifp, &info, w, len);
+                       else
+                               error = sysctl_iflist_ifm(ifp, &info, w, len);
                        if (error)
                                goto done;
                }
@@ -1599,14 +1759,12 @@ sysctl_iflist(int af, struct walkarg *w)
                        info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
                        len = rt_msg2(RTM_NEWADDR, &info, NULL, w);
                        if (w->w_req && w->w_tmem) {
-                               struct ifa_msghdr *ifam;
-
-                               ifam = (struct ifa_msghdr *)w->w_tmem;
-                               ifam->ifam_index = ifa->ifa_ifp->if_index;
-                               ifam->ifam_flags = ifa->ifa_flags;
-                               ifam->ifam_metric = ifa->ifa_metric;
-                               ifam->ifam_addrs = info.rti_addrs;
-                               error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+                               if (w->w_op == NET_RT_IFLISTL)
+                                       error = sysctl_iflist_ifaml(ifa, &info,
+                                           w, len);
+                               else
+                                       error = sysctl_iflist_ifam(ifa, &info,
+                                           w, len);
                                if (error)
                                        goto done;
                        }
@@ -1736,6 +1894,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
                break;
 
        case NET_RT_IFLIST:
+       case NET_RT_IFLISTL:
                error = sysctl_iflist(af, &w);
                break;
 

Modified: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h        Sat Feb 11 05:59:54 2012        (r231504)
+++ head/sys/sys/param.h        Sat Feb 11 06:02:16 2012        (r231505)
@@ -58,7 +58,7 @@
  *             in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1000007      /* Master, propagated to newvers */
+#define __FreeBSD_version 1000008      /* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

Modified: head/sys/sys/socket.h
==============================================================================
--- head/sys/sys/socket.h       Sat Feb 11 05:59:54 2012        (r231504)
+++ head/sys/sys/socket.h       Sat Feb 11 06:02:16 2012        (r231505)
@@ -396,7 +396,9 @@ struct sockproto {
 #define NET_RT_FLAGS   2               /* by flags, e.g. RESOLVING */
 #define NET_RT_IFLIST  3               /* survey interface list */
 #define        NET_RT_IFMALIST 4               /* return multicast address 
list */
-#define        NET_RT_MAXID    5
+#define        NET_RT_IFLISTL  5               /* Survey interface list, using 
'l'en
+                                        * versions of msghdr structs. */
+#define        NET_RT_MAXID    6
 
 #define CTL_NET_RT_NAMES { \
        { 0, 0 }, \
@@ -404,6 +406,7 @@ struct sockproto {
        { "flags", CTLTYPE_STRUCT }, \
        { "iflist", CTLTYPE_STRUCT }, \
        { "ifmalist", CTLTYPE_STRUCT }, \
+       { "iflist2", CTLTYPE_STRUCT }, \
 }
 #endif /* __BSD_VISIBLE */
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to