1 1.27 riastrad /* $NetBSD: if_43.c,v 1.27 2023/03/30 17:48:10 riastradh Exp $ */ 2 1.1 ad 3 1.1 ad /* 4 1.1 ad * Copyright (c) 1982, 1986, 1989, 1990, 1993 5 1.1 ad * The Regents of the University of California. All rights reserved. 6 1.1 ad * 7 1.1 ad * Redistribution and use in source and binary forms, with or without 8 1.1 ad * modification, are permitted provided that the following conditions 9 1.1 ad * are met: 10 1.1 ad * 1. Redistributions of source code must retain the above copyright 11 1.1 ad * notice, this list of conditions and the following disclaimer. 12 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 ad * notice, this list of conditions and the following disclaimer in the 14 1.1 ad * documentation and/or other materials provided with the distribution. 15 1.1 ad * 3. Neither the name of the University nor the names of its contributors 16 1.1 ad * may be used to endorse or promote products derived from this software 17 1.1 ad * without specific prior written permission. 18 1.1 ad * 19 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 ad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 ad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 ad * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 ad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 ad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 ad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 ad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 ad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 ad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 ad * SUCH DAMAGE. 30 1.1 ad * 31 1.1 ad * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 32 1.1 ad */ 33 1.1 ad 34 1.1 ad #include <sys/cdefs.h> 35 1.27 riastrad __KERNEL_RCSID(0, "$NetBSD: if_43.c,v 1.27 2023/03/30 17:48:10 riastradh Exp $"); 36 1.2 dyoung 37 1.2 dyoung #if defined(_KERNEL_OPT) 38 1.2 dyoung #include "opt_compat_netbsd.h" 39 1.2 dyoung #endif 40 1.1 ad 41 1.1 ad #include <sys/param.h> 42 1.1 ad #include <sys/systm.h> 43 1.1 ad #include <sys/filedesc.h> 44 1.1 ad #include <sys/kernel.h> 45 1.1 ad #include <sys/proc.h> 46 1.1 ad #include <sys/file.h> 47 1.1 ad #include <sys/socket.h> 48 1.1 ad #include <sys/socketvar.h> 49 1.1 ad #include <sys/stat.h> 50 1.1 ad #include <sys/ioctl.h> 51 1.1 ad #include <sys/fcntl.h> 52 1.1 ad #include <sys/syslog.h> 53 1.1 ad #include <sys/unistd.h> 54 1.1 ad #include <sys/resourcevar.h> 55 1.1 ad #include <sys/mbuf.h> /* for MLEN */ 56 1.1 ad #include <sys/protosw.h> 57 1.16 pgoyette #include <sys/compat_stub.h> 58 1.1 ad 59 1.1 ad #include <sys/syscallargs.h> 60 1.1 ad 61 1.1 ad #include <net/if.h> 62 1.1 ad #include <net/bpf.h> 63 1.1 ad #include <net/route.h> 64 1.1 ad #include <netinet/in.h> 65 1.1 ad #include <netinet/in_systm.h> 66 1.1 ad #include <netinet/ip.h> 67 1.1 ad #include <net/if_gre.h> 68 1.1 ad #include <net/if_tap.h> 69 1.1 ad #include <net80211/ieee80211_ioctl.h> 70 1.1 ad #include <netinet6/in6_var.h> 71 1.1 ad #include <netinet6/nd6.h> 72 1.26 msaitoh #include <compat/net/if.h> 73 1.1 ad #include <compat/sys/socket.h> 74 1.1 ad #include <compat/sys/sockio.h> 75 1.1 ad 76 1.1 ad #include <compat/common/compat_util.h> 77 1.16 pgoyette #include <compat/common/compat_mod.h> 78 1.1 ad #include <uvm/uvm_extern.h> 79 1.1 ad 80 1.16 pgoyette #if defined(COMPAT_43) 81 1.16 pgoyette 82 1.16 pgoyette /* 83 1.16 pgoyette * Use a wrapper so that the compat_cvtcmd() can return a u_long 84 1.16 pgoyette */ 85 1.16 pgoyette static int 86 1.16 pgoyette do_compat_cvtcmd(u_long *ncmd, u_long ocmd) 87 1.16 pgoyette { 88 1.16 pgoyette 89 1.16 pgoyette *ncmd = compat_cvtcmd(ocmd); 90 1.16 pgoyette return 0; 91 1.16 pgoyette } 92 1.16 pgoyette 93 1.16 pgoyette u_long 94 1.1 ad compat_cvtcmd(u_long cmd) 95 1.16 pgoyette { 96 1.1 ad u_long ncmd; 97 1.1 ad 98 1.1 ad if (IOCPARM_LEN(cmd) != sizeof(struct oifreq)) 99 1.1 ad return cmd; 100 1.1 ad 101 1.3 christos switch (cmd) { 102 1.3 christos case OSIOCSIFADDR: 103 1.3 christos return SIOCSIFADDR; 104 1.3 christos case OOSIOCGIFADDR: 105 1.3 christos return SIOCGIFADDR; 106 1.3 christos case OSIOCSIFDSTADDR: 107 1.3 christos return SIOCSIFDSTADDR; 108 1.3 christos case OOSIOCGIFDSTADDR: 109 1.3 christos return SIOCGIFDSTADDR; 110 1.3 christos case OSIOCSIFFLAGS: 111 1.3 christos return SIOCSIFFLAGS; 112 1.3 christos case OSIOCGIFFLAGS: 113 1.3 christos return SIOCGIFFLAGS; 114 1.3 christos case OOSIOCGIFBRDADDR: 115 1.3 christos return SIOCGIFBRDADDR; 116 1.3 christos case OSIOCSIFBRDADDR: 117 1.3 christos return SIOCSIFBRDADDR; 118 1.3 christos case OOSIOCGIFCONF: 119 1.3 christos return SIOCGIFCONF; 120 1.3 christos case OOSIOCGIFNETMASK: 121 1.3 christos return SIOCGIFNETMASK; 122 1.3 christos case OSIOCSIFNETMASK: 123 1.3 christos return SIOCSIFNETMASK; 124 1.3 christos case OSIOCGIFCONF: 125 1.3 christos return SIOCGIFCONF; 126 1.3 christos case OSIOCADDMULTI: 127 1.3 christos return SIOCADDMULTI; 128 1.3 christos case OSIOCDELMULTI: 129 1.3 christos return SIOCDELMULTI; 130 1.22 msaitoh case SIOCSIFMEDIA_43: 131 1.22 msaitoh return SIOCSIFMEDIA_80; 132 1.3 christos case OSIOCGIFMTU: 133 1.3 christos return SIOCGIFMTU; 134 1.3 christos case OSIOCGIFDATA: 135 1.3 christos return SIOCGIFDATA; 136 1.3 christos case OSIOCZIFDATA: 137 1.3 christos return SIOCZIFDATA; 138 1.3 christos case OBIOCGETIF: 139 1.3 christos return BIOCGETIF; 140 1.3 christos case OBIOCSETIF: 141 1.3 christos return BIOCSETIF; 142 1.3 christos case OTAPGIFNAME: 143 1.3 christos return TAPGIFNAME; 144 1.3 christos default: 145 1.3 christos /* 146 1.3 christos * XXX: the following code should be removed and the 147 1.3 christos * needing treatment ioctls should move to the switch 148 1.3 christos * above. 149 1.3 christos */ 150 1.3 christos ncmd = ((cmd) & ~(IOCPARM_MASK << IOCPARM_SHIFT)) | 151 1.3 christos (sizeof(struct ifreq) << IOCPARM_SHIFT); 152 1.3 christos switch (ncmd) { 153 1.3 christos case BIOCGETIF: 154 1.3 christos case BIOCSETIF: 155 1.3 christos case GREDSOCK: 156 1.3 christos case GREGADDRD: 157 1.3 christos case GREGADDRS: 158 1.3 christos case GREGPROTO: 159 1.3 christos case GRESADDRD: 160 1.3 christos case GRESADDRS: 161 1.3 christos case GRESPROTO: 162 1.3 christos case GRESSOCK: 163 1.3 christos case SIOCADDMULTI: 164 1.3 christos case SIOCDELMULTI: 165 1.3 christos case SIOCDIFADDR: 166 1.3 christos case SIOCDIFADDR_IN6: 167 1.3 christos case SIOCDIFPHYADDR: 168 1.3 christos case SIOCG80211NWID: 169 1.3 christos case SIOCG80211STATS: 170 1.3 christos case SIOCG80211ZSTATS: 171 1.3 christos case SIOCGIFADDR: 172 1.3 christos case SIOCGIFADDR_IN6: 173 1.3 christos case SIOCGIFAFLAG_IN6: 174 1.3 christos case SIOCGIFALIFETIME_IN6: 175 1.3 christos case SIOCGIFBRDADDR: 176 1.3 christos case SIOCGIFDLT: 177 1.3 christos case SIOCGIFDSTADDR: 178 1.3 christos case SIOCGIFDSTADDR_IN6: 179 1.3 christos case SIOCGIFFLAGS: 180 1.3 christos case SIOCGIFGENERIC: 181 1.3 christos case SIOCGIFMETRIC: 182 1.3 christos case SIOCGIFMTU: 183 1.3 christos case SIOCGIFNETMASK: 184 1.3 christos case SIOCGIFNETMASK_IN6: 185 1.3 christos case SIOCGIFPDSTADDR: 186 1.3 christos case SIOCGIFPDSTADDR_IN6: 187 1.3 christos case SIOCGIFPSRCADDR: 188 1.3 christos case SIOCGIFPSRCADDR_IN6: 189 1.3 christos case SIOCGIFSTAT_ICMP6: 190 1.3 christos case SIOCGIFSTAT_IN6: 191 1.3 christos case SIOCGVH: 192 1.3 christos case SIOCIFCREATE: 193 1.3 christos case SIOCIFDESTROY: 194 1.3 christos case SIOCS80211NWID: 195 1.3 christos case SIOCSIFADDR: 196 1.3 christos case SIOCSIFADDR_IN6: 197 1.3 christos case SIOCSIFBRDADDR: 198 1.3 christos case SIOCSIFDSTADDR: 199 1.3 christos case SIOCSIFDSTADDR_IN6: 200 1.3 christos case SIOCSIFFLAGS: 201 1.3 christos case SIOCSIFGENERIC: 202 1.3 christos case SIOCSIFMEDIA: 203 1.3 christos case SIOCSIFMETRIC: 204 1.3 christos case SIOCSIFMTU: 205 1.3 christos case SIOCSIFNETMASK: 206 1.3 christos case SIOCSIFNETMASK_IN6: 207 1.3 christos case SIOCSVH: 208 1.3 christos case TAPGIFNAME: 209 1.3 christos return ncmd; 210 1.3 christos default: 211 1.17 pgoyette { int rv; 212 1.17 pgoyette 213 1.20 pgoyette MODULE_HOOK_CALL(if43_cvtcmd_20_hook, (ncmd), enosys(), 214 1.18 pgoyette rv); 215 1.17 pgoyette if (rv == 0) 216 1.17 pgoyette return ncmd; 217 1.17 pgoyette return cmd; 218 1.17 pgoyette } 219 1.3 christos } 220 1.1 ad } 221 1.1 ad } 222 1.1 ad 223 1.1 ad int 224 1.1 ad compat_ifioctl(struct socket *so, u_long ocmd, u_long cmd, void *data, 225 1.1 ad struct lwp *l) 226 1.1 ad { 227 1.1 ad int error; 228 1.8 matt struct ifreq *ifr = (struct ifreq *)data; 229 1.10 christos struct ifreq ifrb; 230 1.10 christos struct oifreq *oifr = NULL; 231 1.12 ozaki struct ifnet *ifp; 232 1.1 ad struct sockaddr *sa; 233 1.12 ozaki struct psref psref; 234 1.12 ozaki int bound = curlwp_bind(); 235 1.1 ad 236 1.12 ozaki ifp = if_get(ifr->ifr_name, &psref); 237 1.12 ozaki if (ifp == NULL) { 238 1.12 ozaki curlwp_bindx(bound); 239 1.1 ad return ENXIO; 240 1.12 ozaki } 241 1.1 ad 242 1.10 christos /* 243 1.10 christos * If we have not been converted, make sure that we are. 244 1.10 christos * (because the upper layer handles old socket calls, but 245 1.10 christos * not oifreq calls. 246 1.10 christos */ 247 1.10 christos if (cmd == ocmd) { 248 1.10 christos cmd = compat_cvtcmd(ocmd); 249 1.11 njoly } 250 1.11 njoly if (cmd != ocmd) { 251 1.11 njoly oifr = data; 252 1.23 maxv ifr = &ifrb; 253 1.21 msaitoh IFREQO2N_43(oifr, ifr); 254 1.10 christos } 255 1.10 christos 256 1.1 ad switch (ocmd) { 257 1.27 riastrad enum { maxlen = sizeof(oifr->ifr_ifru) }; 258 1.27 riastrad CTASSERT(maxlen == 16); 259 1.27 riastrad socklen_t famlen; 260 1.1 ad case OSIOCSIFADDR: 261 1.1 ad case OSIOCSIFDSTADDR: 262 1.1 ad case OSIOCSIFBRDADDR: 263 1.1 ad case OSIOCSIFNETMASK: 264 1.1 ad sa = &ifr->ifr_addr; 265 1.1 ad #if BYTE_ORDER != BIG_ENDIAN 266 1.27 riastrad if (sa->sa_family == 0 && sa->sa_len < maxlen) { 267 1.1 ad sa->sa_family = sa->sa_len; 268 1.27 riastrad sa->sa_len = maxlen; 269 1.1 ad } 270 1.1 ad #else 271 1.1 ad if (sa->sa_len == 0) 272 1.27 riastrad sa->sa_len = maxlen; 273 1.1 ad #endif 274 1.27 riastrad famlen = sockaddr_getsize_by_family(sa->sa_family); 275 1.27 riastrad if (famlen > sa->sa_len) { 276 1.27 riastrad curlwp_bindx(bound); 277 1.27 riastrad return EAFNOSUPPORT; 278 1.27 riastrad } 279 1.27 riastrad 280 1.1 ad break; 281 1.1 ad } 282 1.1 ad 283 1.7 rtr error = (*so->so_proto->pr_usrreqs->pr_ioctl)(so, cmd, ifr, ifp); 284 1.12 ozaki if_put(ifp, &psref); 285 1.12 ozaki curlwp_bindx(bound); 286 1.1 ad 287 1.1 ad switch (ocmd) { 288 1.1 ad case OOSIOCGIFADDR: 289 1.1 ad case OOSIOCGIFDSTADDR: 290 1.1 ad case OOSIOCGIFBRDADDR: 291 1.1 ad case OOSIOCGIFNETMASK: 292 1.1 ad *(u_int16_t *)&ifr->ifr_addr = 293 1.1 ad ((struct sockaddr *)&ifr->ifr_addr)->sa_family; 294 1.10 christos break; 295 1.1 ad } 296 1.10 christos 297 1.10 christos if (cmd != ocmd) 298 1.21 msaitoh IFREQN2O_43(oifr, ifr); 299 1.10 christos 300 1.1 ad return error; 301 1.1 ad } 302 1.13 pgoyette 303 1.16 pgoyette int 304 1.13 pgoyette if_43_init(void) 305 1.13 pgoyette { 306 1.13 pgoyette 307 1.24 pgoyette MODULE_HOOK_SET(if_cvtcmd_43_hook, do_compat_cvtcmd); 308 1.24 pgoyette MODULE_HOOK_SET(if_ifioctl_43_hook, compat_ifioctl); 309 1.16 pgoyette return 0; 310 1.13 pgoyette } 311 1.13 pgoyette 312 1.16 pgoyette int 313 1.13 pgoyette if_43_fini(void) 314 1.13 pgoyette { 315 1.13 pgoyette 316 1.20 pgoyette MODULE_HOOK_UNSET(if_cvtcmd_43_hook); 317 1.20 pgoyette MODULE_HOOK_UNSET(if_ifioctl_43_hook); 318 1.16 pgoyette return 0; 319 1.13 pgoyette } 320 1.13 pgoyette #endif /* defined(COMPAT_43) */ 321