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