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