Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_ioctl.c revision 1.68
      1 /*	$NetBSD: netbsd32_ioctl.c,v 1.68 2014/01/24 10:41:07 manu 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.68 2014/01/24 10:41:07 manu 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/ataio.h>
     47 #include <sys/sockio.h>
     48 #include <sys/socket.h>
     49 #include <sys/ttycom.h>
     50 #include <sys/mount.h>
     51 #include <sys/syscallargs.h>
     52 #include <sys/ktrace.h>
     53 #include <sys/kmem.h>
     54 #include <sys/envsys.h>
     55 #include <sys/wdog.h>
     56 #include <sys/clockctl.h>
     57 
     58 #ifdef __sparc__
     59 #include <dev/sun/fbio.h>
     60 #include <machine/openpromio.h>
     61 #endif
     62 
     63 #include <net/if.h>
     64 #include <net/route.h>
     65 
     66 #include <net/bpf.h>
     67 #include <netinet/in.h>
     68 #include <netinet/in_var.h>
     69 #include <netinet/igmp.h>
     70 #include <netinet/igmp_var.h>
     71 #include <netinet/ip_mroute.h>
     72 
     73 #include <compat/sys/sockio.h>
     74 
     75 #include <compat/netbsd32/netbsd32.h>
     76 #include <compat/netbsd32/netbsd32_ioctl.h>
     77 #include <compat/netbsd32/netbsd32_syscallargs.h>
     78 
     79 #include <dev/vndvar.h>
     80 
     81 /* convert to/from different structures */
     82 
     83 static inline void
     84 netbsd32_to_partinfo(struct netbsd32_partinfo *s32p, struct partinfo *p, u_long cmd)
     85 {
     86 
     87 	p->disklab = (struct disklabel *)NETBSD32PTR64(s32p->disklab);
     88 	p->part = (struct partition *)NETBSD32PTR64(s32p->part);
     89 }
     90 
     91 #if 0
     92 static inline void
     93 netbsd32_to_format_op(struct netbsd32_format_op *s32p, struct format_op *p, u_long cmd)
     94 {
     95 
     96 	p->df_buf = (char *)NETBSD32PTR64(s32p->df_buf);
     97 	p->df_count = s32p->df_count;
     98 	p->df_startblk = s32p->df_startblk;
     99 	memcpy(p->df_reg, s32p->df_reg, sizeof(s32p->df_reg));
    100 }
    101 #endif
    102 
    103 static inline void
    104 netbsd32_to_ifreq(struct netbsd32_ifreq *s32p, struct ifreq *p, u_long cmd)
    105 {
    106 
    107 	memcpy(p, s32p, sizeof *s32p);
    108 	/*
    109 	 * XXX
    110 	 * struct ifreq says the same, but sometimes the ifr_data
    111 	 * union member needs to be converted to 64 bits... this
    112 	 * is very driver specific and so we ignore it for now..
    113 	 */
    114 	if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA)
    115 		p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data);
    116 }
    117 
    118 static inline void
    119 netbsd32_to_oifreq(struct netbsd32_oifreq *s32p, struct oifreq *p, u_long cmd)
    120 {
    121 
    122 	memcpy(p, s32p, sizeof *s32p);
    123 	/*
    124 	 * XXX
    125 	 * struct ifreq says the same, but sometimes the ifr_data
    126 	 * union member needs to be converted to 64 bits... this
    127 	 * is very driver specific and so we ignore it for now..
    128 	 */
    129 	if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA)
    130 		p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data);
    131 }
    132 
    133 static inline void
    134 netbsd32_to_if_addrprefreq(const struct netbsd32_if_addrprefreq *ifap32,
    135 	struct if_addrprefreq *ifap, u_long cmd)
    136 {
    137 	strlcpy(ifap->ifap_name, ifap32->ifap_name, sizeof(ifap->ifap_name));
    138 	ifap->ifap_preference = ifap32->ifap_preference;
    139 	memcpy(&ifap->ifap_addr, &ifap32->ifap_addr,
    140 	    max(ifap32->ifap_addr.ss_len, _SS_MAXSIZE));
    141 }
    142 
    143 static inline void
    144 netbsd32_to_ifconf(struct netbsd32_ifconf *s32p, struct ifconf *p, u_long cmd)
    145 {
    146 
    147 	p->ifc_len = s32p->ifc_len;
    148 	/* ifc_buf & ifc_req are the same size so this works */
    149 	p->ifc_buf = (void *)NETBSD32PTR64(s32p->ifc_buf);
    150 }
    151 
    152 static inline void
    153 netbsd32_to_ifmediareq(struct netbsd32_ifmediareq *s32p, struct ifmediareq *p, u_long cmd)
    154 {
    155 
    156 	memcpy(p, s32p, sizeof *s32p);
    157 	p->ifm_ulist = (int *)NETBSD32PTR64(s32p->ifm_ulist);
    158 }
    159 
    160 static inline void
    161 netbsd32_to_ifdrv(struct netbsd32_ifdrv *s32p, struct ifdrv *p, u_long cmd)
    162 {
    163 
    164 	memcpy(p, s32p, sizeof *s32p);
    165 	p->ifd_data = (void *)NETBSD32PTR64(s32p->ifd_data);
    166 }
    167 
    168 static inline void
    169 netbsd32_to_sioc_vif_req(struct netbsd32_sioc_vif_req *s32p, struct sioc_vif_req *p, u_long cmd)
    170 {
    171 
    172 	p->vifi = s32p->vifi;
    173 	p->icount = (u_long)s32p->icount;
    174 	p->ocount = (u_long)s32p->ocount;
    175 	p->ibytes = (u_long)s32p->ibytes;
    176 	p->obytes = (u_long)s32p->obytes;
    177 }
    178 
    179 static inline void
    180 netbsd32_to_sioc_sg_req(struct netbsd32_sioc_sg_req *s32p, struct sioc_sg_req *p, u_long cmd)
    181 {
    182 
    183 	p->src = s32p->src;
    184 	p->grp = s32p->grp;
    185 	p->pktcnt = (u_long)s32p->pktcnt;
    186 	p->bytecnt = (u_long)s32p->bytecnt;
    187 	p->wrong_if = (u_long)s32p->wrong_if;
    188 }
    189 
    190 static inline void
    191 netbsd32_to_atareq(struct netbsd32_atareq *s32p, struct atareq *p, u_long cmd)
    192 {
    193 	p->flags = (u_long)s32p->flags;
    194 	p->command = s32p->command;
    195 	p->features = s32p->features;
    196 	p->sec_count = s32p->sec_count;
    197 	p->sec_num = s32p->sec_num;
    198 	p->head = s32p->head;
    199 	p->cylinder = s32p->cylinder;
    200 	p->databuf =  (char *)NETBSD32PTR64(s32p->databuf);
    201 	p->datalen = (u_long)s32p->datalen;
    202 	p->timeout = s32p->timeout;
    203 	p->retsts = s32p->retsts;
    204 	p->error = s32p->error;
    205 }
    206 
    207 static inline void
    208 netbsd32_to_vnd_ioctl(struct netbsd32_vnd_ioctl *s32p, struct vnd_ioctl *p, u_long cmd)
    209 {
    210 
    211 	p->vnd_file = (char *)NETBSD32PTR64(s32p->vnd_file);
    212 	p->vnd_flags = s32p->vnd_flags;
    213 	p->vnd_geom = s32p->vnd_geom;
    214 	p->vnd_osize = s32p->vnd_osize;
    215 	p->vnd_size = s32p->vnd_size;
    216 }
    217 
    218 static inline void
    219 netbsd32_to_vnd_user(struct netbsd32_vnd_user *s32p, struct vnd_user *p, u_long cmd)
    220 {
    221 
    222 	p->vnu_unit = s32p->vnu_unit;
    223 	p->vnu_dev = s32p->vnu_dev;
    224 	p->vnu_ino = s32p->vnu_ino;
    225 }
    226 
    227 static inline void
    228 netbsd32_to_vnd_ioctl50(struct netbsd32_vnd_ioctl50 *s32p, struct vnd_ioctl50 *p, u_long cmd)
    229 {
    230 
    231 	p->vnd_file = (char *)NETBSD32PTR64(s32p->vnd_file);
    232 	p->vnd_flags = s32p->vnd_flags;
    233 	p->vnd_geom = s32p->vnd_geom;
    234 	p->vnd_size = s32p->vnd_size;
    235 }
    236 
    237 static inline void
    238 netbsd32_to_plistref(struct netbsd32_plistref *s32p, struct plistref *p, u_long cmd)
    239 {
    240 
    241 	p->pref_plist = NETBSD32PTR64(s32p->pref_plist);
    242 	p->pref_len = s32p->pref_len;
    243 }
    244 
    245 static inline void
    246 netbsd32_to_u_long(netbsd32_u_long *s32p, u_long *p, u_long cmd)
    247 {
    248 
    249 	*p = (u_long)*s32p;
    250 }
    251 
    252 static inline void
    253 netbsd32_to_wdog_conf(struct netbsd32_wdog_conf *s32p, struct wdog_conf *p, u_long cmd)
    254 {
    255 
    256 	p->wc_names = (char *)NETBSD32PTR64(s32p->wc_names);
    257 	p->wc_count = s32p->wc_count;
    258 }
    259 
    260 static inline void
    261 netbsd32_to_bpf_program(struct netbsd32_bpf_program *s32p, struct bpf_program *p, u_long cmd)
    262 {
    263 
    264 	p->bf_insns = (void *)NETBSD32PTR64(s32p->bf_insns);
    265 	p->bf_len = s32p->bf_len;
    266 }
    267 
    268 static inline void
    269 netbsd32_to_bpf_dltlist(struct netbsd32_bpf_dltlist *s32p, struct bpf_dltlist *p, u_long cmd)
    270 {
    271 
    272 	p->bfl_list = (void *)NETBSD32PTR64(s32p->bfl_list);
    273 	p->bfl_len = s32p->bfl_len;
    274 }
    275 
    276 /* wsdisplay stuff */
    277 static inline void
    278 netbsd32_to_wsdisplay_addscreendata(struct netbsd32_wsdisplay_addscreendata *asd32,
    279 					       struct wsdisplay_addscreendata *asd,
    280 					       u_long cmd)
    281 {
    282 	asd->screentype = (char *)NETBSD32PTR64(asd32->screentype);
    283 	asd->emul = (char *)NETBSD32PTR64(asd32->emul);
    284 	asd->idx = asd32->idx;
    285 }
    286 
    287 static inline void
    288 netbsd32_to_ieee80211req(struct netbsd32_ieee80211req *ireq32,
    289 			 struct ieee80211req *ireq, u_long cmd)
    290 {
    291 	strncpy(ireq->i_name, ireq32->i_name, IFNAMSIZ);
    292 	ireq->i_type = ireq32->i_type;
    293 	ireq->i_val = ireq32->i_val;
    294 	ireq->i_len = ireq32->i_len;
    295 	ireq->i_data = NETBSD32PTR64(ireq32->i_data);
    296 }
    297 
    298 static inline void
    299 netbsd32_to_ieee80211_nwkey(struct netbsd32_ieee80211_nwkey *nwk32,
    300 					       struct ieee80211_nwkey *nwk,
    301 					       u_long cmd)
    302 {
    303 	int i;
    304 
    305 	strncpy(nwk->i_name, nwk32->i_name, IFNAMSIZ);
    306 	nwk->i_wepon = nwk32->i_wepon;
    307 	nwk->i_defkid = nwk32->i_defkid;
    308 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    309 		nwk->i_key[i].i_keylen = nwk32->i_key[i].i_keylen;
    310 		nwk->i_key[i].i_keydat =
    311 		    NETBSD32PTR64(nwk32->i_key[i].i_keydat);
    312 	}
    313 }
    314 
    315 static inline void
    316 netbsd32_to_wsdisplay_cursor(struct netbsd32_wsdisplay_cursor *c32,
    317 					       struct wsdisplay_cursor *c,
    318 					       u_long cmd)
    319 {
    320 	c->which = c32->which;
    321 	c->enable = c32->enable;
    322 	c->pos.x = c32->pos.x;
    323 	c->pos.y = c32->pos.y;
    324 	c->hot.x = c32->hot.x;
    325 	c->hot.y = c32->hot.y;
    326 	c->size.x = c32->size.x;
    327 	c->size.y = c32->size.y;
    328 	c->cmap.index = c32->cmap.index;
    329 	c->cmap.count = c32->cmap.count;
    330 	c->cmap.red = NETBSD32PTR64(c32->cmap.red);
    331 	c->cmap.green = NETBSD32PTR64(c32->cmap.green);
    332 	c->cmap.blue = NETBSD32PTR64(c32->cmap.blue);
    333 	c->image = NETBSD32PTR64(c32->image);
    334 	c->mask = NETBSD32PTR64(c32->mask);
    335 }
    336 
    337 static inline void
    338 netbsd32_to_clockctl_settimeofday(
    339     const struct netbsd32_clockctl_settimeofday *s32p,
    340     struct clockctl_settimeofday *p,
    341     u_long cmd)
    342 {
    343 
    344 	p->tv = NETBSD32PTR64(s32p->tv);
    345 	p->tzp = NETBSD32PTR64(s32p->tzp);
    346 }
    347 
    348 static inline void
    349 netbsd32_to_clockctl_adjtime(
    350     const struct netbsd32_clockctl_adjtime *s32p,
    351     struct clockctl_adjtime *p,
    352     u_long cmd)
    353 {
    354 
    355 	p->delta = NETBSD32PTR64(s32p->delta);
    356 	p->olddelta = NETBSD32PTR64(s32p->olddelta);
    357 }
    358 
    359 static inline void
    360 netbsd32_to_clockctl_clock_settime(
    361     const struct netbsd32_clockctl_clock_settime *s32p,
    362     struct clockctl_clock_settime *p,
    363     u_long cmd)
    364 {
    365 
    366 	p->clock_id = s32p->clock_id;
    367 	p->tp = NETBSD32PTR64(s32p->tp);
    368 }
    369 
    370 static inline void
    371 netbsd32_to_clockctl_ntp_adjtime(
    372     const struct netbsd32_clockctl_ntp_adjtime *s32p,
    373     struct clockctl_ntp_adjtime *p,
    374     u_long cmd)
    375 {
    376 
    377 	p->tp = NETBSD32PTR64(s32p->tp);
    378 	p->retval = s32p->retval;
    379 }
    380 
    381 /*
    382  * handle ioctl conversions from 64-bit kernel -> netbsd32
    383  */
    384 
    385 static inline void
    386 netbsd32_from_partinfo(struct partinfo *p, struct netbsd32_partinfo *s32p, u_long cmd)
    387 {
    388 
    389 	NETBSD32PTR32(s32p->disklab, p->disklab);
    390 	NETBSD32PTR32(s32p->part, p->part);
    391 }
    392 
    393 #if 0
    394 static inline void
    395 netbsd32_from_format_op(struct format_op *p, struct netbsd32_format_op *s32p, u_long cmd)
    396 {
    397 
    398 /* filled in */
    399 #if 0
    400 	s32p->df_buf = (netbsd32_charp)p->df_buf;
    401 #endif
    402 	s32p->df_count = p->df_count;
    403 	s32p->df_startblk = p->df_startblk;
    404 	memcpy(s32p->df_reg, p->df_reg, sizeof(p->df_reg));
    405 }
    406 #endif
    407 
    408 static inline void
    409 netbsd32_from_ifreq(struct ifreq *p, struct netbsd32_ifreq *s32p, u_long cmd)
    410 {
    411 
    412 	/*
    413 	 * XXX
    414 	 * struct ifreq says the same, but sometimes the ifr_data
    415 	 * union member needs to be converted to 64 bits... this
    416 	 * is very driver specific and so we ignore it for now..
    417 	 */
    418 	memcpy(s32p, p, sizeof *s32p);
    419 	if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA)
    420 		NETBSD32PTR32(s32p->ifr_data, p->ifr_data);
    421 }
    422 
    423 static inline void
    424 netbsd32_from_oifreq(struct oifreq *p, struct netbsd32_oifreq *s32p, u_long cmd)
    425 {
    426 
    427 	/*
    428 	 * XXX
    429 	 * struct ifreq says the same, but sometimes the ifr_data
    430 	 * union member needs to be converted to 64 bits... this
    431 	 * is very driver specific and so we ignore it for now..
    432 	 */
    433 	memcpy(s32p, p, sizeof *s32p);
    434 	if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA)
    435 		NETBSD32PTR32(s32p->ifr_data, p->ifr_data);
    436 }
    437 
    438 static inline void
    439 netbsd32_from_if_addrprefreq(const struct if_addrprefreq *ifap,
    440 	struct netbsd32_if_addrprefreq *ifap32, u_long cmd)
    441 {
    442 	strlcpy(ifap32->ifap_name, ifap->ifap_name, sizeof(ifap32->ifap_name));
    443 	ifap32->ifap_preference = ifap->ifap_preference;
    444 	memcpy(&ifap32->ifap_addr, &ifap->ifap_addr,
    445 	    max(ifap->ifap_addr.ss_len, _SS_MAXSIZE));
    446 }
    447 
    448 static inline void
    449 netbsd32_from_ifconf(struct ifconf *p, struct netbsd32_ifconf *s32p, u_long cmd)
    450 {
    451 
    452 	s32p->ifc_len = p->ifc_len;
    453 	/* ifc_buf & ifc_req are the same size so this works */
    454 	NETBSD32PTR32(s32p->ifc_buf, p->ifc_buf);
    455 }
    456 
    457 static inline void
    458 netbsd32_from_ifmediareq(struct ifmediareq *p, struct netbsd32_ifmediareq *s32p, u_long cmd)
    459 {
    460 
    461 	memcpy(s32p, p, sizeof *p);
    462 /* filled in? */
    463 #if 0
    464 	s32p->ifm_ulist = (netbsd32_intp_t)p->ifm_ulist;
    465 #endif
    466 }
    467 
    468 static inline void
    469 netbsd32_from_ifdrv(struct ifdrv *p, struct netbsd32_ifdrv *s32p, u_long cmd)
    470 {
    471 
    472 	memcpy(s32p, p, sizeof *p);
    473 /* filled in? */
    474 #if 0
    475 	s32p->ifm_data = (netbsd32_u_longp_t)p->ifm_data;
    476 #endif
    477 }
    478 
    479 static inline void
    480 netbsd32_from_sioc_vif_req(struct sioc_vif_req *p, struct netbsd32_sioc_vif_req *s32p, u_long cmd)
    481 {
    482 
    483 	s32p->vifi = p->vifi;
    484 	s32p->icount = (netbsd32_u_long)p->icount;
    485 	s32p->ocount = (netbsd32_u_long)p->ocount;
    486 	s32p->ibytes = (netbsd32_u_long)p->ibytes;
    487 	s32p->obytes = (netbsd32_u_long)p->obytes;
    488 }
    489 
    490 static inline void
    491 netbsd32_from_sioc_sg_req(struct sioc_sg_req *p, struct netbsd32_sioc_sg_req *s32p, u_long cmd)
    492 {
    493 
    494 	s32p->src = p->src;
    495 	s32p->grp = p->grp;
    496 	s32p->pktcnt = (netbsd32_u_long)p->pktcnt;
    497 	s32p->bytecnt = (netbsd32_u_long)p->bytecnt;
    498 	s32p->wrong_if = (netbsd32_u_long)p->wrong_if;
    499 }
    500 
    501 static inline void
    502 netbsd32_from_atareq(struct atareq *p, struct netbsd32_atareq *s32p, u_long cmd)
    503 {
    504 	s32p->flags = (netbsd32_u_long)p->flags;
    505 	s32p->command = p->command;
    506 	s32p->features = p->features;
    507 	s32p->sec_count = p->sec_count;
    508 	s32p->sec_num = p->sec_num;
    509 	s32p->head = p->head;
    510 	s32p->cylinder = p->cylinder;
    511 	NETBSD32PTR32(s32p->databuf, p->databuf);
    512 	s32p->datalen = (netbsd32_u_long)p->datalen;
    513 	s32p->timeout = p->timeout;
    514 	s32p->retsts = p->retsts;
    515 	s32p->error = p->error;
    516 }
    517 
    518 static inline void
    519 netbsd32_from_vnd_ioctl(struct vnd_ioctl *p, struct netbsd32_vnd_ioctl *s32p, u_long cmd)
    520 {
    521 
    522 	s32p->vnd_flags = p->vnd_flags;
    523 	s32p->vnd_geom = p->vnd_geom;
    524 	s32p->vnd_osize = p->vnd_osize;
    525 	s32p->vnd_size = p->vnd_size;
    526 }
    527 
    528 static inline void
    529 netbsd32_from_vnd_user(struct vnd_user *p, struct netbsd32_vnd_user *s32p, u_long cmd)
    530 {
    531 
    532 	s32p->vnu_unit = p->vnu_unit;
    533 	s32p->vnu_dev = p->vnu_dev;
    534 	s32p->vnu_ino = p->vnu_ino;
    535 }
    536 
    537 static inline void
    538 netbsd32_from_vnd_ioctl50(struct vnd_ioctl50 *p, struct netbsd32_vnd_ioctl50 *s32p, u_long cmd)
    539 {
    540 
    541 	s32p->vnd_flags = p->vnd_flags;
    542 	s32p->vnd_geom = p->vnd_geom;
    543 	s32p->vnd_size = p->vnd_size;
    544 }
    545 
    546 static inline void
    547 netbsd32_from_plistref(struct plistref *p, struct netbsd32_plistref *s32p, u_long cmd)
    548 {
    549 
    550 	NETBSD32PTR32(s32p->pref_plist, p->pref_plist);
    551 	s32p->pref_len = p->pref_len;
    552 }
    553 
    554 static inline void
    555 netbsd32_from_wdog_conf(struct wdog_conf *p, struct netbsd32_wdog_conf *s32p, u_long cmd)
    556 {
    557 
    558 	NETBSD32PTR32(s32p->wc_names, p->wc_names);
    559 	s32p->wc_count = p->wc_count;
    560 }
    561 
    562 /* wsdisplay stuff */
    563 static inline void
    564 netbsd32_from_wsdisplay_addscreendata(struct wsdisplay_addscreendata *asd,
    565 					struct netbsd32_wsdisplay_addscreendata *asd32,
    566 					u_long cmd)
    567 {
    568 	NETBSD32PTR32(asd32->screentype, asd->screentype);
    569 	NETBSD32PTR32(asd32->emul, asd->emul);
    570 	asd32->idx = asd->idx;
    571 }
    572 
    573 static inline void
    574 netbsd32_from_wsdisplay_cursor(struct wsdisplay_cursor *c,
    575 					       struct netbsd32_wsdisplay_cursor *c32,
    576 					       u_long cmd)
    577 {
    578 	c32->which = c->which;
    579 	c32->enable = c->enable;
    580 	c32->pos.x = c->pos.x;
    581 	c32->pos.y = c->pos.y;
    582 	c32->hot.x = c->hot.x;
    583 	c32->hot.y = c->hot.y;
    584 	c32->size.x = c->size.x;
    585 	c32->size.y = c->size.y;
    586 	c32->cmap.index = c->cmap.index;
    587 	c32->cmap.count = c->cmap.count;
    588 	NETBSD32PTR32(c32->cmap.red, c->cmap.red);
    589 	NETBSD32PTR32(c32->cmap.green, c->cmap.green);
    590 	NETBSD32PTR32(c32->cmap.blue, c->cmap.blue);
    591 	NETBSD32PTR32(c32->image, c->image);
    592 	NETBSD32PTR32(c32->mask, c->mask);
    593 }
    594 
    595 static inline void
    596 netbsd32_from_ieee80211req(struct ieee80211req *ireq,
    597 			   struct netbsd32_ieee80211req *ireq32, u_long cmd)
    598 {
    599 	strncpy(ireq32->i_name, ireq->i_name, IFNAMSIZ);
    600 	ireq32->i_type = ireq->i_type;
    601 	ireq32->i_val = ireq->i_val;
    602 	ireq32->i_len = ireq->i_len;
    603 	NETBSD32PTR32(ireq32->i_data, ireq->i_data);
    604 }
    605 
    606 static inline void
    607 netbsd32_from_ieee80211_nwkey(struct ieee80211_nwkey *nwk,
    608 				struct netbsd32_ieee80211_nwkey *nwk32,
    609 				u_long cmd)
    610 {
    611 	int i;
    612 
    613 	strncpy(nwk32->i_name, nwk->i_name, IFNAMSIZ);
    614 	nwk32->i_wepon = nwk->i_wepon;
    615 	nwk32->i_defkid = nwk->i_defkid;
    616 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    617 		nwk32->i_key[i].i_keylen = nwk->i_key[i].i_keylen;
    618 		NETBSD32PTR32(nwk32->i_key[i].i_keydat,
    619 				nwk->i_key[i].i_keydat);
    620 	}
    621 }
    622 
    623 static inline void
    624 netbsd32_from_bpf_program(struct bpf_program *p, struct netbsd32_bpf_program *s32p, u_long cmd)
    625 {
    626 
    627 	NETBSD32PTR32(s32p->bf_insns, p->bf_insns);
    628 	s32p->bf_len = p->bf_len;
    629 }
    630 
    631 static inline void
    632 netbsd32_from_bpf_dltlist(struct bpf_dltlist *p, struct netbsd32_bpf_dltlist *s32p, u_long cmd)
    633 {
    634 
    635 	NETBSD32PTR32(s32p->bfl_list, p->bfl_list);
    636 	s32p->bfl_len = p->bfl_len;
    637 }
    638 
    639 static inline void
    640 netbsd32_from_u_long(u_long *p, netbsd32_u_long *s32p, u_long cmd)
    641 {
    642 
    643 	*s32p = (netbsd32_u_long)*p;
    644 }
    645 
    646 static inline void
    647 netbsd32_from_clockctl_settimeofday(
    648     const struct clockctl_settimeofday *p,
    649     struct netbsd32_clockctl_settimeofday *s32p,
    650     u_long cmd)
    651 {
    652 
    653 	NETBSD32PTR32(s32p->tv, p->tv);
    654 	NETBSD32PTR32(s32p->tzp, p->tzp);
    655 }
    656 
    657 static inline void
    658 netbsd32_from_clockctl_adjtime(
    659     const struct clockctl_adjtime *p,
    660     struct netbsd32_clockctl_adjtime *s32p,
    661     u_long cmd)
    662 {
    663 
    664 	NETBSD32PTR32(s32p->delta, p->delta);
    665 	NETBSD32PTR32(s32p->olddelta, p->olddelta);
    666 }
    667 
    668 static inline void
    669 netbsd32_from_clockctl_clock_settime(
    670     const struct clockctl_clock_settime *p,
    671     struct netbsd32_clockctl_clock_settime *s32p,
    672     u_long cmd)
    673 {
    674 
    675 	s32p->clock_id = p->clock_id;
    676 	NETBSD32PTR32(s32p->tp, p->tp);
    677 }
    678 
    679 static inline void
    680 netbsd32_from_clockctl_ntp_adjtime(
    681     const struct clockctl_ntp_adjtime *p,
    682     struct netbsd32_clockctl_ntp_adjtime *s32p,
    683     u_long cmd)
    684 {
    685 
    686 	NETBSD32PTR32(s32p->tp, p->tp);
    687 	s32p->retval = p->retval;
    688 }
    689 
    690 /*
    691  * main ioctl syscall.
    692  *
    693  * ok, here we are in the biggy.  we have to do fix ups depending
    694  * on the ioctl command before and afterwards.
    695  */
    696 int
    697 netbsd32_ioctl(struct lwp *l, const struct netbsd32_ioctl_args *uap, register_t *retval)
    698 {
    699 	/* {
    700 		syscallarg(int) fd;
    701 		syscallarg(netbsd32_u_long) com;
    702 		syscallarg(netbsd32_voidp) data;
    703 	} */
    704 	struct proc *p = l->l_proc;
    705 	struct file *fp;
    706 	struct filedesc *fdp;
    707 	u_long com;
    708 	int error = 0;
    709 	size_t size;
    710 	size_t alloc_size32, size32;
    711 	void *data, *memp = NULL;
    712 	void *data32, *memp32 = NULL;
    713 	unsigned int fd;
    714 	fdfile_t *ff;
    715 	int tmp;
    716 #define STK_PARAMS	128
    717 	uint64_t stkbuf[STK_PARAMS/sizeof(uint64_t)];
    718 	uint64_t stkbuf32[STK_PARAMS/sizeof(uint64_t)];
    719 
    720 	/*
    721 	 * we need to translate some commands (_IOW) before calling sys_ioctl,
    722 	 * some after (_IOR), and some both (_IOWR).
    723 	 */
    724 #if 0
    725 	{
    726 		const char * const dirs[8] = {
    727 		    "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!",
    728 		    "INOUT", "VOID|IN|OUT!"
    729 		};
    730 
    731 		printf("netbsd32_ioctl(%d, %x, %x): "
    732 		    "%s group %c base %d len %d\n",
    733 		    SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data).i32,
    734 		    dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)],
    735 		    IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)),
    736 		    IOCPARM_LEN(SCARG(uap, com)));
    737 	}
    738 #endif
    739 
    740 	memp = NULL;
    741 	memp32 = NULL;
    742 	alloc_size32 = 0;
    743 	size32 = 0;
    744 	size = 0;
    745 
    746 	fdp = p->p_fd;
    747 	fd = SCARG(uap, fd);
    748 	if ((fp = fd_getfile(fd)) == NULL)
    749 		return (EBADF);
    750 	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
    751 		error = EBADF;
    752 		goto out;
    753 	}
    754 
    755 	ff = fdp->fd_dt->dt_ff[SCARG(uap, fd)];
    756 	switch (com = SCARG(uap, com)) {
    757 	case FIOCLEX:
    758 		ff->ff_exclose = true;
    759 		fdp->fd_exclose = true;
    760 		goto out;
    761 
    762 	case FIONCLEX:
    763 		ff->ff_exclose = false;
    764 		goto out;
    765 	}
    766 
    767 	/*
    768 	 * Interpret high order word to find amount of data to be
    769 	 * copied to/from the user's address space.
    770 	 */
    771 	size32 = IOCPARM_LEN(com);
    772 	alloc_size32 = size32;
    773 
    774 	/*
    775 	 * The disklabel is now padded to a multiple of 8 bytes however the old
    776 	 * disklabel on 32bit platforms wasn't.  This leaves a difference in
    777 	 * size of 4 bytes between the two but are otherwise identical.
    778 	 * To deal with this, we allocate enough space for the new disklabel
    779 	 * but only copyin/out the smaller amount.
    780 	 */
    781 	if (IOCGROUP(com) == 'd') {
    782 		u_long ncom = com ^ (DIOCGDINFO ^ DIOCGDINFO32);
    783 		switch (ncom) {
    784 		case DIOCGDINFO:
    785 		case DIOCWDINFO:
    786 		case DIOCSDINFO:
    787 		case DIOCGDEFLABEL:
    788 			com = ncom;
    789 			if (IOCPARM_LEN(DIOCGDINFO32) < IOCPARM_LEN(DIOCGDINFO))
    790 				alloc_size32 = IOCPARM_LEN(DIOCGDINFO);
    791 			break;
    792 		}
    793 	}
    794 	if (alloc_size32 > IOCPARM_MAX) {
    795 		error = ENOTTY;
    796 		goto out;
    797 	}
    798 	if (alloc_size32 > sizeof(stkbuf)) {
    799 		memp32 = kmem_alloc(alloc_size32, KM_SLEEP);
    800 		data32 = memp32;
    801 	} else
    802 		data32 = (void *)stkbuf32;
    803 	if ((com >> IOCPARM_SHIFT) == 0)  {
    804 		/* UNIX-style ioctl. */
    805 		data32 = SCARG_P32(uap, data);
    806 	} else {
    807 		if (com&IOC_IN) {
    808 			if (size32) {
    809 				error = copyin(SCARG_P32(uap, data), data32,
    810 				    size32);
    811 				if (error) {
    812 					goto out;
    813 				}
    814 				/*
    815 				 * The data between size and alloc_size has
    816 				 * not been overwritten.  It shouldn't matter
    817 				 * but let's clear that anyway.
    818 				 */
    819 				if (__predict_false(size32 < alloc_size32)) {
    820 					memset((char *)data32+size32, 0,
    821 					    alloc_size32 - size32);
    822 				}
    823 				ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data),
    824 				    size32, 0);
    825 			} else
    826 				*(void **)data32 = SCARG_P32(uap, data);
    827 		} else if ((com&IOC_OUT) && size32) {
    828 			/*
    829 			 * Zero the buffer so the user always
    830 			 * gets back something deterministic.
    831 			 */
    832 			memset(data32, 0, alloc_size32);
    833 		} else if (com&IOC_VOID) {
    834 			*(void **)data32 = SCARG_P32(uap, data);
    835 		}
    836 	}
    837 
    838 	/*
    839 	 * convert various structures, pointers, and other objects that
    840 	 * change size from 32 bit -> 64 bit, for all ioctl commands.
    841 	 */
    842 	switch (SCARG(uap, com)) {
    843 	case FIONBIO:
    844 		mutex_enter(&fp->f_lock);
    845 		if ((tmp = *(int *)data32) != 0)
    846 			fp->f_flag |= FNONBLOCK;
    847 		else
    848 			fp->f_flag &= ~FNONBLOCK;
    849 		mutex_exit(&fp->f_lock);
    850 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (void *)&tmp);
    851 		break;
    852 
    853 	case FIOASYNC:
    854 		mutex_enter(&fp->f_lock);
    855 		if ((tmp = *(int *)data32) != 0)
    856 			fp->f_flag |= FASYNC;
    857 		else
    858 			fp->f_flag &= ~FASYNC;
    859 		mutex_exit(&fp->f_lock);
    860 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (void *)&tmp);
    861 		break;
    862 
    863 	case AUDIO_WSEEK32:
    864 		IOCTL_CONV_TO(AUDIO_WSEEK, u_long);
    865 
    866 	case DIOCGPART32:
    867 		IOCTL_STRUCT_CONV_TO(DIOCGPART, partinfo);
    868 #if 0	/* not implemented by anything */
    869 	case DIOCRFORMAT32:
    870 		IOCTL_STRUCT_CONV_TO(DIOCRFORMAT, format_op);
    871 	case DIOCWFORMAT32:
    872 		IOCTL_STRUCT_CONV_TO(DIOCWFORMAT, format_op);
    873 #endif
    874 
    875 	case ATAIOCCOMMAND32:
    876 		IOCTL_STRUCT_CONV_TO(ATAIOCCOMMAND, atareq);
    877 
    878 /*
    879  * only a few ifreq syscalls need conversion and those are
    880  * all driver specific... XXX
    881  */
    882 #if 0
    883 	case SIOCGADDRROM3232:
    884 		IOCTL_STRUCT_CONV_TO(SIOCGADDRROM32, ifreq);
    885 	case SIOCGCHIPID32:
    886 		IOCTL_STRUCT_CONV_TO(SIOCGCHIPID, ifreq);
    887 	case SIOCSIFADDR32:
    888 		IOCTL_STRUCT_CONV_TO(SIOCSIFADDR, ifreq);
    889 	case OSIOCGIFADDR32:
    890 		IOCTL_STRUCT_CONV_TO(OSIOCGIFADDR, ifreq);
    891 	case SIOCGIFADDR32:
    892 		IOCTL_STRUCT_CONV_TO(SIOCGIFADDR, ifreq);
    893 	case SIOCSIFDSTADDR32:
    894 		IOCTL_STRUCT_CONV_TO(SIOCSIFDSTADDR, ifreq);
    895 	case OSIOCGIFDSTADDR32:
    896 		IOCTL_STRUCT_CONV_TO(OSIOCGIFDSTADDR, ifreq);
    897 	case SIOCGIFDSTADDR32:
    898 		IOCTL_STRUCT_CONV_TO(SIOCGIFDSTADDR, ifreq);
    899 	case OSIOCGIFBRDADDR32:
    900 		IOCTL_STRUCT_CONV_TO(OSIOCGIFBRDADDR, ifreq);
    901 	case SIOCGIFBRDADDR32:
    902 		IOCTL_STRUCT_CONV_TO(SIOCGIFBRDADDR, ifreq);
    903 	case SIOCSIFBRDADDR32:
    904 		IOCTL_STRUCT_CONV_TO(SIOCSIFBRDADDR, ifreq);
    905 	case OSIOCGIFNETMASK32:
    906 		IOCTL_STRUCT_CONV_TO(OSIOCGIFNETMASK, ifreq);
    907 	case SIOCGIFNETMASK32:
    908 		IOCTL_STRUCT_CONV_TO(SIOCGIFNETMASK, ifreq);
    909 	case SIOCSIFNETMASK32:
    910 		IOCTL_STRUCT_CONV_TO(SIOCSIFNETMASK, ifreq);
    911 	case SIOCGIFMETRIC32:
    912 		IOCTL_STRUCT_CONV_TO(SIOCGIFMETRIC, ifreq);
    913 	case SIOCSIFMETRIC32:
    914 		IOCTL_STRUCT_CONV_TO(SIOCSIFMETRIC, ifreq);
    915 	case SIOCDIFADDR32:
    916 		IOCTL_STRUCT_CONV_TO(SIOCDIFADDR, ifreq);
    917 	case SIOCADDMULTI32:
    918 		IOCTL_STRUCT_CONV_TO(SIOCADDMULTI, ifreq);
    919 	case SIOCDELMULTI32:
    920 		IOCTL_STRUCT_CONV_TO(SIOCDELMULTI, ifreq);
    921 	case SIOCSIFMEDIA32:
    922 		IOCTL_STRUCT_CONV_TO(SIOCSIFMEDIA, ifreq);
    923 	case SIOCSIFMTU32:
    924 		IOCTL_STRUCT_CONV_TO(SIOCSIFMTU, ifreq);
    925 	case SIOCGIFMTU32:
    926 		IOCTL_STRUCT_CONV_TO(SIOCGIFMTU, ifreq);
    927 	case BIOCGETIF32:
    928 		IOCTL_STRUCT_CONV_TO(BIOCGETIF, ifreq);
    929 	case BIOCSETIF32:
    930 		IOCTL_STRUCT_CONV_TO(BIOCSETIF, ifreq);
    931 	case SIOCPHASE132:
    932 		IOCTL_STRUCT_CONV_TO(SIOCPHASE1, ifreq);
    933 	case SIOCPHASE232:
    934 		IOCTL_STRUCT_CONV_TO(SIOCPHASE2, ifreq);
    935 #endif
    936 
    937 	case OOSIOCGIFCONF32:
    938 		IOCTL_STRUCT_CONV_TO(OOSIOCGIFCONF, ifconf);
    939 	case OSIOCGIFCONF32:
    940 		IOCTL_STRUCT_CONV_TO(OSIOCGIFCONF, ifconf);
    941 	case SIOCGIFCONF32:
    942 		IOCTL_STRUCT_CONV_TO(SIOCGIFCONF, ifconf);
    943 
    944 	case SIOCGIFFLAGS32:
    945 		IOCTL_STRUCT_CONV_TO(SIOCGIFFLAGS, ifreq);
    946 	case SIOCSIFFLAGS32:
    947 		IOCTL_STRUCT_CONV_TO(SIOCSIFFLAGS, ifreq);
    948 
    949 	case SIOCGIFADDRPREF32:
    950 		IOCTL_STRUCT_CONV_TO(SIOCGIFADDRPREF, if_addrprefreq);
    951 	case SIOCSIFADDRPREF32:
    952 		IOCTL_STRUCT_CONV_TO(SIOCSIFADDRPREF, if_addrprefreq);
    953 
    954 
    955 	case OSIOCGIFFLAGS32:
    956 		IOCTL_STRUCT_CONV_TO(OSIOCGIFFLAGS, oifreq);
    957 	case OSIOCSIFFLAGS32:
    958 		IOCTL_STRUCT_CONV_TO(OSIOCSIFFLAGS, oifreq);
    959 
    960 	case SIOCGIFMEDIA32:
    961 		IOCTL_STRUCT_CONV_TO(SIOCGIFMEDIA, ifmediareq);
    962 
    963 	case SIOCSDRVSPEC32:
    964 		IOCTL_STRUCT_CONV_TO(SIOCSDRVSPEC, ifdrv);
    965 
    966 	case SIOCGETVIFCNT32:
    967 		IOCTL_STRUCT_CONV_TO(SIOCGETVIFCNT, sioc_vif_req);
    968 
    969 	case SIOCGETSGCNT32:
    970 		IOCTL_STRUCT_CONV_TO(SIOCGETSGCNT, sioc_sg_req);
    971 
    972 	case VNDIOCSET32:
    973 		IOCTL_STRUCT_CONV_TO(VNDIOCSET, vnd_ioctl);
    974 
    975 	case VNDIOCCLR32:
    976 		IOCTL_STRUCT_CONV_TO(VNDIOCCLR, vnd_ioctl);
    977 
    978 	case VNDIOCGET32:
    979 		IOCTL_STRUCT_CONV_TO(VNDIOCGET, vnd_user);
    980 
    981 	case VNDIOCSET5032:
    982 		IOCTL_STRUCT_CONV_TO(VNDIOCSET50, vnd_ioctl50);
    983 
    984 	case VNDIOCCLR5032:
    985 		IOCTL_STRUCT_CONV_TO(VNDIOCCLR50, vnd_ioctl50);
    986 
    987 	case ENVSYS_GETDICTIONARY32:
    988 		IOCTL_STRUCT_CONV_TO(ENVSYS_GETDICTIONARY, plistref);
    989 	case ENVSYS_SETDICTIONARY32:
    990 		IOCTL_STRUCT_CONV_TO(ENVSYS_SETDICTIONARY, plistref);
    991 	case ENVSYS_REMOVEPROPS32:
    992 		IOCTL_STRUCT_CONV_TO(ENVSYS_REMOVEPROPS, plistref);
    993 
    994 	case WDOGIOC_GWDOGS32:
    995 		IOCTL_STRUCT_CONV_TO(WDOGIOC_GWDOGS, wdog_conf);
    996 
    997 	case BIOCSETF32:
    998 		IOCTL_STRUCT_CONV_TO(BIOCSETF, bpf_program);
    999 	case BIOCSTCPF32:
   1000 		IOCTL_STRUCT_CONV_TO(BIOCSTCPF, bpf_program);
   1001 	case BIOCSUDPF32:
   1002 		IOCTL_STRUCT_CONV_TO(BIOCSUDPF, bpf_program);
   1003 	case BIOCGDLTLIST32:
   1004 		IOCTL_STRUCT_CONV_TO(BIOCGDLTLIST, bpf_dltlist);
   1005 
   1006 	case WSDISPLAYIO_ADDSCREEN32:
   1007 		IOCTL_STRUCT_CONV_TO(WSDISPLAYIO_ADDSCREEN, wsdisplay_addscreendata);
   1008 
   1009 	case WSDISPLAYIO_GCURSOR32:
   1010 		IOCTL_STRUCT_CONV_TO(WSDISPLAYIO_GCURSOR, wsdisplay_cursor);
   1011 	case WSDISPLAYIO_SCURSOR32:
   1012 		IOCTL_STRUCT_CONV_TO(WSDISPLAYIO_SCURSOR, wsdisplay_cursor);
   1013 
   1014 	case SIOCS8021132:
   1015 		IOCTL_STRUCT_CONV_TO(SIOCS80211, ieee80211req);
   1016 	case SIOCG8021132:
   1017 		IOCTL_STRUCT_CONV_TO(SIOCG80211, ieee80211req);
   1018 	case SIOCS80211NWKEY32:
   1019 		IOCTL_STRUCT_CONV_TO(SIOCS80211NWKEY, ieee80211_nwkey);
   1020 	case SIOCG80211NWKEY32:
   1021 		IOCTL_STRUCT_CONV_TO(SIOCG80211NWKEY, ieee80211_nwkey);
   1022 
   1023 	case POWER_EVENT_RECVDICT32:
   1024 		IOCTL_STRUCT_CONV_TO(POWER_EVENT_RECVDICT, plistref);
   1025 
   1026 	case CLOCKCTL_SETTIMEOFDAY32:
   1027 		IOCTL_STRUCT_CONV_TO(CLOCKCTL_SETTIMEOFDAY,
   1028 		    clockctl_settimeofday);
   1029 	case CLOCKCTL_ADJTIME32:
   1030 		IOCTL_STRUCT_CONV_TO(CLOCKCTL_ADJTIME, clockctl_adjtime);
   1031 	case CLOCKCTL_CLOCK_SETTIME32:
   1032 		IOCTL_STRUCT_CONV_TO(CLOCKCTL_CLOCK_SETTIME,
   1033 		    clockctl_clock_settime);
   1034 	case CLOCKCTL_NTP_ADJTIME32:
   1035 		IOCTL_STRUCT_CONV_TO(CLOCKCTL_NTP_ADJTIME,
   1036 		    clockctl_ntp_adjtime);
   1037 
   1038 	default:
   1039 #ifdef NETBSD32_MD_IOCTL
   1040 		error = netbsd32_md_ioctl(fp, com, data32, l);
   1041 #else
   1042 		error = (*fp->f_ops->fo_ioctl)(fp, com, data32);
   1043 #endif
   1044 		break;
   1045 	}
   1046 
   1047 	if (error == EPASSTHROUGH)
   1048 		error = ENOTTY;
   1049 
   1050 	/*
   1051 	 * Copy any data to user, size was
   1052 	 * already set and checked above.
   1053 	 */
   1054 	if (error == 0 && (com&IOC_OUT) && size32) {
   1055 		error = copyout(data32, SCARG_P32(uap, data), size32);
   1056 		ktrgenio(fd, UIO_READ, SCARG_P32(uap, data),
   1057 		    size32, error);
   1058 	}
   1059 
   1060  out:
   1061 	/* If we allocated data, free it here. */
   1062 	if (memp32)
   1063 		kmem_free(memp32, alloc_size32);
   1064 	if (memp)
   1065 		kmem_free(memp, size);
   1066 	fd_putfile(fd);
   1067 	return (error);
   1068 }
   1069