1 /* $NetBSD: netbsd32_ioctl.c,v 1.53 2011/01/22 20:51:21 matt 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.53 2011/01/22 20:51:21 matt 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 size_t size; 441 size_t alloc_size32, size32; 442 void *data, *memp = NULL; 443 void *data32, *memp32 = NULL; 444 unsigned int fd; 445 fdfile_t *ff; 446 int tmp; 447 #define STK_PARAMS 128 448 u_long stkbuf[STK_PARAMS/sizeof(u_long)]; 449 u_long stkbuf32[STK_PARAMS/sizeof(u_long)]; 450 451 /* 452 * we need to translate some commands (_IOW) before calling sys_ioctl, 453 * some after (_IOR), and some both (_IOWR). 454 */ 455 #if 0 456 { 457 const char * const dirs[8] = { 458 "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!", 459 "INOUT", "VOID|IN|OUT!" 460 }; 461 462 printf("netbsd32_ioctl(%d, %x, %x): " 463 "%s group %c base %d len %d\n", 464 SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data).i32, 465 dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)], 466 IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)), 467 IOCPARM_LEN(SCARG(uap, com))); 468 } 469 #endif 470 471 memp = NULL; 472 memp32 = NULL; 473 alloc_size32 = 0; 474 size32 = 0; 475 size = 0; 476 477 fdp = p->p_fd; 478 fd = SCARG(uap, fd); 479 if ((fp = fd_getfile(fd)) == NULL) 480 return (EBADF); 481 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 482 error = EBADF; 483 goto out; 484 } 485 486 ff = fdp->fd_dt->dt_ff[SCARG(uap, fd)]; 487 switch (com = SCARG(uap, com)) { 488 case FIOCLEX: 489 ff->ff_exclose = true; 490 fdp->fd_exclose = true; 491 goto out; 492 493 case FIONCLEX: 494 ff->ff_exclose = false; 495 goto out; 496 } 497 498 /* 499 * Interpret high order word to find amount of data to be 500 * copied to/from the user's address space. 501 */ 502 size32 = IOCPARM_LEN(com); 503 alloc_size32 = size32; 504 505 /* 506 * The disklabel is now padded to a multiple of 8 bytes however the old 507 * disklabel on 32bit platforms wasn't. This leaves a difference in 508 * size of 4 bytes between the two but are otherwise identical. 509 * To deal with this, we allocate enough space for the new disklabel 510 * but only copyin/out the smaller amount. 511 */ 512 if (IOCGROUP(com) == 'd') { 513 u_long ncom = com ^ (DIOCGDINFO ^ DIOCGDINFO32); 514 switch (ncom) { 515 case DIOCGDINFO: 516 case DIOCWDINFO: 517 case DIOCSDINFO: 518 case DIOCGDEFLABEL: 519 com = ncom; 520 if (IOCPARM_LEN(DIOCGDINFO32) < IOCPARM_LEN(DIOCGDINFO)) 521 alloc_size32 = IOCPARM_LEN(DIOCGDINFO); 522 break; 523 } 524 } 525 if (alloc_size32 > IOCPARM_MAX) { 526 error = ENOTTY; 527 goto out; 528 } 529 if (alloc_size32 > sizeof(stkbuf)) { 530 memp32 = kmem_alloc(alloc_size32, KM_SLEEP); 531 data32 = memp32; 532 } else 533 data32 = (void *)stkbuf32; 534 if ((com >> IOCPARM_SHIFT) == 0) { 535 /* UNIX-style ioctl. */ 536 data32 = SCARG_P32(uap, data); 537 } else { 538 if (com&IOC_IN) { 539 if (size32) { 540 error = copyin(SCARG_P32(uap, data), data32, 541 size32); 542 if (error) { 543 goto out; 544 } 545 /* 546 * The data between size and alloc_size has 547 * not been overwritten. It shouldn't matter 548 * but let's clear that anyway. 549 */ 550 if (__predict_false(size32 < alloc_size32)) { 551 memset((char *)data32+size32, 0, 552 alloc_size32 - size32); 553 } 554 ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data), 555 size32, 0); 556 } else 557 *(void **)data32 = SCARG_P32(uap, data); 558 } else if ((com&IOC_OUT) && size32) { 559 /* 560 * Zero the buffer so the user always 561 * gets back something deterministic. 562 */ 563 memset(data32, 0, alloc_size32); 564 } else if (com&IOC_VOID) { 565 *(void **)data32 = SCARG_P32(uap, data); 566 } 567 } 568 569 /* 570 * convert various structures, pointers, and other objects that 571 * change size from 32 bit -> 64 bit, for all ioctl commands. 572 */ 573 switch (SCARG(uap, com)) { 574 case FIONBIO: 575 mutex_enter(&fp->f_lock); 576 if ((tmp = *(int *)data32) != 0) 577 fp->f_flag |= FNONBLOCK; 578 else 579 fp->f_flag &= ~FNONBLOCK; 580 mutex_exit(&fp->f_lock); 581 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (void *)&tmp); 582 break; 583 584 case FIOASYNC: 585 mutex_enter(&fp->f_lock); 586 if ((tmp = *(int *)data32) != 0) 587 fp->f_flag |= FASYNC; 588 else 589 fp->f_flag &= ~FASYNC; 590 mutex_exit(&fp->f_lock); 591 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (void *)&tmp); 592 break; 593 594 case AUDIO_WSEEK32: 595 IOCTL_CONV_TO(AUDIO_WSEEK, u_long); 596 597 case DIOCGPART32: 598 IOCTL_STRUCT_CONV_TO(DIOCGPART, partinfo); 599 #if 0 /* not implemented by anything */ 600 case DIOCRFORMAT32: 601 IOCTL_STRUCT_CONV_TO(DIOCRFORMAT, format_op); 602 case DIOCWFORMAT32: 603 IOCTL_STRUCT_CONV_TO(DIOCWFORMAT, format_op); 604 #endif 605 606 /* 607 * only a few ifreq syscalls need conversion and those are 608 * all driver specific... XXX 609 */ 610 #if 0 611 case SIOCGADDRROM3232: 612 IOCTL_STRUCT_CONV_TO(SIOCGADDRROM32, ifreq); 613 case SIOCGCHIPID32: 614 IOCTL_STRUCT_CONV_TO(SIOCGCHIPID, ifreq); 615 case SIOCSIFADDR32: 616 IOCTL_STRUCT_CONV_TO(SIOCSIFADDR, ifreq); 617 case OSIOCGIFADDR32: 618 IOCTL_STRUCT_CONV_TO(OSIOCGIFADDR, ifreq); 619 case SIOCGIFADDR32: 620 IOCTL_STRUCT_CONV_TO(SIOCGIFADDR, ifreq); 621 case SIOCSIFDSTADDR32: 622 IOCTL_STRUCT_CONV_TO(SIOCSIFDSTADDR, ifreq); 623 case OSIOCGIFDSTADDR32: 624 IOCTL_STRUCT_CONV_TO(OSIOCGIFDSTADDR, ifreq); 625 case SIOCGIFDSTADDR32: 626 IOCTL_STRUCT_CONV_TO(SIOCGIFDSTADDR, ifreq); 627 case OSIOCGIFBRDADDR32: 628 IOCTL_STRUCT_CONV_TO(OSIOCGIFBRDADDR, ifreq); 629 case SIOCGIFBRDADDR32: 630 IOCTL_STRUCT_CONV_TO(SIOCGIFBRDADDR, ifreq); 631 case SIOCSIFBRDADDR32: 632 IOCTL_STRUCT_CONV_TO(SIOCSIFBRDADDR, ifreq); 633 case OSIOCGIFNETMASK32: 634 IOCTL_STRUCT_CONV_TO(OSIOCGIFNETMASK, ifreq); 635 case SIOCGIFNETMASK32: 636 IOCTL_STRUCT_CONV_TO(SIOCGIFNETMASK, ifreq); 637 case SIOCSIFNETMASK32: 638 IOCTL_STRUCT_CONV_TO(SIOCSIFNETMASK, ifreq); 639 case SIOCGIFMETRIC32: 640 IOCTL_STRUCT_CONV_TO(SIOCGIFMETRIC, ifreq); 641 case SIOCSIFMETRIC32: 642 IOCTL_STRUCT_CONV_TO(SIOCSIFMETRIC, ifreq); 643 case SIOCDIFADDR32: 644 IOCTL_STRUCT_CONV_TO(SIOCDIFADDR, ifreq); 645 case SIOCADDMULTI32: 646 IOCTL_STRUCT_CONV_TO(SIOCADDMULTI, ifreq); 647 case SIOCDELMULTI32: 648 IOCTL_STRUCT_CONV_TO(SIOCDELMULTI, ifreq); 649 case SIOCSIFMEDIA32: 650 IOCTL_STRUCT_CONV_TO(SIOCSIFMEDIA, ifreq); 651 case SIOCSIFMTU32: 652 IOCTL_STRUCT_CONV_TO(SIOCSIFMTU, ifreq); 653 case SIOCGIFMTU32: 654 IOCTL_STRUCT_CONV_TO(SIOCGIFMTU, ifreq); 655 case BIOCGETIF32: 656 IOCTL_STRUCT_CONV_TO(BIOCGETIF, ifreq); 657 case BIOCSETIF32: 658 IOCTL_STRUCT_CONV_TO(BIOCSETIF, ifreq); 659 case SIOCPHASE132: 660 IOCTL_STRUCT_CONV_TO(SIOCPHASE1, ifreq); 661 case SIOCPHASE232: 662 IOCTL_STRUCT_CONV_TO(SIOCPHASE2, ifreq); 663 #endif 664 665 case OOSIOCGIFCONF32: 666 IOCTL_STRUCT_CONV_TO(OOSIOCGIFCONF, ifconf); 667 case OSIOCGIFCONF32: 668 IOCTL_STRUCT_CONV_TO(OSIOCGIFCONF, ifconf); 669 case SIOCGIFCONF32: 670 IOCTL_STRUCT_CONV_TO(SIOCGIFCONF, ifconf); 671 672 case SIOCGIFFLAGS32: 673 IOCTL_STRUCT_CONV_TO(SIOCGIFFLAGS, ifreq); 674 case SIOCSIFFLAGS32: 675 IOCTL_STRUCT_CONV_TO(SIOCSIFFLAGS, ifreq); 676 677 case OSIOCGIFFLAGS32: 678 IOCTL_STRUCT_CONV_TO(OSIOCGIFFLAGS, oifreq); 679 case OSIOCSIFFLAGS32: 680 IOCTL_STRUCT_CONV_TO(OSIOCSIFFLAGS, oifreq); 681 682 case SIOCGIFMEDIA32: 683 IOCTL_STRUCT_CONV_TO(SIOCGIFMEDIA, ifmediareq); 684 685 case SIOCSDRVSPEC32: 686 IOCTL_STRUCT_CONV_TO(SIOCSDRVSPEC, ifdrv); 687 688 case SIOCGETVIFCNT32: 689 IOCTL_STRUCT_CONV_TO(SIOCGETVIFCNT, sioc_vif_req); 690 691 case SIOCGETSGCNT32: 692 IOCTL_STRUCT_CONV_TO(SIOCGETSGCNT, sioc_sg_req); 693 694 case VNDIOCSET32: 695 IOCTL_STRUCT_CONV_TO(VNDIOCSET, vnd_ioctl); 696 697 case VNDIOCCLR32: 698 IOCTL_STRUCT_CONV_TO(VNDIOCCLR, vnd_ioctl); 699 700 case VNDIOCGET32: 701 IOCTL_STRUCT_CONV_TO(VNDIOCGET, vnd_user); 702 703 case VNDIOCSET5032: 704 IOCTL_STRUCT_CONV_TO(VNDIOCSET50, vnd_ioctl50); 705 706 case VNDIOCCLR5032: 707 IOCTL_STRUCT_CONV_TO(VNDIOCCLR50, vnd_ioctl50); 708 709 case ENVSYS_GETDICTIONARY32: 710 IOCTL_STRUCT_CONV_TO(ENVSYS_GETDICTIONARY, plistref); 711 case ENVSYS_SETDICTIONARY32: 712 IOCTL_STRUCT_CONV_TO(ENVSYS_SETDICTIONARY, plistref); 713 case ENVSYS_REMOVEPROPS32: 714 IOCTL_STRUCT_CONV_TO(ENVSYS_REMOVEPROPS, plistref); 715 716 default: 717 #ifdef NETBSD32_MD_IOCTL 718 error = netbsd32_md_ioctl(fp, com, data32, l); 719 #else 720 error = (*fp->f_ops->fo_ioctl)(fp, com, data32); 721 #endif 722 break; 723 } 724 725 if (error == EPASSTHROUGH) 726 error = ENOTTY; 727 728 /* 729 * Copy any data to user, size was 730 * already set and checked above. 731 */ 732 if (error == 0 && (com&IOC_OUT) && size32) { 733 error = copyout(data32, SCARG_P32(uap, data), size32); 734 ktrgenio(fd, UIO_READ, SCARG_P32(uap, data), 735 size32, error); 736 } 737 738 out: 739 /* If we allocated data, free it here. */ 740 if (memp32) 741 kmem_free(memp32, alloc_size32); 742 if (memp) 743 kmem_free(memp, size); 744 fd_putfile(fd); 745 return (error); 746 } 747