IPv4 multicast: fix netstat -g

The vif structure includes fields at the end which are #ifdef KERNEL,
causing a mismatch between the structure sizes between kernel and
user level.  netstat -g failed with an ENOMEM on the sysctl to fetch
the vif table.  Change the vif sysctl code in ip_mroute to copy out
only the user-level-visible portion of each table entry.

Reviewed by:	bz, wma
Differential Revision: https://reviews.freebsd.org/D34627
This commit is contained in:
Mike Karels 2022-03-21 14:59:13 -05:00
parent 2cf1e120c6
commit 04cd74b4cd
2 changed files with 9 additions and 3 deletions

View File

@ -2727,18 +2727,23 @@ static SYSCTL_NODE(_net_inet_ip, OID_AUTO, mfctable,
static int
sysctl_viflist(SYSCTL_HANDLER_ARGS)
{
int error;
int error, i;
if (req->newptr)
return (EPERM);
if (V_viftable == NULL) /* XXX unlocked */
return (0);
error = sysctl_wire_old_buffer(req, sizeof(*V_viftable) * MAXVIFS);
error = sysctl_wire_old_buffer(req, MROUTE_VIF_SYSCTL_LEN * MAXVIFS);
if (error)
return (error);
MRW_RLOCK();
error = SYSCTL_OUT(req, V_viftable, sizeof(*V_viftable) * MAXVIFS);
/* Copy out user-visible portion of vif entry. */
for (i = 0; i < MAXVIFS; i++) {
error = SYSCTL_OUT(req, &V_viftable[i], MROUTE_VIF_SYSCTL_LEN);
if (error)
break;
}
MRW_RUNLOCK();
return (error);
}

View File

@ -265,6 +265,7 @@ struct vif {
u_long v_bytes_in; /* # bytes in on interface */
u_long v_bytes_out; /* # bytes out on interface */
#ifdef _KERNEL
#define MROUTE_VIF_SYSCTL_LEN __offsetof(struct vif, v_spin)
struct mtx v_spin; /* Spin mutex for pkt stats */
char v_spin_name[32];
#endif