1 /* $NetBSD: netbsd32_ioctl.c,v 1.51 2010/09/24 13:12:53 njoly Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * handle ioctl conversions from netbsd32 -> 64-bit kernel 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.51 2010/09/24 13:12:53 njoly Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/filedesc.h> 39 #include <sys/ioctl.h> 40 #include <sys/file.h> 41 #include <sys/proc.h> 42 #include <sys/socketvar.h> 43 #include <sys/audioio.h> 44 #include <sys/disklabel.h> 45 #include <sys/dkio.h> 46 #include <sys/sockio.h> 47 #include <sys/socket.h> 48 #include <sys/ttycom.h> 49 #include <sys/mount.h> 50 #include <sys/syscallargs.h> 51 #include <sys/ktrace.h> 52 #include <sys/kmem.h> 53 #include <sys/envsys.h> 54 55 #ifdef __sparc__ 56 #include <dev/sun/fbio.h> 57 #include <machine/openpromio.h> 58 #endif 59 60 #include <net/if.h> 61 #include <net/route.h> 62 63 #include <netinet/in.h> 64 #include <netinet/in_var.h> 65 #include <netinet/igmp.h> 66 #include <netinet/igmp_var.h> 67 #include <netinet/ip_mroute.h> 68 69 #include <compat/sys/sockio.h> 70 71 #include <compat/netbsd32/netbsd32.h> 72 #include <compat/netbsd32/netbsd32_ioctl.h> 73 #include <compat/netbsd32/netbsd32_syscallargs.h> 74 75 #include <dev/vndvar.h> 76 77 /* prototypes for the converters */ 78 static inline void netbsd32_to_partinfo(struct netbsd32_partinfo *, 79 struct partinfo *, u_long); 80 #if 0 81 static inline void netbsd32_to_format_op(struct netbsd32_format_op *, 82 struct format_op *, u_long); 83 #endif 84 static inline void netbsd32_to_oifreq(struct netbsd32_oifreq *, struct oifreq *, 85 u_long cmd); 86 static inline void netbsd32_to_ifreq(struct netbsd32_ifreq *, struct ifreq *, 87 u_long cmd); 88 static inline void netbsd32_to_ifconf(struct netbsd32_ifconf *, 89 struct ifconf *, u_long); 90 static inline void netbsd32_to_ifmediareq(struct netbsd32_ifmediareq *, 91 struct ifmediareq *, u_long); 92 static inline void netbsd32_to_ifdrv(struct netbsd32_ifdrv *, struct ifdrv *, 93 u_long); 94 static inline void netbsd32_to_sioc_vif_req(struct netbsd32_sioc_vif_req *, 95 struct sioc_vif_req *, u_long); 96 static inline void netbsd32_to_sioc_sg_req(struct netbsd32_sioc_sg_req *, 97 struct sioc_sg_req *, u_long); 98 static inline void netbsd32_from_partinfo(struct partinfo *, 99 struct netbsd32_partinfo *, u_long); 100 #if 0 101 static inline void netbsd32_from_format_op(struct format_op *, 102 struct netbsd32_format_op *, 103 u_long); 104 #endif 105 static inline void netbsd32_from_ifreq(struct ifreq *, 106 struct netbsd32_ifreq *, u_long); 107 static inline void netbsd32_from_oifreq(struct oifreq *, 108 struct netbsd32_oifreq *, u_long); 109 static inline void netbsd32_from_ifconf(struct ifconf *, 110 struct netbsd32_ifconf *, u_long); 111 static inline void netbsd32_from_ifmediareq(struct ifmediareq *, 112 struct netbsd32_ifmediareq *, 113 u_long); 114 static inline void netbsd32_from_ifdrv(struct ifdrv *, 115 struct netbsd32_ifdrv *, u_long); 116 static inline void netbsd32_from_sioc_vif_req(struct sioc_vif_req *, 117 struct netbsd32_sioc_vif_req *, 118 u_long); 119 static inline void netbsd32_from_sioc_sg_req(struct sioc_sg_req *, 120 struct netbsd32_sioc_sg_req *, 121 u_long); 122 123 /* convert to/from different structures */ 124 125 static inline void 126 netbsd32_to_partinfo(struct netbsd32_partinfo *s32p, struct partinfo *p, u_long cmd) 127 { 128 129 p->disklab = (struct disklabel *)NETBSD32PTR64(s32p->disklab); 130 p->part = (struct partition *)NETBSD32PTR64(s32p->part); 131 } 132 133 #if 0 134 static inline void 135 netbsd32_to_format_op(struct netbsd32_format_op *s32p, struct format_op *p, u_long cmd) 136 { 137 138 p->df_buf = (char *)NETBSD32PTR64(s32p->df_buf); 139 p->df_count = s32p->df_count; 140 p->df_startblk = s32p->df_startblk; 141 memcpy(p->df_reg, s32p->df_reg, sizeof(s32p->df_reg)); 142 } 143 #endif 144 145 static inline void 146 netbsd32_to_ifreq(struct netbsd32_ifreq *s32p, struct ifreq *p, u_long cmd) 147 { 148 149 memcpy(p, s32p, sizeof *s32p); 150 /* 151 * XXX 152 * struct ifreq says the same, but sometimes the ifr_data 153 * union member needs to be converted to 64 bits... this 154 * is very driver specific and so we ignore it for now.. 155 */ 156 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) 157 p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data); 158 } 159 160 static inline void 161 netbsd32_to_oifreq(struct netbsd32_oifreq *s32p, struct oifreq *p, u_long cmd) 162 { 163 164 memcpy(p, s32p, sizeof *s32p); 165 /* 166 * XXX 167 * struct ifreq says the same, but sometimes the ifr_data 168 * union member needs to be converted to 64 bits... this 169 * is very driver specific and so we ignore it for now.. 170 */ 171 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) 172 p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data); 173 } 174 175 static inline void 176 netbsd32_to_ifconf(struct netbsd32_ifconf *s32p, struct ifconf *p, u_long cmd) 177 { 178 179 p->ifc_len = s32p->ifc_len; 180 /* ifc_buf & ifc_req are the same size so this works */ 181 p->ifc_buf = (void *)NETBSD32PTR64(s32p->ifc_buf); 182 } 183 184 static inline void 185 netbsd32_to_ifmediareq(struct netbsd32_ifmediareq *s32p, struct ifmediareq *p, u_long cmd) 186 { 187 188 memcpy(p, s32p, sizeof *s32p); 189 p->ifm_ulist = (int *)NETBSD32PTR64(s32p->ifm_ulist); 190 } 191 192 static inline void 193 netbsd32_to_ifdrv(struct netbsd32_ifdrv *s32p, struct ifdrv *p, u_long cmd) 194 { 195 196 memcpy(p, s32p, sizeof *s32p); 197 p->ifd_data = (void *)NETBSD32PTR64(s32p->ifd_data); 198 } 199 200 static inline void 201 netbsd32_to_sioc_vif_req(struct netbsd32_sioc_vif_req *s32p, struct sioc_vif_req *p, u_long cmd) 202 { 203 204 p->vifi = s32p->vifi; 205 p->icount = (u_long)s32p->icount; 206 p->ocount = (u_long)s32p->ocount; 207 p->ibytes = (u_long)s32p->ibytes; 208 p->obytes = (u_long)s32p->obytes; 209 } 210 211 static inline void 212 netbsd32_to_sioc_sg_req(struct netbsd32_sioc_sg_req *s32p, struct sioc_sg_req *p, u_long cmd) 213 { 214 215 p->src = s32p->src; 216 p->grp = s32p->grp; 217 p->pktcnt = (u_long)s32p->pktcnt; 218 p->bytecnt = (u_long)s32p->bytecnt; 219 p->wrong_if = (u_long)s32p->wrong_if; 220 } 221 222 static inline void 223 netbsd32_to_vnd_ioctl(struct netbsd32_vnd_ioctl *s32p, struct vnd_ioctl *p, u_long cmd) 224 { 225 226 p->vnd_file = (char *)NETBSD32PTR64(s32p->vnd_file); 227 p->vnd_flags = s32p->vnd_flags; 228 p->vnd_geom = s32p->vnd_geom; 229 p->vnd_osize = s32p->vnd_osize; 230 p->vnd_size = s32p->vnd_size; 231 } 232 233 static inline void 234 netbsd32_to_vnd_user(struct netbsd32_vnd_user *s32p, struct vnd_user *p, u_long cmd) 235 { 236 237 p->vnu_unit = s32p->vnu_unit; 238 p->vnu_dev = s32p->vnu_dev; 239 p->vnu_ino = s32p->vnu_ino; 240 } 241 242 static inline void 243 netbsd32_to_vnd_ioctl50(struct netbsd32_vnd_ioctl50 *s32p, struct vnd_ioctl50 *p, u_long cmd) 244 { 245 246 p->vnd_file = (char *)NETBSD32PTR64(s32p->vnd_file); 247 p->vnd_flags = s32p->vnd_flags; 248 p->vnd_geom = s32p->vnd_geom; 249 p->vnd_size = s32p->vnd_size; 250 } 251 252 static inline void 253 netbsd32_to_plistref(struct netbsd32_plistref *s32p, struct plistref *p, u_long cmd) 254 { 255 256 p->pref_plist = NETBSD32PTR64(s32p->pref_plist); 257 p->pref_len = s32p->pref_len; 258 } 259 260 static inline void 261 netbsd32_to_u_long(netbsd32_u_long *s32p, u_long *p, u_long cmd) 262 { 263 264 *p = (u_long)*s32p; 265 } 266 267 /* 268 * handle ioctl conversions from 64-bit kernel -> netbsd32 269 */ 270 271 static inline void 272 netbsd32_from_partinfo(struct partinfo *p, struct netbsd32_partinfo *s32p, u_long cmd) 273 { 274 275 NETBSD32PTR32(s32p->disklab, p->disklab); 276 NETBSD32PTR32(s32p->part, p->part); 277 } 278 279 #if 0 280 static inline void 281 netbsd32_from_format_op(struct format_op *p, struct netbsd32_format_op *s32p, u_long cmd) 282 { 283 284 /* filled in */ 285 #if 0 286 s32p->df_buf = (netbsd32_charp)p->df_buf; 287 #endif 288 s32p->df_count = p->df_count; 289 s32p->df_startblk = p->df_startblk; 290 memcpy(s32p->df_reg, p->df_reg, sizeof(p->df_reg)); 291 } 292 #endif 293 294 static inline void 295 netbsd32_from_ifreq(struct ifreq *p, struct netbsd32_ifreq *s32p, u_long cmd) 296 { 297 298 /* 299 * XXX 300 * struct ifreq says the same, but sometimes the ifr_data 301 * union member needs to be converted to 64 bits... this 302 * is very driver specific and so we ignore it for now.. 303 */ 304 memcpy(s32p, p, sizeof *s32p); 305 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) 306 NETBSD32PTR32(s32p->ifr_data, p->ifr_data); 307 } 308 309 static inline void 310 netbsd32_from_oifreq(struct oifreq *p, struct netbsd32_oifreq *s32p, u_long cmd) 311 { 312 313 /* 314 * XXX 315 * struct ifreq says the same, but sometimes the ifr_data 316 * union member needs to be converted to 64 bits... this 317 * is very driver specific and so we ignore it for now.. 318 */ 319 memcpy(s32p, p, sizeof *s32p); 320 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) 321 NETBSD32PTR32(s32p->ifr_data, p->ifr_data); 322 } 323 324 static inline void 325 netbsd32_from_ifconf(struct ifconf *p, struct netbsd32_ifconf *s32p, u_long cmd) 326 { 327 328 s32p->ifc_len = p->ifc_len; 329 /* ifc_buf & ifc_req are the same size so this works */ 330 NETBSD32PTR32(s32p->ifc_buf, p->ifc_buf); 331 } 332 333 static inline void 334 netbsd32_from_ifmediareq(struct ifmediareq *p, struct netbsd32_ifmediareq *s32p, u_long cmd) 335 { 336 337 memcpy(s32p, p, sizeof *p); 338 /* filled in? */ 339 #if 0 340 s32p->ifm_ulist = (netbsd32_intp_t)p->ifm_ulist; 341 #endif 342 } 343 344 static inline void 345 netbsd32_from_ifdrv(struct ifdrv *p, struct netbsd32_ifdrv *s32p, u_long cmd) 346 { 347 348 memcpy(s32p, p, sizeof *p); 349 /* filled in? */ 350 #if 0 351 s32p->ifm_data = (netbsd32_u_longp_t)p->ifm_data; 352 #endif 353 } 354 355 static inline void 356 netbsd32_from_sioc_vif_req(struct sioc_vif_req *p, struct netbsd32_sioc_vif_req *s32p, u_long cmd) 357 { 358 359 s32p->vifi = p->vifi; 360 s32p->icount = (netbsd32_u_long)p->icount; 361 s32p->ocount = (netbsd32_u_long)p->ocount; 362 s32p->ibytes = (netbsd32_u_long)p->ibytes; 363 s32p->obytes = (netbsd32_u_long)p->obytes; 364 } 365 366 static inline void 367 netbsd32_from_sioc_sg_req(struct sioc_sg_req *p, struct netbsd32_sioc_sg_req *s32p, u_long cmd) 368 { 369 370 s32p->src = p->src; 371 s32p->grp = p->grp; 372 s32p->pktcnt = (netbsd32_u_long)p->pktcnt; 373 s32p->bytecnt = (netbsd32_u_long)p->bytecnt; 374 s32p->wrong_if = (netbsd32_u_long)p->wrong_if; 375 } 376 377 static inline void 378 netbsd32_from_vnd_ioctl(struct vnd_ioctl *p, struct netbsd32_vnd_ioctl *s32p, u_long cmd) 379 { 380 381 s32p->vnd_flags = p->vnd_flags; 382 s32p->vnd_geom = p->vnd_geom; 383 s32p->vnd_osize = p->vnd_osize; 384 s32p->vnd_size = p->vnd_size; 385 } 386 387 static inline void 388 netbsd32_from_vnd_user(struct vnd_user *p, struct netbsd32_vnd_user *s32p, u_long cmd) 389 { 390 391 s32p->vnu_unit = p->vnu_unit; 392 s32p->vnu_dev = p->vnu_dev; 393 s32p->vnu_ino = p->vnu_ino; 394 } 395 396 static inline void 397 netbsd32_from_vnd_ioctl50(struct vnd_ioctl50 *p, struct netbsd32_vnd_ioctl50 *s32p, u_long cmd) 398 { 399 400 s32p->vnd_flags = p->vnd_flags; 401 s32p->vnd_geom = p->vnd_geom; 402 s32p->vnd_size = p->vnd_size; 403 } 404 405 static inline void 406 netbsd32_from_plistref(struct plistref *p, struct netbsd32_plistref *s32p, u_long cmd) 407 { 408 409 NETBSD32PTR32(s32p->pref_plist, p->pref_plist); 410 s32p->pref_len = p->pref_len; 411 } 412 413 static inline void 414 netbsd32_from_u_long(u_long *p, netbsd32_u_long *s32p, u_long cmd) 415 { 416 417 *s32p = (netbsd32_u_long)*p; 418 } 419 420 421 /* 422 * main ioctl syscall. 423 * 424 * ok, here we are in the biggy. we have to do fix ups depending 425 * on the ioctl command before and afterwards. 426 */ 427 int 428 netbsd32_ioctl(struct lwp *l, const struct netbsd32_ioctl_args *uap, register_t *retval) 429 { 430 /* { 431 syscallarg(int) fd; 432 syscallarg(netbsd32_u_long) com; 433 syscallarg(netbsd32_voidp) data; 434 } */ 435 struct proc *p = l->l_proc; 436 struct file *fp; 437 struct filedesc *fdp; 438 u_long com; 439 int error = 0; 440 u_int size, size32; 441 void *data, *memp = NULL; 442 void *data32, *memp32 = NULL; 443 unsigned fd; 444 fdfile_t *ff; 445 int tmp; 446 #define STK_PARAMS 128 447 u_long stkbuf[STK_PARAMS/sizeof(u_long)]; 448 u_long stkbuf32[STK_PARAMS/sizeof(u_long)]; 449 450 /* 451 * we need to translate some commands (_IOW) before calling sys_ioctl, 452 * some after (_IOR), and some both (_IOWR). 453 */ 454 #if 0 455 { 456 char *dirs[8] = { "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!", 457 "INOUT", "VOID|IN|OUT!" }; 458 459 printf("netbsd32_ioctl(%d, %x, %x): %s group %c base %d len %d\n", 460 SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data), 461 dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)], 462 IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)), 463 IOCPARM_LEN(SCARG(uap, com))); 464 } 465 #endif 466 467 fdp = p->p_fd; 468 fd = SCARG(uap, fd); 469 if ((fp = fd_getfile(fd)) == NULL) 470 return (EBADF); 471 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 472 error = EBADF; 473 goto out; 474 } 475 476 ff = fdp->fd_dt->dt_ff[SCARG(uap, fd)]; 477 switch (com = SCARG(uap, com)) { 478 case FIOCLEX: 479 ff->ff_exclose = true; 480 fdp->fd_exclose = true; 481 goto out; 482 483 case FIONCLEX: 484 ff->ff_exclose = false; 485 goto out; 486 } 487 488 /* 489 * Interpret high order word to find amount of data to be 490 * copied to/from the user's address space. 491 */ 492 size = 0; 493 size32 = IOCPARM_LEN(com); 494 if (size32 > IOCPARM_MAX) { 495 error = ENOTTY; 496 goto out; 497 } 498 if (size32 > sizeof(stkbuf)) { 499 memp32 = kmem_alloc((size_t)size32, KM_SLEEP); 500 data32 = memp32; 501 } else 502 data32 = (void *)stkbuf32; 503 if (com&IOC_IN) { 504 if (size32) { 505 error = copyin(SCARG_P32(uap, data), data32, size32); 506 if (error) { 507 if (memp32) 508 kmem_free(memp32, (size_t)size32); 509 goto out; 510 } 511 ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data), 512 size32, 0); 513 } else 514 *(void **)data32 = SCARG_P32(uap, data); 515 } else if ((com&IOC_OUT) && size32) 516 /* 517 * Zero the buffer so the user always 518 * gets back something deterministic. 519 */ 520 memset(data32, 0, size32); 521 else if (com&IOC_VOID) 522 *(void **)data32 = SCARG_P32(uap, data); 523 524 /* 525 * convert various structures, pointers, and other objects that 526 * change size from 32 bit -> 64 bit, for all ioctl commands. 527 */ 528 switch (SCARG(uap, com)) { 529 case FIONBIO: 530 mutex_enter(&fp->f_lock); 531 if ((tmp = *(int *)data32) != 0) 532 fp->f_flag |= FNONBLOCK; 533 else 534 fp->f_flag &= ~FNONBLOCK; 535 mutex_exit(&fp->f_lock); 536 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (void *)&tmp); 537 break; 538 539 case FIOASYNC: 540 mutex_enter(&fp->f_lock); 541 if ((tmp = *(int *)data32) != 0) 542 fp->f_flag |= FASYNC; 543 else 544 fp->f_flag &= ~FASYNC; 545 mutex_exit(&fp->f_lock); 546 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (void *)&tmp); 547 break; 548 549 case AUDIO_WSEEK32: 550 IOCTL_CONV_TO(AUDIO_WSEEK, u_long); 551 552 case DIOCGPART32: 553 IOCTL_STRUCT_CONV_TO(DIOCGPART, partinfo); 554 #if 0 /* not implemented by anything */ 555 case DIOCRFORMAT32: 556 IOCTL_STRUCT_CONV_TO(DIOCRFORMAT, format_op); 557 case DIOCWFORMAT32: 558 IOCTL_STRUCT_CONV_TO(DIOCWFORMAT, format_op); 559 #endif 560 561 /* 562 * only a few ifreq syscalls need conversion and those are 563 * all driver specific... XXX 564 */ 565 #if 0 566 case SIOCGADDRROM3232: 567 IOCTL_STRUCT_CONV_TO(SIOCGADDRROM32, ifreq); 568 case SIOCGCHIPID32: 569 IOCTL_STRUCT_CONV_TO(SIOCGCHIPID, ifreq); 570 case SIOCSIFADDR32: 571 IOCTL_STRUCT_CONV_TO(SIOCSIFADDR, ifreq); 572 case OSIOCGIFADDR32: 573 IOCTL_STRUCT_CONV_TO(OSIOCGIFADDR, ifreq); 574 case SIOCGIFADDR32: 575 IOCTL_STRUCT_CONV_TO(SIOCGIFADDR, ifreq); 576 case SIOCSIFDSTADDR32: 577 IOCTL_STRUCT_CONV_TO(SIOCSIFDSTADDR, ifreq); 578 case OSIOCGIFDSTADDR32: 579 IOCTL_STRUCT_CONV_TO(OSIOCGIFDSTADDR, ifreq); 580 case SIOCGIFDSTADDR32: 581 IOCTL_STRUCT_CONV_TO(SIOCGIFDSTADDR, ifreq); 582 case OSIOCGIFBRDADDR32: 583 IOCTL_STRUCT_CONV_TO(OSIOCGIFBRDADDR, ifreq); 584 case SIOCGIFBRDADDR32: 585 IOCTL_STRUCT_CONV_TO(SIOCGIFBRDADDR, ifreq); 586 case SIOCSIFBRDADDR32: 587 IOCTL_STRUCT_CONV_TO(SIOCSIFBRDADDR, ifreq); 588 case OSIOCGIFNETMASK32: 589 IOCTL_STRUCT_CONV_TO(OSIOCGIFNETMASK, ifreq); 590 case SIOCGIFNETMASK32: 591 IOCTL_STRUCT_CONV_TO(SIOCGIFNETMASK, ifreq); 592 case SIOCSIFNETMASK32: 593 IOCTL_STRUCT_CONV_TO(SIOCSIFNETMASK, ifreq); 594 case SIOCGIFMETRIC32: 595 IOCTL_STRUCT_CONV_TO(SIOCGIFMETRIC, ifreq); 596 case SIOCSIFMETRIC32: 597 IOCTL_STRUCT_CONV_TO(SIOCSIFMETRIC, ifreq); 598 case SIOCDIFADDR32: 599 IOCTL_STRUCT_CONV_TO(SIOCDIFADDR, ifreq); 600 case SIOCADDMULTI32: 601 IOCTL_STRUCT_CONV_TO(SIOCADDMULTI, ifreq); 602 case SIOCDELMULTI32: 603 IOCTL_STRUCT_CONV_TO(SIOCDELMULTI, ifreq); 604 case SIOCSIFMEDIA32: 605 IOCTL_STRUCT_CONV_TO(SIOCSIFMEDIA, ifreq); 606 case SIOCSIFMTU32: 607 IOCTL_STRUCT_CONV_TO(SIOCSIFMTU, ifreq); 608 case SIOCGIFMTU32: 609 IOCTL_STRUCT_CONV_TO(SIOCGIFMTU, ifreq); 610 case BIOCGETIF32: 611 IOCTL_STRUCT_CONV_TO(BIOCGETIF, ifreq); 612 case BIOCSETIF32: 613 IOCTL_STRUCT_CONV_TO(BIOCSETIF, ifreq); 614 case SIOCPHASE132: 615 IOCTL_STRUCT_CONV_TO(SIOCPHASE1, ifreq); 616 case SIOCPHASE232: 617 IOCTL_STRUCT_CONV_TO(SIOCPHASE2, ifreq); 618 #endif 619 620 case OOSIOCGIFCONF32: 621 IOCTL_STRUCT_CONV_TO(OOSIOCGIFCONF, ifconf); 622 case OSIOCGIFCONF32: 623 IOCTL_STRUCT_CONV_TO(OSIOCGIFCONF, ifconf); 624 case SIOCGIFCONF32: 625 IOCTL_STRUCT_CONV_TO(SIOCGIFCONF, ifconf); 626 627 case SIOCGIFFLAGS32: 628 IOCTL_STRUCT_CONV_TO(SIOCGIFFLAGS, ifreq); 629 case SIOCSIFFLAGS32: 630 IOCTL_STRUCT_CONV_TO(SIOCSIFFLAGS, ifreq); 631 632 case OSIOCGIFFLAGS32: 633 IOCTL_STRUCT_CONV_TO(OSIOCGIFFLAGS, oifreq); 634 case OSIOCSIFFLAGS32: 635 IOCTL_STRUCT_CONV_TO(OSIOCSIFFLAGS, oifreq); 636 637 case SIOCGIFMEDIA32: 638 IOCTL_STRUCT_CONV_TO(SIOCGIFMEDIA, ifmediareq); 639 640 case SIOCSDRVSPEC32: 641 IOCTL_STRUCT_CONV_TO(SIOCSDRVSPEC, ifdrv); 642 643 case SIOCGETVIFCNT32: 644 IOCTL_STRUCT_CONV_TO(SIOCGETVIFCNT, sioc_vif_req); 645 646 case SIOCGETSGCNT32: 647 IOCTL_STRUCT_CONV_TO(SIOCGETSGCNT, sioc_sg_req); 648 649 case VNDIOCSET32: 650 IOCTL_STRUCT_CONV_TO(VNDIOCSET, vnd_ioctl); 651 652 case VNDIOCCLR32: 653 IOCTL_STRUCT_CONV_TO(VNDIOCCLR, vnd_ioctl); 654 655 case VNDIOCGET32: 656 IOCTL_STRUCT_CONV_TO(VNDIOCGET, vnd_user); 657 658 case VNDIOCSET5032: 659 IOCTL_STRUCT_CONV_TO(VNDIOCSET50, vnd_ioctl50); 660 661 case VNDIOCCLR5032: 662 IOCTL_STRUCT_CONV_TO(VNDIOCCLR50, vnd_ioctl50); 663 664 case ENVSYS_GETDICTIONARY32: 665 IOCTL_STRUCT_CONV_TO(ENVSYS_GETDICTIONARY, plistref); 666 case ENVSYS_SETDICTIONARY32: 667 IOCTL_STRUCT_CONV_TO(ENVSYS_SETDICTIONARY, plistref); 668 case ENVSYS_REMOVEPROPS32: 669 IOCTL_STRUCT_CONV_TO(ENVSYS_REMOVEPROPS, plistref); 670 671 default: 672 #ifdef NETBSD32_MD_IOCTL 673 error = netbsd32_md_ioctl(fp, com, data32, l); 674 #else 675 error = (*fp->f_ops->fo_ioctl)(fp, com, data32); 676 #endif 677 break; 678 } 679 680 if (error == EPASSTHROUGH) 681 error = ENOTTY; 682 683 /* 684 * Copy any data to user, size was 685 * already set and checked above. 686 */ 687 if (error == 0 && (com&IOC_OUT) && size32) { 688 error = copyout(data32, SCARG_P32(uap, data), size32); 689 ktrgenio(fd, UIO_READ, SCARG_P32(uap, data), 690 size32, error); 691 } 692 693 /* If we allocated data, free it here. */ 694 if (memp32) 695 kmem_free(memp32, (size_t)size32); 696 if (memp) 697 kmem_free(memp, (size_t)size); 698 out: 699 fd_putfile(fd); 700 return (error); 701 } 702