if_mib.c revision 181803
117651Speter/*-
2254069Sdelphij * Copyright 1996 Massachusetts Institute of Technology
3131380Stjr *
417651Speter * Permission to use, copy, modify, and distribute this software and
517651Speter * its documentation for any purpose and without fee is hereby
650476Speter * granted, provided that both the above copyright notice and this
717651Speter * permission notice appear in all copies, that both the above
8131380Stjr * copyright notice and this permission notice appear in all
9131380Stjr * supporting documentation, and that the name of M.I.T. not be used
1017651Speter * in advertising or publicity pertaining to distribution of the
1117651Speter * software without specific, written prior permission.  M.I.T. makes
1217651Speter * no representations about the suitability of this software for any
1317651Speter * purpose.  It is provided "as is" without express or implied
14205471Sdelphij * warranty.
15205471Sdelphij *
1617651Speter * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17205471Sdelphij * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18237691Sdelphij * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19205471Sdelphij * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20205471Sdelphij * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21205471Sdelphij * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22205471Sdelphij * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23205471Sdelphij * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24254069Sdelphij * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25205471Sdelphij * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26205471Sdelphij * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27205471Sdelphij * SUCH DAMAGE.
28205471Sdelphij *
29205471Sdelphij * $FreeBSD: head/sys/net/if_mib.c 181803 2008-08-17 23:27:27Z bz $
30205471Sdelphij */
31205471Sdelphij
32237691Sdelphij#include <sys/param.h>
33237691Sdelphij#include <sys/systm.h>
34237691Sdelphij#include <sys/kernel.h>
35237691Sdelphij#include <sys/socket.h>
36237691Sdelphij#include <sys/sysctl.h>
37205471Sdelphij#include <sys/vimage.h>
38205471Sdelphij
39205471Sdelphij#include <net/if.h>
40145490Skientzle#include <net/if_mib.h>
41205471Sdelphij
42205471Sdelphij/*
43145490Skientzle * A sysctl(3) MIB for generic interface information.  This information
44145490Skientzle * is exported in the net.link.generic branch, which has the following
45205471Sdelphij * structure:
46145490Skientzle *
47237691Sdelphij * net.link.generic	.system			- system-wide control variables
48145490Skientzle *						  and statistics (node)
49205471Sdelphij *			.ifdata.<ifindex>.general
50237691Sdelphij *						- what's in `struct ifdata'
51205471Sdelphij *						  plus some other info
52205471Sdelphij *			.ifdata.<ifindex>.linkspecific
53205471Sdelphij *						- a link-type-specific data
54205471Sdelphij *						  structure (as might be used
55205471Sdelphij *						  by an SNMP agent
56237691Sdelphij *
57237691Sdelphij * Perhaps someday we will make addresses accessible via this interface
58237691Sdelphij * as well (then there will be four such...).  The reason that the
59237691Sdelphij * index comes before the last element in the name is because it
60237691Sdelphij * seems more orthogonal that way, particularly with the possibility
61237691Sdelphij * of other per-interface data living down here as well (e.g., integrated
62237691Sdelphij * services stuff).
63237691Sdelphij */
64237691Sdelphij
65237691SdelphijSYSCTL_DECL(_net_link_generic);
66237691SdelphijSYSCTL_NODE(_net_link_generic, IFMIB_SYSTEM, system, CTLFLAG_RW, 0,
67237691Sdelphij	    "Variables global to all interfaces");
68237691SdelphijSYSCTL_INT(_net_link_generic_system, IFMIB_IFCOUNT, ifcount, CTLFLAG_RD,
69237691Sdelphij	   &if_index, 0, "Number of configured interfaces");
70237691Sdelphij
71237691Sdelphijstatic int
72237691Sdelphijsysctl_ifdata(SYSCTL_HANDLER_ARGS) /* XXX bad syntax! */
73237691Sdelphij{
74237691Sdelphij	int *name = (int *)arg1;
75237691Sdelphij	int error;
76237691Sdelphij	u_int namelen = arg2;
77237691Sdelphij	struct ifnet *ifp;
78237691Sdelphij	struct ifmibdata ifmd;
79237691Sdelphij	size_t dlen;
80237691Sdelphij	char *dbuf;
81254069Sdelphij
82237691Sdelphij	if (namelen != 2)
83237691Sdelphij		return EINVAL;
84237691Sdelphij
85237691Sdelphij	if (name[0] <= 0 || name[0] > V_if_index ||
86237691Sdelphij	    ifnet_byindex(name[0]) == NULL)
87237691Sdelphij		return ENOENT;
88237691Sdelphij
89237691Sdelphij	ifp = ifnet_byindex(name[0]);
90237691Sdelphij
91237691Sdelphij	switch(name[1]) {
92237691Sdelphij	default:
93237691Sdelphij		return ENOENT;
94205471Sdelphij
95205471Sdelphij	case IFDATA_GENERAL:
96205471Sdelphij		bzero(&ifmd, sizeof(ifmd));
97205471Sdelphij		strlcpy(ifmd.ifmd_name, ifp->if_xname, sizeof(ifmd.ifmd_name));
98205471Sdelphij
99205471Sdelphij#define COPY(fld) ifmd.ifmd_##fld = ifp->if_##fld
100205471Sdelphij		COPY(pcount);
101145490Skientzle		COPY(data);
102205471Sdelphij#undef COPY
103205471Sdelphij		ifmd.ifmd_flags = ifp->if_flags | ifp->if_drv_flags;
104205471Sdelphij		ifmd.ifmd_snd_len = ifp->if_snd.ifq_len;
105205471Sdelphij		ifmd.ifmd_snd_maxlen = ifp->if_snd.ifq_maxlen;
106205471Sdelphij		ifmd.ifmd_snd_drops = ifp->if_snd.ifq_drops;
107145490Skientzle
108254069Sdelphij		error = SYSCTL_OUT(req, &ifmd, sizeof ifmd);
109145490Skientzle		if (error || !req->newptr)
110145490Skientzle			return error;
111205471Sdelphij
112237691Sdelphij		error = SYSCTL_IN(req, &ifmd, sizeof ifmd);
113205471Sdelphij		if (error)
114205471Sdelphij			return error;
115205471Sdelphij
116237691Sdelphij#define DONTCOPY(fld) ifmd.ifmd_data.ifi_##fld = ifp->if_data.ifi_##fld
117237691Sdelphij		DONTCOPY(type);
118237691Sdelphij		DONTCOPY(physical);
119145490Skientzle		DONTCOPY(addrlen);
120237691Sdelphij		DONTCOPY(hdrlen);
121237691Sdelphij		DONTCOPY(mtu);
122237691Sdelphij		DONTCOPY(metric);
123237691Sdelphij		DONTCOPY(baudrate);
124205471Sdelphij#undef DONTCOPY
125205471Sdelphij#define COPY(fld) ifp->if_##fld = ifmd.ifmd_##fld
12617651Speter		COPY(data);
127205471Sdelphij		ifp->if_snd.ifq_maxlen = ifmd.ifmd_snd_maxlen;
128205471Sdelphij		ifp->if_snd.ifq_drops = ifmd.ifmd_snd_drops;
129205471Sdelphij#undef COPY
130157046Sdes		break;
131205471Sdelphij
132157046Sdes	case IFDATA_LINKSPECIFIC:
133237691Sdelphij		error = SYSCTL_OUT(req, ifp->if_linkmib, ifp->if_linkmiblen);
134237691Sdelphij		if (error || !req->newptr)
135237691Sdelphij			return error;
136205471Sdelphij
137205471Sdelphij		error = SYSCTL_IN(req, ifp->if_linkmib, ifp->if_linkmiblen);
138157046Sdes		if (error)
139205471Sdelphij			return error;
140157046Sdes
141145490Skientzle	case IFDATA_DRIVERNAME:
142205471Sdelphij		/* 20 is enough for 64bit ints */
143145490Skientzle		dlen = strlen(ifp->if_dname) + 20 + 1;
144145490Skientzle		if ((dbuf = malloc(dlen, M_TEMP, M_NOWAIT)) == NULL)
145205471Sdelphij			return (ENOMEM);
146205471Sdelphij		if (ifp->if_dunit == IF_DUNIT_NONE)
147145490Skientzle			strcpy(dbuf, ifp->if_dname);
148205471Sdelphij		else
149205471Sdelphij			sprintf(dbuf, "%s%d", ifp->if_dname, ifp->if_dunit);
150205471Sdelphij
151205471Sdelphij		error = SYSCTL_OUT(req, dbuf, strlen(dbuf) + 1);
152205471Sdelphij		if (error == 0 && req->newptr != NULL)
15317651Speter			error = EPERM;
15417651Speter		free(dbuf, M_TEMP);
155131380Stjr		return (error);
156131380Stjr	}
157131380Stjr	return 0;
158131380Stjr}
159131380Stjr
160131380StjrSYSCTL_NODE(_net_link_generic, IFMIB_IFDATA, ifdata, CTLFLAG_RW,
161131380Stjr	    sysctl_ifdata, "Interface table");
162131380Stjr
163131380Stjr