xref: /netbsd-src/sys/compat/netbsd32/netbsd32_ioctl.c (revision 481fca6e59249d8ffcf24fef7cfbe7b131bfb080)
1 /*	$NetBSD: netbsd32_ioctl.c,v 1.6 2000/07/09 13:39:31 mrg Exp $	*/
2 
3 /*
4  * Copyright (c) 1998 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  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 /*
32  * handle ioctl conversions from netbsd32 -> sparc64
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/audioio.h>
38 #include <sys/disklabel.h>
39 #include <sys/dkio.h>
40 #include <sys/malloc.h>
41 #include <sys/proc.h>
42 #include <sys/sockio.h>
43 #include <sys/socket.h>
44 #include <sys/ttycom.h>
45 #include <sys/mount.h>
46 #include <sys/syscallargs.h>
47 
48 #include <machine/fbio.h>
49 #include <machine/openpromio.h>
50 
51 #include <net/if.h>
52 #include <net/route.h>
53 
54 #include <netinet/in.h>
55 #include <netinet/in_var.h>
56 #include <netinet/igmp.h>
57 #include <netinet/igmp_var.h>
58 #include <netinet/ip_mroute.h>
59 
60 #include <compat/netbsd32/netbsd32.h>
61 #include <compat/netbsd32/netbsd32_ioctl.h>
62 #include <compat/netbsd32/netbsd32_syscallargs.h>
63 
64 /* prototypes for the converters */
65 static __inline void
66 netbsd32_to_fbcmap(struct netbsd32_fbcmap *, struct fbcmap *);
67 static __inline void
68 netbsd32_to_fbcursor(struct netbsd32_fbcursor *, struct fbcursor *);
69 static __inline void
70 netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *, struct opiocdesc *);
71 static __inline void
72 netbsd32_to_partinfo(struct netbsd32_partinfo *, struct partinfo *);
73 static __inline void
74 netbsd32_to_format_op(struct netbsd32_format_op *, struct format_op *);
75 static __inline void
76 netbsd32_to_ifconf(struct netbsd32_ifconf *, struct ifconf *);
77 static __inline void
78 netbsd32_to_ifmediareq(struct netbsd32_ifmediareq *, struct ifmediareq *);
79 static __inline void
80 netbsd32_to_ifdrv(struct netbsd32_ifdrv *, struct ifdrv *);
81 static __inline void
82 netbsd32_to_sioc_vif_req(struct netbsd32_sioc_vif_req *, struct sioc_vif_req *);
83 static __inline void
84 netbsd32_to_sioc_sg_req(struct netbsd32_sioc_sg_req *, struct sioc_sg_req *);
85 
86 static __inline void
87 netbsd32_from_fbcmap(struct fbcmap *, struct netbsd32_fbcmap *);
88 static __inline void
89 netbsd32_from_fbcursor(struct fbcursor *, struct netbsd32_fbcursor *);
90 static __inline void
91 netbsd32_from_opiocdesc(struct opiocdesc *, struct netbsd32_opiocdesc *);
92 static __inline void
93 netbsd32_from_format_op(struct format_op *, struct netbsd32_format_op *);
94 static __inline void
95 netbsd32_from_ifconf(struct ifconf *, struct netbsd32_ifconf *);
96 static __inline void
97 netbsd32_from_ifmediareq(struct ifmediareq *, struct netbsd32_ifmediareq *);
98 static __inline void
99 netbsd32_from_ifdrv(struct ifdrv *, struct netbsd32_ifdrv *);
100 static __inline void
101 netbsd32_from_sioc_vif_req(struct sioc_vif_req *, struct netbsd32_sioc_vif_req *);
102 static __inline void
103 netbsd32_from_sioc_sg_req(struct sioc_sg_req *, struct netbsd32_sioc_sg_req *);
104 
105 /* convert to/from different structures */
106 
107 static __inline void
108 netbsd32_to_fbcmap(s32p, p)
109 	struct netbsd32_fbcmap *s32p;
110 	struct fbcmap *p;
111 {
112 
113 	p->index = s32p->index;
114 	p->count = s32p->count;
115 	p->red = (u_char *)(u_long)s32p->red;
116 	p->green = (u_char *)(u_long)s32p->green;
117 	p->blue = (u_char *)(u_long)s32p->blue;
118 }
119 
120 static __inline void
121 netbsd32_to_fbcursor(s32p, p)
122 	struct netbsd32_fbcursor *s32p;
123 	struct fbcursor *p;
124 {
125 
126 	p->set = s32p->set;
127 	p->enable = s32p->enable;
128 	p->pos = s32p->pos;
129 	p->hot = s32p->hot;
130 	netbsd32_to_fbcmap(&s32p->cmap, &p->cmap);
131 	p->size = s32p->size;
132 	p->image = (char *)(u_long)s32p->image;
133 	p->mask = (char *)(u_long)s32p->mask;
134 }
135 
136 static __inline void
137 netbsd32_to_opiocdesc(s32p, p)
138 	struct netbsd32_opiocdesc *s32p;
139 	struct opiocdesc *p;
140 {
141 
142 	p->op_nodeid = s32p->op_nodeid;
143 	p->op_namelen = s32p->op_namelen;
144 	p->op_name = (char *)(u_long)s32p->op_name;
145 	p->op_buflen = s32p->op_buflen;
146 	p->op_buf = (char *)(u_long)s32p->op_buf;
147 }
148 
149 static __inline void
150 netbsd32_to_partinfo(s32p, p)
151 	struct netbsd32_partinfo *s32p;
152 	struct partinfo *p;
153 {
154 
155 	p->disklab = (struct disklabel *)(u_long)s32p->disklab;
156 	p->part = (struct partition *)(u_long)s32p->part;
157 }
158 
159 static __inline void
160 netbsd32_to_format_op(s32p, p)
161 	struct netbsd32_format_op *s32p;
162 	struct format_op *p;
163 {
164 
165 	p->df_buf = (char *)(u_long)s32p->df_buf;
166 	p->df_count = s32p->df_count;
167 	p->df_startblk = s32p->df_startblk;
168 	memcpy(p->df_reg, s32p->df_reg, sizeof(s32p->df_reg));
169 }
170 
171 #if 0 /* XXX see below */
172 static __inline void
173 netbsd32_to_ifreq(s32p, p, cmd)
174 	struct netbsd32_ifreq *s32p;
175 	struct ifreq *p;
176 	u_long cmd;	/* XXX unused yet */
177 {
178 
179 	/*
180 	 * XXX
181 	 * struct ifreq says the same, but sometimes the ifr_data
182 	 * union member needs to be converted to 64 bits... this
183 	 * is very driver specific and so we ignore it for now..
184 	 */
185 	memcpy(p, s32p, sizeof *s32p);
186 }
187 #endif
188 
189 static __inline void
190 netbsd32_to_ifconf(s32p, p)
191 	struct netbsd32_ifconf *s32p;
192 	struct ifconf *p;
193 {
194 
195 	p->ifc_len = s32p->ifc_len;
196 	/* ifc_buf & ifc_req are the same size so this works */
197 	p->ifc_buf = (caddr_t)(u_long)s32p->ifc_buf;
198 }
199 
200 static __inline void
201 netbsd32_to_ifmediareq(s32p, p)
202 	struct netbsd32_ifmediareq *s32p;
203 	struct ifmediareq *p;
204 {
205 
206 	memcpy(p, s32p, sizeof *s32p);
207 	p->ifm_ulist = (int *)(u_long)s32p->ifm_ulist;
208 }
209 
210 static __inline void
211 netbsd32_to_ifdrv(s32p, p)
212 	struct netbsd32_ifdrv *s32p;
213 	struct ifdrv *p;
214 {
215 
216 	memcpy(p, s32p, sizeof *s32p);
217 	p->ifd_data = (void *)(u_long)s32p->ifd_data;
218 }
219 
220 static __inline void
221 netbsd32_to_sioc_vif_req(s32p, p)
222 	struct netbsd32_sioc_vif_req *s32p;
223 	struct sioc_vif_req *p;
224 {
225 
226 	p->vifi = s32p->vifi;
227 	p->icount = (u_long)s32p->icount;
228 	p->ocount = (u_long)s32p->ocount;
229 	p->ibytes = (u_long)s32p->ibytes;
230 	p->obytes = (u_long)s32p->obytes;
231 }
232 
233 static __inline void
234 netbsd32_to_sioc_sg_req(s32p, p)
235 	struct netbsd32_sioc_sg_req *s32p;
236 	struct sioc_sg_req *p;
237 {
238 
239 	p->src = s32p->src;
240 	p->grp = s32p->grp;
241 	p->pktcnt = (u_long)s32p->pktcnt;
242 	p->bytecnt = (u_long)s32p->bytecnt;
243 	p->wrong_if = (u_long)s32p->wrong_if;
244 }
245 
246 /*
247  * handle ioctl conversions from sparc64 -> netbsd32
248  */
249 
250 static __inline void
251 netbsd32_from_fbcmap(p, s32p)
252 	struct fbcmap *p;
253 	struct netbsd32_fbcmap *s32p;
254 {
255 
256 	s32p->index = p->index;
257 	s32p->count = p->count;
258 /* filled in */
259 #if 0
260 	s32p->red = (netbsd32_u_charp)p->red;
261 	s32p->green = (netbsd32_u_charp)p->green;
262 	s32p->blue = (netbsd32_u_charp)p->blue;
263 #endif
264 }
265 
266 static __inline void
267 netbsd32_from_fbcursor(p, s32p)
268 	struct fbcursor *p;
269 	struct netbsd32_fbcursor *s32p;
270 {
271 
272 	s32p->set = p->set;
273 	s32p->enable = p->enable;
274 	s32p->pos = p->pos;
275 	s32p->hot = p->hot;
276 	netbsd32_from_fbcmap(&p->cmap, &s32p->cmap);
277 	s32p->size = p->size;
278 /* filled in */
279 #if 0
280 	s32p->image = (netbsd32_charp)p->image;
281 	s32p->mask = (netbsd32_charp)p->mask;
282 #endif
283 }
284 
285 static __inline void
286 netbsd32_from_opiocdesc(p, s32p)
287 	struct opiocdesc *p;
288 	struct netbsd32_opiocdesc *s32p;
289 {
290 
291 	s32p->op_nodeid = p->op_nodeid;
292 	s32p->op_namelen = p->op_namelen;
293 	s32p->op_name = (netbsd32_charp)(u_long)p->op_name;
294 	s32p->op_buflen = p->op_buflen;
295 	s32p->op_buf = (netbsd32_charp)(u_long)p->op_buf;
296 }
297 
298 static __inline void
299 netbsd32_from_format_op(p, s32p)
300 	struct format_op *p;
301 	struct netbsd32_format_op *s32p;
302 {
303 
304 /* filled in */
305 #if 0
306 	s32p->df_buf = (netbsd32_charp)p->df_buf;
307 #endif
308 	s32p->df_count = p->df_count;
309 	s32p->df_startblk = p->df_startblk;
310 	memcpy(s32p->df_reg, p->df_reg, sizeof(p->df_reg));
311 }
312 
313 #if 0 /* XXX see below */
314 static __inline void
315 netbsd32_from_ifreq(p, s32p, cmd)
316 	struct ifreq *p;
317 	struct netbsd32_ifreq *s32p;
318 	u_long cmd;	/* XXX unused yet */
319 {
320 
321 	/*
322 	 * XXX
323 	 * struct ifreq says the same, but sometimes the ifr_data
324 	 * union member needs to be converted to 64 bits... this
325 	 * is very driver specific and so we ignore it for now..
326 	 */
327 	*s32p = *p;
328 }
329 #endif
330 
331 static __inline void
332 netbsd32_from_ifconf(p, s32p)
333 	struct ifconf *p;
334 	struct netbsd32_ifconf *s32p;
335 {
336 
337 	s32p->ifc_len = p->ifc_len;
338 	/* ifc_buf & ifc_req are the same size so this works */
339 	s32p->ifc_buf = (netbsd32_caddr_t)(u_long)p->ifc_buf;
340 }
341 
342 static __inline void
343 netbsd32_from_ifmediareq(p, s32p)
344 	struct ifmediareq *p;
345 	struct netbsd32_ifmediareq *s32p;
346 {
347 
348 	memcpy(s32p, p, sizeof *p);
349 /* filled in? */
350 #if 0
351 	s32p->ifm_ulist = (netbsd32_intp_t)p->ifm_ulist;
352 #endif
353 }
354 
355 static __inline void
356 netbsd32_from_ifdrv(p, s32p)
357 	struct ifdrv *p;
358 	struct netbsd32_ifdrv *s32p;
359 {
360 
361 	memcpy(s32p, p, sizeof *p);
362 /* filled in? */
363 #if 0
364 	s32p->ifm_data = (netbsd32_u_longp_t)p->ifm_data;
365 #endif
366 }
367 
368 static __inline void
369 netbsd32_from_sioc_vif_req(p, s32p)
370 	struct sioc_vif_req *p;
371 	struct netbsd32_sioc_vif_req *s32p;
372 {
373 
374 	s32p->vifi = p->vifi;
375 	s32p->icount = (netbsd32_u_long)p->icount;
376 	s32p->ocount = (netbsd32_u_long)p->ocount;
377 	s32p->ibytes = (netbsd32_u_long)p->ibytes;
378 	s32p->obytes = (netbsd32_u_long)p->obytes;
379 }
380 
381 static __inline void
382 netbsd32_from_sioc_sg_req(p, s32p)
383 	struct sioc_sg_req *p;
384 	struct netbsd32_sioc_sg_req *s32p;
385 {
386 
387 	s32p->src = p->src;
388 	s32p->grp = p->grp;
389 	s32p->pktcnt = (netbsd32_u_long)p->pktcnt;
390 	s32p->bytecnt = (netbsd32_u_long)p->bytecnt;
391 	s32p->wrong_if = (netbsd32_u_long)p->wrong_if;
392 }
393 
394 
395 /*
396  * main ioctl syscall.
397  *
398  * ok, here we are in the biggy.  we have to do fix ups depending
399  * on the ioctl command before and afterwards.
400  */
401 int
402 netbsd32_ioctl(p, v, retval)
403 	struct proc *p;
404 	void *v;
405 	register_t *retval;
406 {
407 	struct netbsd32_ioctl_args /* {
408 		syscallarg(int) fd;
409 		syscallarg(netbsd32_u_long) com;
410 		syscallarg(netbsd32_voidp) data;
411 	} */ *uap = v;
412 	struct sys_ioctl_args ua;
413 	void *data = NULL;
414 	int rv;
415 
416 	/*
417 	 * we need to translate some commands (_IOW) before calling sys_ioctl,
418 	 * some after (_IOR), and some both (_IOWR).
419 	 */
420 #if 0
421 	{
422 char *dirs[8] = { "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!",
423 		"INOUT", "VOID|IN|OUT!" };
424 
425 printf("netbsd32_ioctl(%d, %x, %x): %s group %c base %d len %d\n",
426        SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data),
427        dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)],
428        IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)),
429        IOCPARM_LEN(SCARG(uap, com)));
430 	}
431 #endif
432 
433 /* we define some handy macros here... */
434 #define IOCTL_STRUCT_CONV_TO(type)	\
435 	data = malloc(sizeof(struct type), M_TEMP, M_WAITOK); \
436 	__CONCAT(netbsd32_to_, type)((struct __CONCAT(netbsd32_, type) *) \
437 	    (u_long)SCARG(uap, data), data)
438 
439 #define IOCTL_STRUCT_CONV_CMD_TO(type, cmd)	\
440 	data = malloc(sizeof(struct type), M_TEMP, M_WAITOK); \
441 	__CONCAT(netbsd32_to_, type)((struct __CONCAT(netbsd32_, type) *) \
442 	    (u_long)SCARG(uap, data), data, cmd)
443 
444 #define IOCTL_STRUCT_CONV_FROM(type)	\
445 	__CONCAT(netbsd32_from_, type)(data, \
446 	    (struct __CONCAT(netbsd32_, type) *) (u_long)SCARG(uap, data))
447 
448 #define IOCTL_STRUCT_CONV_CMD_FROM(type, cmd)	\
449 	__CONCAT(netbsd32_from_, type)(data, \
450 	    (struct __CONCAT(netbsd32_, type) *) (u_long)SCARG(uap, data), cmd)
451 
452 	/*
453 	 * convert various structures, pointers, and other objects that
454 	 * change size from 32 bit -> 64 bit, for all ioctl commands.
455 	 */
456 	switch (SCARG(uap, com)) {
457 	case FBIOPUTCMAP:
458 	case FBIOGETCMAP:
459 		IOCTL_STRUCT_CONV_TO(fbcmap);
460 		break;
461 
462 	case FBIOSCURSOR:
463 	case FBIOGCURSOR:
464 		IOCTL_STRUCT_CONV_TO(fbcursor);
465 		break;
466 
467 	case OPIOCGET:
468 	case OPIOCSET:
469 	case OPIOCNEXTPROP:
470 		IOCTL_STRUCT_CONV_TO(opiocdesc);
471 		break;
472 
473 	case DIOCGPART:
474 		IOCTL_STRUCT_CONV_TO(partinfo);
475 		break;
476 
477 	case DIOCRFORMAT:
478 	case DIOCWFORMAT:
479 		IOCTL_STRUCT_CONV_TO(format_op);
480 		break;
481 
482 /*
483  * only a few ifreq syscalls need conversion and those are
484  * all driver specific... XXX
485  */
486 #if 0
487 	case SIOCGADDRROM:
488 	case SIOCGCHIPID:
489 	case SIOCSIFADDR:
490 	case OSIOCGIFADDR:
491 	case SIOCGIFADDR:
492 	case SIOCSIFDSTADDR:
493 	case OSIOCGIFDSTADDR:
494 	case SIOCGIFDSTADDR:
495 	case SIOCSIFFLAGS:
496 	case SIOCGIFFLAGS:
497 	case OSIOCGIFBRDADDR:
498 	case SIOCGIFBRDADDR:
499 	case SIOCSIFBRDADDR:
500 	case OSIOCGIFNETMASK:
501 	case SIOCGIFNETMASK:
502 	case SIOCSIFNETMASK:
503 	case SIOCGIFMETRIC:
504 	case SIOCSIFMETRIC:
505 	case SIOCDIFADDR:
506 	case SIOCADDMULTI:
507 	case SIOCDELMULTI:
508 	case SIOCSIFMEDIA:
509 	case SIOCSIFMTU:
510 	case SIOCGIFMTU:
511 	case SIOCSIFASYNCMAP:
512 	case SIOCGIFASYNCMAP:
513 /*	case BIOCGETIF: READ ONLY */
514 	case BIOCSETIF:
515 	case SIOCPHASE1:
516 	case SIOCPHASE2:
517 		IOCTL_STRUCT_CONV_CMD_TO(ifreq, SCARG(uap, cmd));
518 		break;
519 #endif
520 
521 	case OSIOCGIFCONF:
522 	case SIOCGIFCONF:
523 		IOCTL_STRUCT_CONV_TO(ifconf);
524 		break;
525 
526 	case SIOCGIFMEDIA:
527 		IOCTL_STRUCT_CONV_TO(ifmediareq);
528 		break;
529 
530 	case SIOCSDRVSPEC:
531 		IOCTL_STRUCT_CONV_TO(ifdrv);
532 		break;
533 
534 	case SIOCGETVIFCNT:
535 		IOCTL_STRUCT_CONV_TO(sioc_vif_req);
536 		break;
537 
538 	case SIOCGETSGCNT:
539 		IOCTL_STRUCT_CONV_TO(sioc_sg_req);
540 		break;
541 
542 	}
543 
544 	/*
545 	 * if we malloced a new data segment, plug it into the
546 	 * syscall args, otherwise copy incoming one as a void
547 	 * pointer.  also copy the rest of the syscall args...
548 	 */
549 	if (data)
550 		SCARG(&ua, data) = data;
551 	else
552 		NETBSD32TOP_UAP(data, void);
553 	NETBSD32TO64_UAP(fd);
554 	NETBSD32TOX_UAP(com, u_long);
555 
556 	/* call the real ioctl */
557 	rv = sys_ioctl(p, &ua, retval);
558 
559 	/*
560 	 * convert _back_ to 32 bit the results of the command.
561 	 */
562 	switch (SCARG(uap, com)) {
563 	case FBIOGETCMAP:
564 		IOCTL_STRUCT_CONV_FROM(fbcmap);
565 		break;
566 
567 	case FBIOGCURSOR:
568 		IOCTL_STRUCT_CONV_FROM(fbcursor);
569 		break;
570 
571 	case OPIOCGET:
572 	case OPIOCNEXTPROP:
573 		IOCTL_STRUCT_CONV_FROM(opiocdesc);
574 		break;
575 
576 	case DIOCRFORMAT:
577 	case DIOCWFORMAT:
578 		IOCTL_STRUCT_CONV_FROM(format_op);
579 		break;
580 
581 /*
582  * only a few ifreq syscalls need conversion and those are
583  * all driver specific... XXX
584  */
585 #if 0
586 	case SIOCGADDRROM:
587 	case SIOCGCHIPID:
588 	case SIOCSIFADDR:
589 	case OSIOCGIFADDR:
590 	case SIOCGIFADDR:
591 	case SIOCSIFDSTADDR:
592 	case OSIOCGIFDSTADDR:
593 	case SIOCGIFDSTADDR:
594 	case SIOCSIFFLAGS:
595 	case SIOCGIFFLAGS:
596 	case OSIOCGIFBRDADDR:
597 	case SIOCGIFBRDADDR:
598 	case SIOCSIFBRDADDR:
599 	case OSIOCGIFNETMASK:
600 	case SIOCGIFNETMASK:
601 	case SIOCSIFNETMASK:
602 	case SIOCGIFMETRIC:
603 	case SIOCSIFMETRIC:
604 	case SIOCDIFADDR:
605 	case SIOCADDMULTI:
606 	case SIOCDELMULTI:
607 	case SIOCSIFMEDIA:
608 	case SIOCSIFMTU:
609 	case SIOCGIFMTU:
610 	case SIOCSIFASYNCMAP:
611 	case SIOCGIFASYNCMAP:
612 /*	case BIOCGETIF: READ ONLY */
613 	case BIOCSETIF:
614 	case SIOCPHASE1:
615 	case SIOCPHASE2:
616 		IOCTL_STRUCT_CONV_CMD_FROM(ifreq, SCARG(uap, cmd));
617 		break;
618 #endif
619 
620 	case OSIOCGIFCONF:
621 	case SIOCGIFCONF:
622 		IOCTL_STRUCT_CONV_FROM(ifconf);
623 		break;
624 
625 	case SIOCGIFMEDIA:
626 		IOCTL_STRUCT_CONV_FROM(ifmediareq);
627 		break;
628 
629 	case SIOCSDRVSPEC:
630 		IOCTL_STRUCT_CONV_FROM(ifdrv);
631 		break;
632 
633 	case SIOCGETVIFCNT:
634 		IOCTL_STRUCT_CONV_FROM(sioc_vif_req);
635 		break;
636 
637 	case SIOCGETSGCNT:
638 		IOCTL_STRUCT_CONV_FROM(sioc_sg_req);
639 		break;
640 	}
641 
642 	/* if we malloced data, free it here */
643 	if (data)
644 		free(data, M_TEMP);
645 
646 	/* done! */
647 	return (rv);
648 }
649