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