netbsd32_ioctl.c revision 1.64 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