1/* 2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright 1996 Massachusetts Institute of Technology 30 * 31 * Permission to use, copy, modify, and distribute this software and 32 * its documentation for any purpose and without fee is hereby 33 * granted, provided that both the above copyright notice and this 34 * permission notice appear in all copies, that both the above 35 * copyright notice and this permission notice appear in all 36 * supporting documentation, and that the name of M.I.T. not be used 37 * in advertising or publicity pertaining to distribution of the 38 * software without specific, written prior permission. M.I.T. makes 39 * no representations about the suitability of this software for any 40 * purpose. It is provided "as is" without express or implied 41 * warranty. 42 * 43 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 44 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 45 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 46 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 47 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 50 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 51 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 52 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 53 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 * 56 * $FreeBSD: src/sys/net/if_mib.c,v 1.8.2.1 2000/08/03 00:09:34 ps Exp $ 57 */ 58 59#include <sys/param.h> 60#include <sys/systm.h> 61#include <sys/kernel.h> 62#include <sys/socket.h> 63#include <sys/sysctl.h> 64#include <sys/systm.h> 65 66#include <net/if.h> 67#include <net/if_mib.h> 68#include <net/if_var.h> 69 70/* 71 * A sysctl(3) MIB for generic interface information. This information 72 * is exported in the net.link.generic branch, which has the following 73 * structure: 74 * 75 * net.link.generic .system - system-wide control variables 76 * and statistics (node) 77 * .ifdata.<ifindex>.general 78 * - what's in `struct ifdata' 79 * plus some other info 80 * .ifdata.<ifindex>.linkspecific 81 * - a link-type-specific data 82 * structure (as might be used 83 * by an SNMP agent 84 * 85 * Perhaps someday we will make addresses accessible via this interface 86 * as well (then there will be four such...). The reason that the 87 * index comes before the last element in the name is because it 88 * seems more orthogonal that way, particularly with the possibility 89 * of other per-interface data living down here as well (e.g., integrated 90 * services stuff). 91 */ 92 93SYSCTL_DECL(_net_link_generic); 94 95SYSCTL_NODE(_net_link_generic, IFMIB_SYSTEM, system, CTLFLAG_RD|CTLFLAG_LOCKED, 0, 96 "Variables global to all interfaces"); 97 98SYSCTL_INT(_net_link_generic_system, IFMIB_IFCOUNT, ifcount, CTLFLAG_RD | CTLFLAG_LOCKED, 99 &if_index, 0, "Number of configured interfaces"); 100 101static int sysctl_ifdata SYSCTL_HANDLER_ARGS; 102SYSCTL_NODE(_net_link_generic, IFMIB_IFDATA, ifdata, CTLFLAG_RD | CTLFLAG_LOCKED, 103 sysctl_ifdata, "Interface table"); 104 105static int sysctl_ifalldata SYSCTL_HANDLER_ARGS; 106SYSCTL_NODE(_net_link_generic, IFMIB_IFALLDATA, ifalldata, CTLFLAG_RD | CTLFLAG_LOCKED, 107 sysctl_ifalldata, "Interface table"); 108 109static int make_ifmibdata(struct ifnet *, int *, struct sysctl_req *); 110 111int 112make_ifmibdata(struct ifnet *ifp, int *name, struct sysctl_req *req) 113{ 114 struct ifmibdata ifmd; 115 int error = 0; 116 117 switch(name[1]) { 118 default: 119 error = ENOENT; 120 break; 121 122 case IFDATA_GENERAL: 123 bzero(&ifmd, sizeof(ifmd)); 124 /* 125 * Make sure the interface is in use 126 */ 127 if (ifnet_is_attached(ifp, 0)) { 128 snprintf(ifmd.ifmd_name, sizeof(ifmd.ifmd_name), "%s%d", 129 ifp->if_name, ifp->if_unit); 130 131#define COPY(fld) ifmd.ifmd_##fld = ifp->if_##fld 132 COPY(pcount); 133 COPY(flags); 134 if_data_internal_to_if_data64(ifp, &ifp->if_data, &ifmd.ifmd_data); 135#undef COPY 136 ifmd.ifmd_snd_len = IFCQ_LEN(&ifp->if_snd); 137 ifmd.ifmd_snd_maxlen = IFCQ_MAXLEN(&ifp->if_snd); 138 ifmd.ifmd_snd_drops = ifp->if_snd.ifcq_dropcnt.packets; 139 } 140 error = SYSCTL_OUT(req, &ifmd, sizeof ifmd); 141 if (error || !req->newptr) 142 break; 143 144#ifdef IF_MIB_WR 145 error = SYSCTL_IN(req, &ifmd, sizeof ifmd); 146 if (error) 147 break; 148 149#define DONTCOPY(fld) ifmd.ifmd_data.ifi_##fld = ifp->if_data.ifi_##fld 150 DONTCOPY(type); 151 DONTCOPY(physical); 152 DONTCOPY(addrlen); 153 DONTCOPY(hdrlen); 154 DONTCOPY(mtu); 155 DONTCOPY(metric); 156 DONTCOPY(baudrate); 157#undef DONTCOPY 158#define COPY(fld) ifp->if_##fld = ifmd.ifmd_##fld 159 COPY(data); 160 ifp->if_snd.ifq_maxlen = ifmd.ifmd_snd_maxlen; 161 ifp->if_snd.ifq_drops = ifmd.ifmd_snd_drops; 162#undef COPY 163#endif /* IF_MIB_WR */ 164 break; 165 166 case IFDATA_LINKSPECIFIC: 167 error = SYSCTL_OUT(req, ifp->if_linkmib, ifp->if_linkmiblen); 168 if (error || !req->newptr) 169 break; 170 171#ifdef IF_MIB_WR 172 error = SYSCTL_IN(req, ifp->if_linkmib, ifp->if_linkmiblen); 173 if (error) 174 break; 175#endif /* IF_MIB_WR */ 176 break; 177 178 case IFDATA_SUPPLEMENTAL: { 179 struct ifmibdata_supplemental *ifmd_supp; 180 181 if ((ifmd_supp = _MALLOC(sizeof (*ifmd_supp), M_TEMP, 182 M_NOWAIT | M_ZERO)) == NULL) { 183 error = ENOMEM; 184 break; 185 } 186 187 if_copy_traffic_class(ifp, &ifmd_supp->ifmd_traffic_class); 188 if_copy_data_extended(ifp, &ifmd_supp->ifmd_data_extended); 189 if_copy_packet_stats(ifp, &ifmd_supp->ifmd_packet_stats); 190 if_copy_rxpoll_stats(ifp, &ifmd_supp->ifmd_rxpoll_stats); 191 192 error = SYSCTL_OUT(req, ifmd_supp, sizeof (*ifmd_supp)); 193 _FREE(ifmd_supp, M_TEMP); 194 break; 195 } 196 } 197 198 return error; 199} 200 201int 202sysctl_ifdata SYSCTL_HANDLER_ARGS /* XXX bad syntax! */ 203{ 204#pragma unused(oidp) 205 int *name = (int *)arg1; 206 int error = 0; 207 u_int namelen = arg2; 208 struct ifnet *ifp; 209 210 if (namelen != 2) 211 return (EINVAL); 212 213 ifnet_head_lock_shared(); 214 if (name[0] <= 0 || name[0] > if_index || 215 (ifp = ifindex2ifnet[name[0]]) == NULL) { 216 ifnet_head_done(); 217 return (ENOENT); 218 } 219 ifnet_reference(ifp); 220 ifnet_head_done(); 221 222 ifnet_lock_shared(ifp); 223 error = make_ifmibdata(ifp, name, req); 224 ifnet_lock_done(ifp); 225 226 ifnet_release(ifp); 227 228 return (error); 229} 230 231int 232sysctl_ifalldata SYSCTL_HANDLER_ARGS /* XXX bad syntax! */ 233{ 234#pragma unused(oidp) 235 int *name = (int *)arg1; 236 int error = 0; 237 u_int namelen = arg2; 238 struct ifnet *ifp; 239 240 if (namelen != 2) 241 return (EINVAL); 242 243 ifnet_head_lock_shared(); 244 TAILQ_FOREACH(ifp, &ifnet_head, if_link) { 245 ifnet_lock_shared(ifp); 246 247 error = make_ifmibdata(ifp, name, req); 248 249 ifnet_lock_done(ifp); 250 if (error != 0) 251 break; 252 } 253 ifnet_head_done(); 254 return error; 255} 256