Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_ioctl.c revision 1.51
      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