netbsd32_ioctl.c revision 1.50 1 /* $NetBSD: netbsd32_ioctl.c,v 1.50 2010/09/19 10:33:31 mrg 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.50 2010/09/19 10:33:31 mrg 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
54 #ifdef __sparc__
55 #include <dev/sun/fbio.h>
56 #include <machine/openpromio.h>
57 #endif
58
59 #include <net/if.h>
60 #include <net/route.h>
61
62 #include <netinet/in.h>
63 #include <netinet/in_var.h>
64 #include <netinet/igmp.h>
65 #include <netinet/igmp_var.h>
66 #include <netinet/ip_mroute.h>
67
68 #include <compat/sys/sockio.h>
69
70 #include <compat/netbsd32/netbsd32.h>
71 #include <compat/netbsd32/netbsd32_ioctl.h>
72 #include <compat/netbsd32/netbsd32_syscallargs.h>
73
74 #include <dev/vndvar.h>
75
76 /* prototypes for the converters */
77 static inline void netbsd32_to_partinfo(struct netbsd32_partinfo *,
78 struct partinfo *, u_long);
79 #if 0
80 static inline void netbsd32_to_format_op(struct netbsd32_format_op *,
81 struct format_op *, u_long);
82 #endif
83 static inline void netbsd32_to_oifreq(struct netbsd32_oifreq *, struct oifreq *,
84 u_long cmd);
85 static inline void netbsd32_to_ifreq(struct netbsd32_ifreq *, struct ifreq *,
86 u_long cmd);
87 static inline void netbsd32_to_ifconf(struct netbsd32_ifconf *,
88 struct ifconf *, u_long);
89 static inline void netbsd32_to_ifmediareq(struct netbsd32_ifmediareq *,
90 struct ifmediareq *, u_long);
91 static inline void netbsd32_to_ifdrv(struct netbsd32_ifdrv *, struct ifdrv *,
92 u_long);
93 static inline void netbsd32_to_sioc_vif_req(struct netbsd32_sioc_vif_req *,
94 struct sioc_vif_req *, u_long);
95 static inline void netbsd32_to_sioc_sg_req(struct netbsd32_sioc_sg_req *,
96 struct sioc_sg_req *, u_long);
97 static inline void netbsd32_from_partinfo(struct partinfo *,
98 struct netbsd32_partinfo *, u_long);
99 #if 0
100 static inline void netbsd32_from_format_op(struct format_op *,
101 struct netbsd32_format_op *,
102 u_long);
103 #endif
104 static inline void netbsd32_from_ifreq(struct ifreq *,
105 struct netbsd32_ifreq *, u_long);
106 static inline void netbsd32_from_oifreq(struct oifreq *,
107 struct netbsd32_oifreq *, u_long);
108 static inline void netbsd32_from_ifconf(struct ifconf *,
109 struct netbsd32_ifconf *, u_long);
110 static inline void netbsd32_from_ifmediareq(struct ifmediareq *,
111 struct netbsd32_ifmediareq *,
112 u_long);
113 static inline void netbsd32_from_ifdrv(struct ifdrv *,
114 struct netbsd32_ifdrv *, u_long);
115 static inline void netbsd32_from_sioc_vif_req(struct sioc_vif_req *,
116 struct netbsd32_sioc_vif_req *,
117 u_long);
118 static inline void netbsd32_from_sioc_sg_req(struct sioc_sg_req *,
119 struct netbsd32_sioc_sg_req *,
120 u_long);
121
122 /* convert to/from different structures */
123
124 static inline void
125 netbsd32_to_partinfo(struct netbsd32_partinfo *s32p, struct partinfo *p, u_long cmd)
126 {
127
128 p->disklab = (struct disklabel *)NETBSD32PTR64(s32p->disklab);
129 p->part = (struct partition *)NETBSD32PTR64(s32p->part);
130 }
131
132 #if 0
133 static inline void
134 netbsd32_to_format_op(struct netbsd32_format_op *s32p, struct format_op *p, u_long cmd)
135 {
136
137 p->df_buf = (char *)NETBSD32PTR64(s32p->df_buf);
138 p->df_count = s32p->df_count;
139 p->df_startblk = s32p->df_startblk;
140 memcpy(p->df_reg, s32p->df_reg, sizeof(s32p->df_reg));
141 }
142 #endif
143
144 static inline void
145 netbsd32_to_ifreq(struct netbsd32_ifreq *s32p, struct ifreq *p, u_long cmd)
146 {
147
148 memcpy(p, s32p, sizeof *s32p);
149 /*
150 * XXX
151 * struct ifreq says the same, but sometimes the ifr_data
152 * union member needs to be converted to 64 bits... this
153 * is very driver specific and so we ignore it for now..
154 */
155 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA)
156 p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data);
157 }
158
159 static inline void
160 netbsd32_to_oifreq(struct netbsd32_oifreq *s32p, struct oifreq *p, u_long cmd)
161 {
162
163 memcpy(p, s32p, sizeof *s32p);
164 /*
165 * XXX
166 * struct ifreq says the same, but sometimes the ifr_data
167 * union member needs to be converted to 64 bits... this
168 * is very driver specific and so we ignore it for now..
169 */
170 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA)
171 p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data);
172 }
173
174 static inline void
175 netbsd32_to_ifconf(struct netbsd32_ifconf *s32p, struct ifconf *p, u_long cmd)
176 {
177
178 p->ifc_len = s32p->ifc_len;
179 /* ifc_buf & ifc_req are the same size so this works */
180 p->ifc_buf = (void *)NETBSD32PTR64(s32p->ifc_buf);
181 }
182
183 static inline void
184 netbsd32_to_ifmediareq(struct netbsd32_ifmediareq *s32p, struct ifmediareq *p, u_long cmd)
185 {
186
187 memcpy(p, s32p, sizeof *s32p);
188 p->ifm_ulist = (int *)NETBSD32PTR64(s32p->ifm_ulist);
189 }
190
191 static inline void
192 netbsd32_to_ifdrv(struct netbsd32_ifdrv *s32p, struct ifdrv *p, u_long cmd)
193 {
194
195 memcpy(p, s32p, sizeof *s32p);
196 p->ifd_data = (void *)NETBSD32PTR64(s32p->ifd_data);
197 }
198
199 static inline void
200 netbsd32_to_sioc_vif_req(struct netbsd32_sioc_vif_req *s32p, struct sioc_vif_req *p, u_long cmd)
201 {
202
203 p->vifi = s32p->vifi;
204 p->icount = (u_long)s32p->icount;
205 p->ocount = (u_long)s32p->ocount;
206 p->ibytes = (u_long)s32p->ibytes;
207 p->obytes = (u_long)s32p->obytes;
208 }
209
210 static inline void
211 netbsd32_to_sioc_sg_req(struct netbsd32_sioc_sg_req *s32p, struct sioc_sg_req *p, u_long cmd)
212 {
213
214 p->src = s32p->src;
215 p->grp = s32p->grp;
216 p->pktcnt = (u_long)s32p->pktcnt;
217 p->bytecnt = (u_long)s32p->bytecnt;
218 p->wrong_if = (u_long)s32p->wrong_if;
219 }
220
221 static inline void
222 netbsd32_to_vnd_ioctl(struct netbsd32_vnd_ioctl *s32p, struct vnd_ioctl *p, u_long cmd)
223 {
224
225 p->vnd_file = (char *)NETBSD32PTR64(s32p->vnd_file);
226 p->vnd_flags = s32p->vnd_flags;
227 p->vnd_geom = s32p->vnd_geom;
228 p->vnd_osize = s32p->vnd_osize;
229 p->vnd_size = s32p->vnd_size;
230 }
231
232 static inline void
233 netbsd32_to_vnd_user(struct netbsd32_vnd_user *s32p, struct vnd_user *p, u_long cmd)
234 {
235
236 p->vnu_unit = s32p->vnu_unit;
237 p->vnu_dev = s32p->vnu_dev;
238 p->vnu_ino = s32p->vnu_ino;
239 }
240
241 static inline void
242 netbsd32_to_vnd_ioctl50(struct netbsd32_vnd_ioctl50 *s32p, struct vnd_ioctl50 *p, u_long cmd)
243 {
244
245 p->vnd_file = (char *)NETBSD32PTR64(s32p->vnd_file);
246 p->vnd_flags = s32p->vnd_flags;
247 p->vnd_geom = s32p->vnd_geom;
248 p->vnd_size = s32p->vnd_size;
249 }
250
251 static inline void
252 netbsd32_to_u_long(netbsd32_u_long *s32p, u_long *p, u_long cmd)
253 {
254
255 *p = (u_long)*s32p;
256 }
257
258 /*
259 * handle ioctl conversions from 64-bit kernel -> netbsd32
260 */
261
262 static inline void
263 netbsd32_from_partinfo(struct partinfo *p, struct netbsd32_partinfo *s32p, u_long cmd)
264 {
265
266 NETBSD32PTR32(s32p->disklab, p->disklab);
267 NETBSD32PTR32(s32p->part, p->part);
268 }
269
270 #if 0
271 static inline void
272 netbsd32_from_format_op(struct format_op *p, struct netbsd32_format_op *s32p, u_long cmd)
273 {
274
275 /* filled in */
276 #if 0
277 s32p->df_buf = (netbsd32_charp)p->df_buf;
278 #endif
279 s32p->df_count = p->df_count;
280 s32p->df_startblk = p->df_startblk;
281 memcpy(s32p->df_reg, p->df_reg, sizeof(p->df_reg));
282 }
283 #endif
284
285 static inline void
286 netbsd32_from_ifreq(struct ifreq *p, struct netbsd32_ifreq *s32p, u_long cmd)
287 {
288
289 /*
290 * XXX
291 * struct ifreq says the same, but sometimes the ifr_data
292 * union member needs to be converted to 64 bits... this
293 * is very driver specific and so we ignore it for now..
294 */
295 memcpy(s32p, p, sizeof *s32p);
296 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA)
297 NETBSD32PTR32(s32p->ifr_data, p->ifr_data);
298 }
299
300 static inline void
301 netbsd32_from_oifreq(struct oifreq *p, struct netbsd32_oifreq *s32p, u_long cmd)
302 {
303
304 /*
305 * XXX
306 * struct ifreq says the same, but sometimes the ifr_data
307 * union member needs to be converted to 64 bits... this
308 * is very driver specific and so we ignore it for now..
309 */
310 memcpy(s32p, p, sizeof *s32p);
311 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA)
312 NETBSD32PTR32(s32p->ifr_data, p->ifr_data);
313 }
314
315 static inline void
316 netbsd32_from_ifconf(struct ifconf *p, struct netbsd32_ifconf *s32p, u_long cmd)
317 {
318
319 s32p->ifc_len = p->ifc_len;
320 /* ifc_buf & ifc_req are the same size so this works */
321 NETBSD32PTR32(s32p->ifc_buf, p->ifc_buf);
322 }
323
324 static inline void
325 netbsd32_from_ifmediareq(struct ifmediareq *p, struct netbsd32_ifmediareq *s32p, u_long cmd)
326 {
327
328 memcpy(s32p, p, sizeof *p);
329 /* filled in? */
330 #if 0
331 s32p->ifm_ulist = (netbsd32_intp_t)p->ifm_ulist;
332 #endif
333 }
334
335 static inline void
336 netbsd32_from_ifdrv(struct ifdrv *p, struct netbsd32_ifdrv *s32p, u_long cmd)
337 {
338
339 memcpy(s32p, p, sizeof *p);
340 /* filled in? */
341 #if 0
342 s32p->ifm_data = (netbsd32_u_longp_t)p->ifm_data;
343 #endif
344 }
345
346 static inline void
347 netbsd32_from_sioc_vif_req(struct sioc_vif_req *p, struct netbsd32_sioc_vif_req *s32p, u_long cmd)
348 {
349
350 s32p->vifi = p->vifi;
351 s32p->icount = (netbsd32_u_long)p->icount;
352 s32p->ocount = (netbsd32_u_long)p->ocount;
353 s32p->ibytes = (netbsd32_u_long)p->ibytes;
354 s32p->obytes = (netbsd32_u_long)p->obytes;
355 }
356
357 static inline void
358 netbsd32_from_sioc_sg_req(struct sioc_sg_req *p, struct netbsd32_sioc_sg_req *s32p, u_long cmd)
359 {
360
361 s32p->src = p->src;
362 s32p->grp = p->grp;
363 s32p->pktcnt = (netbsd32_u_long)p->pktcnt;
364 s32p->bytecnt = (netbsd32_u_long)p->bytecnt;
365 s32p->wrong_if = (netbsd32_u_long)p->wrong_if;
366 }
367
368 static inline void
369 netbsd32_from_vnd_ioctl(struct vnd_ioctl *p, struct netbsd32_vnd_ioctl *s32p, u_long cmd)
370 {
371
372 s32p->vnd_flags = p->vnd_flags;
373 s32p->vnd_geom = p->vnd_geom;
374 s32p->vnd_osize = p->vnd_osize;
375 s32p->vnd_size = p->vnd_size;
376 }
377
378 static inline void
379 netbsd32_from_vnd_user(struct vnd_user *p, struct netbsd32_vnd_user *s32p, u_long cmd)
380 {
381
382 s32p->vnu_unit = p->vnu_unit;
383 s32p->vnu_dev = p->vnu_dev;
384 s32p->vnu_ino = p->vnu_ino;
385 }
386
387 static inline void
388 netbsd32_from_vnd_ioctl50(struct vnd_ioctl50 *p, struct netbsd32_vnd_ioctl50 *s32p, u_long cmd)
389 {
390
391 s32p->vnd_flags = p->vnd_flags;
392 s32p->vnd_geom = p->vnd_geom;
393 s32p->vnd_size = p->vnd_size;
394 }
395
396 static inline void
397 netbsd32_from_u_long(u_long *p, netbsd32_u_long *s32p, u_long cmd)
398 {
399
400 *s32p = (netbsd32_u_long)*p;
401 }
402
403
404 /*
405 * main ioctl syscall.
406 *
407 * ok, here we are in the biggy. we have to do fix ups depending
408 * on the ioctl command before and afterwards.
409 */
410 int
411 netbsd32_ioctl(struct lwp *l, const struct netbsd32_ioctl_args *uap, register_t *retval)
412 {
413 /* {
414 syscallarg(int) fd;
415 syscallarg(netbsd32_u_long) com;
416 syscallarg(netbsd32_voidp) data;
417 } */
418 struct proc *p = l->l_proc;
419 struct file *fp;
420 struct filedesc *fdp;
421 u_long com;
422 int error = 0;
423 u_int size, size32;
424 void *data, *memp = NULL;
425 void *data32, *memp32 = NULL;
426 unsigned fd;
427 fdfile_t *ff;
428 int tmp;
429 #define STK_PARAMS 128
430 u_long stkbuf[STK_PARAMS/sizeof(u_long)];
431 u_long stkbuf32[STK_PARAMS/sizeof(u_long)];
432
433 /*
434 * we need to translate some commands (_IOW) before calling sys_ioctl,
435 * some after (_IOR), and some both (_IOWR).
436 */
437 #if 0
438 {
439 char *dirs[8] = { "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!",
440 "INOUT", "VOID|IN|OUT!" };
441
442 printf("netbsd32_ioctl(%d, %x, %x): %s group %c base %d len %d\n",
443 SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data),
444 dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)],
445 IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)),
446 IOCPARM_LEN(SCARG(uap, com)));
447 }
448 #endif
449
450 fdp = p->p_fd;
451 fd = SCARG(uap, fd);
452 if ((fp = fd_getfile(fd)) == NULL)
453 return (EBADF);
454 if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
455 error = EBADF;
456 goto out;
457 }
458
459 ff = fdp->fd_dt->dt_ff[SCARG(uap, fd)];
460 switch (com = SCARG(uap, com)) {
461 case FIOCLEX:
462 ff->ff_exclose = true;
463 fdp->fd_exclose = true;
464 goto out;
465
466 case FIONCLEX:
467 ff->ff_exclose = false;
468 goto out;
469 }
470
471 /*
472 * Interpret high order word to find amount of data to be
473 * copied to/from the user's address space.
474 */
475 size = 0;
476 size32 = IOCPARM_LEN(com);
477 if (size32 > IOCPARM_MAX) {
478 error = ENOTTY;
479 goto out;
480 }
481 if (size32 > sizeof(stkbuf)) {
482 memp32 = kmem_alloc((size_t)size32, KM_SLEEP);
483 data32 = memp32;
484 } else
485 data32 = (void *)stkbuf32;
486 if (com&IOC_IN) {
487 if (size32) {
488 error = copyin(SCARG_P32(uap, data), data32, size32);
489 if (error) {
490 if (memp32)
491 kmem_free(memp32, (size_t)size32);
492 goto out;
493 }
494 ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data),
495 size32, 0);
496 } else
497 *(void **)data32 = SCARG_P32(uap, data);
498 } else if ((com&IOC_OUT) && size32)
499 /*
500 * Zero the buffer so the user always
501 * gets back something deterministic.
502 */
503 memset(data32, 0, size32);
504 else if (com&IOC_VOID)
505 *(void **)data32 = SCARG_P32(uap, data);
506
507 /*
508 * convert various structures, pointers, and other objects that
509 * change size from 32 bit -> 64 bit, for all ioctl commands.
510 */
511 switch (SCARG(uap, com)) {
512 case FIONBIO:
513 mutex_enter(&fp->f_lock);
514 if ((tmp = *(int *)data32) != 0)
515 fp->f_flag |= FNONBLOCK;
516 else
517 fp->f_flag &= ~FNONBLOCK;
518 mutex_exit(&fp->f_lock);
519 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (void *)&tmp);
520 break;
521
522 case FIOASYNC:
523 mutex_enter(&fp->f_lock);
524 if ((tmp = *(int *)data32) != 0)
525 fp->f_flag |= FASYNC;
526 else
527 fp->f_flag &= ~FASYNC;
528 mutex_exit(&fp->f_lock);
529 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (void *)&tmp);
530 break;
531
532 case AUDIO_WSEEK32:
533 IOCTL_CONV_TO(AUDIO_WSEEK, u_long);
534
535 case DIOCGPART32:
536 IOCTL_STRUCT_CONV_TO(DIOCGPART, partinfo);
537 #if 0 /* not implemented by anything */
538 case DIOCRFORMAT32:
539 IOCTL_STRUCT_CONV_TO(DIOCRFORMAT, format_op);
540 case DIOCWFORMAT32:
541 IOCTL_STRUCT_CONV_TO(DIOCWFORMAT, format_op);
542 #endif
543
544 /*
545 * only a few ifreq syscalls need conversion and those are
546 * all driver specific... XXX
547 */
548 #if 0
549 case SIOCGADDRROM3232:
550 IOCTL_STRUCT_CONV_TO(SIOCGADDRROM32, ifreq);
551 case SIOCGCHIPID32:
552 IOCTL_STRUCT_CONV_TO(SIOCGCHIPID, ifreq);
553 case SIOCSIFADDR32:
554 IOCTL_STRUCT_CONV_TO(SIOCSIFADDR, ifreq);
555 case OSIOCGIFADDR32:
556 IOCTL_STRUCT_CONV_TO(OSIOCGIFADDR, ifreq);
557 case SIOCGIFADDR32:
558 IOCTL_STRUCT_CONV_TO(SIOCGIFADDR, ifreq);
559 case SIOCSIFDSTADDR32:
560 IOCTL_STRUCT_CONV_TO(SIOCSIFDSTADDR, ifreq);
561 case OSIOCGIFDSTADDR32:
562 IOCTL_STRUCT_CONV_TO(OSIOCGIFDSTADDR, ifreq);
563 case SIOCGIFDSTADDR32:
564 IOCTL_STRUCT_CONV_TO(SIOCGIFDSTADDR, ifreq);
565 case OSIOCGIFBRDADDR32:
566 IOCTL_STRUCT_CONV_TO(OSIOCGIFBRDADDR, ifreq);
567 case SIOCGIFBRDADDR32:
568 IOCTL_STRUCT_CONV_TO(SIOCGIFBRDADDR, ifreq);
569 case SIOCSIFBRDADDR32:
570 IOCTL_STRUCT_CONV_TO(SIOCSIFBRDADDR, ifreq);
571 case OSIOCGIFNETMASK32:
572 IOCTL_STRUCT_CONV_TO(OSIOCGIFNETMASK, ifreq);
573 case SIOCGIFNETMASK32:
574 IOCTL_STRUCT_CONV_TO(SIOCGIFNETMASK, ifreq);
575 case SIOCSIFNETMASK32:
576 IOCTL_STRUCT_CONV_TO(SIOCSIFNETMASK, ifreq);
577 case SIOCGIFMETRIC32:
578 IOCTL_STRUCT_CONV_TO(SIOCGIFMETRIC, ifreq);
579 case SIOCSIFMETRIC32:
580 IOCTL_STRUCT_CONV_TO(SIOCSIFMETRIC, ifreq);
581 case SIOCDIFADDR32:
582 IOCTL_STRUCT_CONV_TO(SIOCDIFADDR, ifreq);
583 case SIOCADDMULTI32:
584 IOCTL_STRUCT_CONV_TO(SIOCADDMULTI, ifreq);
585 case SIOCDELMULTI32:
586 IOCTL_STRUCT_CONV_TO(SIOCDELMULTI, ifreq);
587 case SIOCSIFMEDIA32:
588 IOCTL_STRUCT_CONV_TO(SIOCSIFMEDIA, ifreq);
589 case SIOCSIFMTU32:
590 IOCTL_STRUCT_CONV_TO(SIOCSIFMTU, ifreq);
591 case SIOCGIFMTU32:
592 IOCTL_STRUCT_CONV_TO(SIOCGIFMTU, ifreq);
593 case BIOCGETIF32:
594 IOCTL_STRUCT_CONV_TO(BIOCGETIF, ifreq);
595 case BIOCSETIF32:
596 IOCTL_STRUCT_CONV_TO(BIOCSETIF, ifreq);
597 case SIOCPHASE132:
598 IOCTL_STRUCT_CONV_TO(SIOCPHASE1, ifreq);
599 case SIOCPHASE232:
600 IOCTL_STRUCT_CONV_TO(SIOCPHASE2, ifreq);
601 #endif
602
603 case OOSIOCGIFCONF32:
604 IOCTL_STRUCT_CONV_TO(OOSIOCGIFCONF, ifconf);
605 case OSIOCGIFCONF32:
606 IOCTL_STRUCT_CONV_TO(OSIOCGIFCONF, ifconf);
607 case SIOCGIFCONF32:
608 IOCTL_STRUCT_CONV_TO(SIOCGIFCONF, ifconf);
609
610 case SIOCGIFFLAGS32:
611 IOCTL_STRUCT_CONV_TO(SIOCGIFFLAGS, ifreq);
612 case SIOCSIFFLAGS32:
613 IOCTL_STRUCT_CONV_TO(SIOCSIFFLAGS, ifreq);
614
615 case OSIOCGIFFLAGS32:
616 IOCTL_STRUCT_CONV_TO(OSIOCGIFFLAGS, oifreq);
617 case OSIOCSIFFLAGS32:
618 IOCTL_STRUCT_CONV_TO(OSIOCSIFFLAGS, oifreq);
619
620 case SIOCGIFMEDIA32:
621 IOCTL_STRUCT_CONV_TO(SIOCGIFMEDIA, ifmediareq);
622
623 case SIOCSDRVSPEC32:
624 IOCTL_STRUCT_CONV_TO(SIOCSDRVSPEC, ifdrv);
625
626 case SIOCGETVIFCNT32:
627 IOCTL_STRUCT_CONV_TO(SIOCGETVIFCNT, sioc_vif_req);
628
629 case SIOCGETSGCNT32:
630 IOCTL_STRUCT_CONV_TO(SIOCGETSGCNT, sioc_sg_req);
631
632 case VNDIOCSET32:
633 IOCTL_STRUCT_CONV_TO(VNDIOCSET, vnd_ioctl);
634
635 case VNDIOCCLR32:
636 IOCTL_STRUCT_CONV_TO(VNDIOCCLR, vnd_ioctl);
637
638 case VNDIOCGET32:
639 IOCTL_STRUCT_CONV_TO(VNDIOCGET, vnd_user);
640
641 case VNDIOCSET5032:
642 IOCTL_STRUCT_CONV_TO(VNDIOCSET50, vnd_ioctl50);
643
644 case VNDIOCCLR5032:
645 IOCTL_STRUCT_CONV_TO(VNDIOCCLR50, vnd_ioctl50);
646
647 default:
648 #ifdef NETBSD32_MD_IOCTL
649 error = netbsd32_md_ioctl(fp, com, data32, l);
650 #else
651 error = (*fp->f_ops->fo_ioctl)(fp, com, data32);
652 #endif
653 break;
654 }
655
656 if (error == EPASSTHROUGH)
657 error = ENOTTY;
658
659 /*
660 * Copy any data to user, size was
661 * already set and checked above.
662 */
663 if (error == 0 && (com&IOC_OUT) && size32) {
664 error = copyout(data32, SCARG_P32(uap, data), size32);
665 ktrgenio(fd, UIO_READ, SCARG_P32(uap, data),
666 size32, error);
667 }
668
669 /* If we allocated data, free it here. */
670 if (memp32)
671 kmem_free(memp32, (size_t)size32);
672 if (memp)
673 kmem_free(memp, (size_t)size);
674 out:
675 fd_putfile(fd);
676 return (error);
677 }
678