1 /* 2 * Copyright (c) 2000-2021 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/systm.h> 64 65 #include <net/if.h> 66 #include <net/if_mib.h> 67 #include <net/if_var.h> 68 #include <net/net_sysctl.h> 69 70 #include <os/log.h> 71 72 /* 73 * A sysctl(3) MIB for generic interface information. This information 74 * is exported in the net.link.generic branch, which has the following 75 * structure: 76 * 77 * net.link.generic .system - system-wide control variables 78 * and statistics (node) 79 * .ifdata.<ifindex>.general 80 * - what's in `struct ifdata' 81 * plus some other info 82 * .ifdata.<ifindex>.linkspecific 83 * - a link-type-specific data 84 * structure (as might be used 85 * by an SNMP agent 86 * 87 * Perhaps someday we will make addresses accessible via this interface 88 * as well (then there will be four such...). The reason that the 89 * index comes before the last element in the name is because it 90 * seems more orthogonal that way, particularly with the possibility 91 * of other per-interface data living down here as well (e.g., integrated 92 * services stuff). 93 */ 94 95 SYSCTL_DECL(_net_link_generic); 96 97 SYSCTL_NODE(_net_link_generic, IFMIB_SYSTEM, system, CTLFLAG_RD | CTLFLAG_LOCKED, 0, 98 "Variables global to all interfaces"); 99 100 static int sysctl_ifdata SYSCTL_HANDLER_ARGS; 101 SYSCTL_NODE(_net_link_generic, IFMIB_IFDATA, ifdata, CTLFLAG_RD | CTLFLAG_LOCKED, 102 sysctl_ifdata, "Interface table"); 103 104 static int sysctl_ifalldata SYSCTL_HANDLER_ARGS; 105 SYSCTL_NODE(_net_link_generic, IFMIB_IFALLDATA, ifalldata, CTLFLAG_RD | CTLFLAG_LOCKED, 106 sysctl_ifalldata, "Interface table"); 107 108 static int make_ifmibdata(struct ifnet *, int *__counted_by(2), struct sysctl_req *); 109 int 110 make_ifmibdata(struct ifnet *ifp, int *__counted_by(2) name, struct sysctl_req *req) 111 { 112 struct ifmibdata ifmd; 113 int error = 0; 114 115 switch (name[1]) { 116 default: 117 error = ENOENT; 118 break; 119 120 case IFDATA_GENERAL: 121 bzero(&ifmd, sizeof(ifmd)); 122 /* 123 * Make sure the interface is in use 124 */ 125 if (ifnet_is_attached(ifp, 0)) { 126 snprintf(ifmd.ifmd_name, sizeof(ifmd.ifmd_name), "%s", 127 if_name(ifp)); 128 129 #define COPY(fld) ifmd.ifmd_##fld = ifp->if_##fld 130 COPY(pcount); 131 COPY(flags); 132 if_data_internal_to_if_data64(ifp, &ifp->if_data, &ifmd.ifmd_data); 133 #undef COPY 134 ifmd.ifmd_snd_len = IFCQ_LEN(ifp->if_snd); 135 ifmd.ifmd_snd_maxlen = IFCQ_MAXLEN(ifp->if_snd); 136 ifmd.ifmd_snd_drops = 137 (unsigned int)ifp->if_snd->ifcq_dropcnt.packets; 138 } 139 error = SYSCTL_OUT(req, &ifmd, sizeof ifmd); 140 if (error || !req->newptr) { 141 break; 142 } 143 144 #ifdef IF_MIB_WR 145 error = SYSCTL_IN(req, &ifmd, sizeof ifmd); 146 if (error) { 147 break; 148 } 149 150 #define DONTCOPY(fld) ifmd.ifmd_data.ifi_##fld = ifp->if_data.ifi_##fld 151 DONTCOPY(type); 152 DONTCOPY(physical); 153 DONTCOPY(addrlen); 154 DONTCOPY(hdrlen); 155 DONTCOPY(mtu); 156 DONTCOPY(metric); 157 DONTCOPY(baudrate); 158 #undef DONTCOPY 159 #define COPY(fld) ifp->if_##fld = ifmd.ifmd_##fld 160 COPY(data); 161 ifp->if_snd->ifq_maxlen = ifmd.ifmd_snd_maxlen; 162 ifp->if_snd->ifq_drops = ifmd.ifmd_snd_drops; 163 #undef COPY 164 #endif /* IF_MIB_WR */ 165 break; 166 167 case IFDATA_LINKSPECIFIC: 168 error = SYSCTL_OUT(req, ifp->if_linkmib, ifp->if_linkmiblen); 169 if (error || !req->newptr) { 170 break; 171 } 172 173 #ifdef IF_MIB_WR 174 error = SYSCTL_IN(req, ifp->if_linkmib, ifp->if_linkmiblen); 175 if (error) { 176 break; 177 } 178 #endif /* IF_MIB_WR */ 179 break; 180 181 case IFDATA_SUPPLEMENTAL: { 182 struct ifmibdata_supplemental *ifmd_supp; 183 184 ifmd_supp = kalloc_type(struct ifmibdata_supplemental, 185 Z_WAITOK | Z_ZERO | Z_NOFAIL); 186 if_copy_traffic_class(ifp, &ifmd_supp->ifmd_traffic_class); 187 if_copy_data_extended(ifp, &ifmd_supp->ifmd_data_extended); 188 if_copy_packet_stats(ifp, &ifmd_supp->ifmd_packet_stats); 189 if_copy_rxpoll_stats(ifp, &ifmd_supp->ifmd_rxpoll_stats); 190 if_copy_netif_stats(ifp, &ifmd_supp->ifmd_netif_stats); 191 192 if (req->oldptr == USER_ADDR_NULL) { 193 req->oldlen = sizeof(*ifmd_supp); 194 } 195 196 error = SYSCTL_OUT(req, ifmd_supp, MIN(sizeof(*ifmd_supp), 197 req->oldlen)); 198 #if DEVELOPMENT || DEBUG 199 if (error != 0) { 200 os_log(OS_LOG_DEFAULT, "%s: IFDATA_SUPPLEMENTAL SYSCTL_OUT(MIN(%lu, %lu) failed with error %d", 201 __func__, sizeof(*ifmd_supp), req->oldlen, error); 202 } 203 #endif /* DEVELOPMENT || DEBUG */ 204 205 kfree_type(struct ifmibdata_supplemental, ifmd_supp); 206 break; 207 } 208 } 209 210 return error; 211 } 212 213 int 214 sysctl_ifdata SYSCTL_HANDLER_ARGS /* XXX bad syntax! */ 215 { 216 #pragma unused(oidp) 217 DECLARE_SYSCTL_HANDLER_ARG_ARRAY(int, 2, name, namelen); 218 int error = 0; 219 struct ifnet *ifp; 220 221 ifnet_head_lock_shared(); 222 if (name[0] <= 0 || name[0] > if_index || 223 (ifp = ifindex2ifnet[name[0]]) == NULL) { 224 ifnet_head_done(); 225 return ENOENT; 226 } 227 ifnet_reference(ifp); 228 ifnet_head_done(); 229 230 ifnet_lock_shared(ifp); 231 error = make_ifmibdata(ifp, name, req); 232 ifnet_lock_done(ifp); 233 234 ifnet_release(ifp); 235 236 return error; 237 } 238 239 int 240 sysctl_ifalldata SYSCTL_HANDLER_ARGS /* XXX bad syntax! */ 241 { 242 #pragma unused(oidp) 243 DECLARE_SYSCTL_HANDLER_ARG_ARRAY(int, 2, name, namelen); 244 int error = 0; 245 struct ifnet *ifp; 246 247 ifnet_head_lock_shared(); 248 TAILQ_FOREACH(ifp, &ifnet_head, if_link) { 249 ifnet_lock_shared(ifp); 250 251 error = make_ifmibdata(ifp, name, req); 252 253 ifnet_lock_done(ifp); 254 if (error != 0) { 255 break; 256 } 257 } 258 ifnet_head_done(); 259 return error; 260 } 261 262 static int 263 sysctl_ifindex SYSCTL_HANDLER_ARGS 264 { 265 int error, val = if_index; 266 267 error = sysctl_handle_int(oidp, &val, 0, req); 268 if (error || !req->newptr) { 269 return error; 270 } 271 272 return 0; 273 } 274 275 SYSCTL_PROC( _net_link_generic_system, IFMIB_IFCOUNT, ifcount, 276 CTLFLAG_RD | CTLFLAG_LOCKED, 277 NULL, 0, sysctl_ifindex, "Number of configured interfaces", 278 ""); 279