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
This commit is contained in:
parent
f55d6eed8c
commit
d05091db1d
@ -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 follows:
|
||||
.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).
|
||||
|
54
sys/net/if.h
54
sys/net/if.h
@ -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 */
|
||||
@ -255,9 +256,35 @@ struct if_msghdr {
|
||||
struct if_data ifm_data;/* statistics and other data about if */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
@ -269,6 +296,33 @@ struct ifa_msghdr {
|
||||
int ifam_metric; /* value of ifa_metric */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
247
sys/net/rtsock.c
247
sys/net/rtsock.c
@ -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, struct rt_addrinfo *rtinfo)
|
||||
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 *rtinfo)
|
||||
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 @@ rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
|
||||
|
||||
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:
|
||||
@ -1534,6 +1581,147 @@ copy_ifdata32(struct if_data *src, struct if_data32 *dst)
|
||||
}
|
||||
#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)
|
||||
{
|
||||
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user