1 /* $NetBSD: netbsd32_ioctl.c,v 1.67 2012/08/06 08:27:49 skrll 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.67 2012/08/06 08:27:49 skrll 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 #include <sys/clockctl.h> 56 57 #ifdef __sparc__ 58 #include <dev/sun/fbio.h> 59 #include <machine/openpromio.h> 60 #endif 61 62 #include <net/if.h> 63 #include <net/route.h> 64 65 #include <net/bpf.h> 66 #include <netinet/in.h> 67 #include <netinet/in_var.h> 68 #include <netinet/igmp.h> 69 #include <netinet/igmp_var.h> 70 #include <netinet/ip_mroute.h> 71 72 #include <compat/sys/sockio.h> 73 74 #include <compat/netbsd32/netbsd32.h> 75 #include <compat/netbsd32/netbsd32_ioctl.h> 76 #include <compat/netbsd32/netbsd32_syscallargs.h> 77 78 #include <dev/vndvar.h> 79 80 /* convert to/from different structures */ 81 82 static inline void 83 netbsd32_to_partinfo(struct netbsd32_partinfo *s32p, struct partinfo *p, u_long cmd) 84 { 85 86 p->disklab = (struct disklabel *)NETBSD32PTR64(s32p->disklab); 87 p->part = (struct partition *)NETBSD32PTR64(s32p->part); 88 } 89 90 #if 0 91 static inline void 92 netbsd32_to_format_op(struct netbsd32_format_op *s32p, struct format_op *p, u_long cmd) 93 { 94 95 p->df_buf = (char *)NETBSD32PTR64(s32p->df_buf); 96 p->df_count = s32p->df_count; 97 p->df_startblk = s32p->df_startblk; 98 memcpy(p->df_reg, s32p->df_reg, sizeof(s32p->df_reg)); 99 } 100 #endif 101 102 static inline void 103 netbsd32_to_ifreq(struct netbsd32_ifreq *s32p, struct ifreq *p, u_long cmd) 104 { 105 106 memcpy(p, s32p, sizeof *s32p); 107 /* 108 * XXX 109 * struct ifreq says the same, but sometimes the ifr_data 110 * union member needs to be converted to 64 bits... this 111 * is very driver specific and so we ignore it for now.. 112 */ 113 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) 114 p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data); 115 } 116 117 static inline void 118 netbsd32_to_oifreq(struct netbsd32_oifreq *s32p, struct oifreq *p, u_long cmd) 119 { 120 121 memcpy(p, s32p, sizeof *s32p); 122 /* 123 * XXX 124 * struct ifreq says the same, but sometimes the ifr_data 125 * union member needs to be converted to 64 bits... this 126 * is very driver specific and so we ignore it for now.. 127 */ 128 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) 129 p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data); 130 } 131 132 static inline void 133 netbsd32_to_if_addrprefreq(const struct netbsd32_if_addrprefreq *ifap32, 134 struct if_addrprefreq *ifap, u_long cmd) 135 { 136 strlcpy(ifap->ifap_name, ifap32->ifap_name, sizeof(ifap->ifap_name)); 137 ifap->ifap_preference = ifap32->ifap_preference; 138 memcpy(&ifap->ifap_addr, &ifap32->ifap_addr, 139 max(ifap32->ifap_addr.ss_len, _SS_MAXSIZE)); 140 } 141 142 static inline void 143 netbsd32_to_ifconf(struct netbsd32_ifconf *s32p, struct ifconf *p, u_long cmd) 144 { 145 146 p->ifc_len = s32p->ifc_len; 147 /* ifc_buf & ifc_req are the same size so this works */ 148 p->ifc_buf = (void *)NETBSD32PTR64(s32p->ifc_buf); 149 } 150 151 static inline void 152 netbsd32_to_ifmediareq(struct netbsd32_ifmediareq *s32p, struct ifmediareq *p, u_long cmd) 153 { 154 155 memcpy(p, s32p, sizeof *s32p); 156 p->ifm_ulist = (int *)NETBSD32PTR64(s32p->ifm_ulist); 157 } 158 159 static inline void 160 netbsd32_to_ifdrv(struct netbsd32_ifdrv *s32p, struct ifdrv *p, u_long cmd) 161 { 162 163 memcpy(p, s32p, sizeof *s32p); 164 p->ifd_data = (void *)NETBSD32PTR64(s32p->ifd_data); 165 } 166 167 static inline void 168 netbsd32_to_sioc_vif_req(struct netbsd32_sioc_vif_req *s32p, struct sioc_vif_req *p, u_long cmd) 169 { 170 171 p->vifi = s32p->vifi; 172 p->icount = (u_long)s32p->icount; 173 p->ocount = (u_long)s32p->ocount; 174 p->ibytes = (u_long)s32p->ibytes; 175 p->obytes = (u_long)s32p->obytes; 176 } 177 178 static inline void 179 netbsd32_to_sioc_sg_req(struct netbsd32_sioc_sg_req *s32p, struct sioc_sg_req *p, u_long cmd) 180 { 181 182 p->src = s32p->src; 183 p->grp = s32p->grp; 184 p->pktcnt = (u_long)s32p->pktcnt; 185 p->bytecnt = (u_long)s32p->bytecnt; 186 p->wrong_if = (u_long)s32p->wrong_if; 187 } 188 189 static inline void 190 netbsd32_to_vnd_ioctl(struct netbsd32_vnd_ioctl *s32p, struct vnd_ioctl *p, u_long cmd) 191 { 192 193 p->vnd_file = (char *)NETBSD32PTR64(s32p->vnd_file); 194 p->vnd_flags = s32p->vnd_flags; 195 p->vnd_geom = s32p->vnd_geom; 196 p->vnd_osize = s32p->vnd_osize; 197 p->vnd_size = s32p->vnd_size; 198 } 199 200 static inline void 201 netbsd32_to_vnd_user(struct netbsd32_vnd_user *s32p, struct vnd_user *p, u_long cmd) 202 { 203 204 p->vnu_unit = s32p->vnu_unit; 205 p->vnu_dev = s32p->vnu_dev; 206 p->vnu_ino = s32p->vnu_ino; 207 } 208 209 static inline void 210 netbsd32_to_vnd_ioctl50(struct netbsd32_vnd_ioctl50 *s32p, struct vnd_ioctl50 *p, u_long cmd) 211 { 212 213 p->vnd_file = (char *)NETBSD32PTR64(s32p->vnd_file); 214 p->vnd_flags = s32p->vnd_flags; 215 p->vnd_geom = s32p->vnd_geom; 216 p->vnd_size = s32p->vnd_size; 217 } 218 219 static inline void 220 netbsd32_to_plistref(struct netbsd32_plistref *s32p, struct plistref *p, u_long cmd) 221 { 222 223 p->pref_plist = NETBSD32PTR64(s32p->pref_plist); 224 p->pref_len = s32p->pref_len; 225 } 226 227 static inline void 228 netbsd32_to_u_long(netbsd32_u_long *s32p, u_long *p, u_long cmd) 229 { 230 231 *p = (u_long)*s32p; 232 } 233 234 static inline void 235 netbsd32_to_wdog_conf(struct netbsd32_wdog_conf *s32p, struct wdog_conf *p, u_long cmd) 236 { 237 238 p->wc_names = (char *)NETBSD32PTR64(s32p->wc_names); 239 p->wc_count = s32p->wc_count; 240 } 241 242 static inline void 243 netbsd32_to_bpf_program(struct netbsd32_bpf_program *s32p, struct bpf_program *p, u_long cmd) 244 { 245 246 p->bf_insns = (void *)NETBSD32PTR64(s32p->bf_insns); 247 p->bf_len = s32p->bf_len; 248 } 249 250 static inline void 251 netbsd32_to_bpf_dltlist(struct netbsd32_bpf_dltlist *s32p, struct bpf_dltlist *p, u_long cmd) 252 { 253 254 p->bfl_list = (void *)NETBSD32PTR64(s32p->bfl_list); 255 p->bfl_len = s32p->bfl_len; 256 } 257 258 /* wsdisplay stuff */ 259 static inline void 260 netbsd32_to_wsdisplay_addscreendata(struct netbsd32_wsdisplay_addscreendata *asd32, 261 struct wsdisplay_addscreendata *asd, 262 u_long cmd) 263 { 264 asd->screentype = (char *)NETBSD32PTR64(asd32->screentype); 265 asd->emul = (char *)NETBSD32PTR64(asd32->emul); 266 asd->idx = asd32->idx; 267 } 268 269 static inline void 270 netbsd32_to_ieee80211req(struct netbsd32_ieee80211req *ireq32, 271 struct ieee80211req *ireq, u_long cmd) 272 { 273 strncpy(ireq->i_name, ireq32->i_name, IFNAMSIZ); 274 ireq->i_type = ireq32->i_type; 275 ireq->i_val = ireq32->i_val; 276 ireq->i_len = ireq32->i_len; 277 ireq->i_data = NETBSD32PTR64(ireq32->i_data); 278 } 279 280 static inline void 281 netbsd32_to_ieee80211_nwkey(struct netbsd32_ieee80211_nwkey *nwk32, 282 struct ieee80211_nwkey *nwk, 283 u_long cmd) 284 { 285 int i; 286 287 strncpy(nwk->i_name, nwk32->i_name, IFNAMSIZ); 288 nwk->i_wepon = nwk32->i_wepon; 289 nwk->i_defkid = nwk32->i_defkid; 290 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 291 nwk->i_key[i].i_keylen = nwk32->i_key[i].i_keylen; 292 nwk->i_key[i].i_keydat = 293 NETBSD32PTR64(nwk32->i_key[i].i_keydat); 294 } 295 } 296 297 static inline void 298 netbsd32_to_wsdisplay_cursor(struct netbsd32_wsdisplay_cursor *c32, 299 struct wsdisplay_cursor *c, 300 u_long cmd) 301 { 302 c->which = c32->which; 303 c->enable = c32->enable; 304 c->pos.x = c32->pos.x; 305 c->pos.y = c32->pos.y; 306 c->hot.x = c32->hot.x; 307 c->hot.y = c32->hot.y; 308 c->size.x = c32->size.x; 309 c->size.y = c32->size.y; 310 c->cmap.index = c32->cmap.index; 311 c->cmap.count = c32->cmap.count; 312 c->cmap.red = NETBSD32PTR64(c32->cmap.red); 313 c->cmap.green = NETBSD32PTR64(c32->cmap.green); 314 c->cmap.blue = NETBSD32PTR64(c32->cmap.blue); 315 c->image = NETBSD32PTR64(c32->image); 316 c->mask = NETBSD32PTR64(c32->mask); 317 } 318 319 static inline void 320 netbsd32_to_clockctl_settimeofday( 321 const struct netbsd32_clockctl_settimeofday *s32p, 322 struct clockctl_settimeofday *p, 323 u_long cmd) 324 { 325 326 p->tv = NETBSD32PTR64(s32p->tv); 327 p->tzp = NETBSD32PTR64(s32p->tzp); 328 } 329 330 static inline void 331 netbsd32_to_clockctl_adjtime( 332 const struct netbsd32_clockctl_adjtime *s32p, 333 struct clockctl_adjtime *p, 334 u_long cmd) 335 { 336 337 p->delta = NETBSD32PTR64(s32p->delta); 338 p->olddelta = NETBSD32PTR64(s32p->olddelta); 339 } 340 341 static inline void 342 netbsd32_to_clockctl_clock_settime( 343 const struct netbsd32_clockctl_clock_settime *s32p, 344 struct clockctl_clock_settime *p, 345 u_long cmd) 346 { 347 348 p->clock_id = s32p->clock_id; 349 p->tp = NETBSD32PTR64(s32p->tp); 350 } 351 352 static inline void 353 netbsd32_to_clockctl_ntp_adjtime( 354 const struct netbsd32_clockctl_ntp_adjtime *s32p, 355 struct clockctl_ntp_adjtime *p, 356 u_long cmd) 357 { 358 359 p->tp = NETBSD32PTR64(s32p->tp); 360 p->retval = s32p->retval; 361 } 362 363 /* 364 * handle ioctl conversions from 64-bit kernel -> netbsd32 365 */ 366 367 static inline void 368 netbsd32_from_partinfo(struct partinfo *p, struct netbsd32_partinfo *s32p, u_long cmd) 369 { 370 371 NETBSD32PTR32(s32p->disklab, p->disklab); 372 NETBSD32PTR32(s32p->part, p->part); 373 } 374 375 #if 0 376 static inline void 377 netbsd32_from_format_op(struct format_op *p, struct netbsd32_format_op *s32p, u_long cmd) 378 { 379 380 /* filled in */ 381 #if 0 382 s32p->df_buf = (netbsd32_charp)p->df_buf; 383 #endif 384 s32p->df_count = p->df_count; 385 s32p->df_startblk = p->df_startblk; 386 memcpy(s32p->df_reg, p->df_reg, sizeof(p->df_reg)); 387 } 388 #endif 389 390 static inline void 391 netbsd32_from_ifreq(struct ifreq *p, struct netbsd32_ifreq *s32p, u_long cmd) 392 { 393 394 /* 395 * XXX 396 * struct ifreq says the same, but sometimes the ifr_data 397 * union member needs to be converted to 64 bits... this 398 * is very driver specific and so we ignore it for now.. 399 */ 400 memcpy(s32p, p, sizeof *s32p); 401 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) 402 NETBSD32PTR32(s32p->ifr_data, p->ifr_data); 403 } 404 405 static inline void 406 netbsd32_from_oifreq(struct oifreq *p, struct netbsd32_oifreq *s32p, u_long cmd) 407 { 408 409 /* 410 * XXX 411 * struct ifreq says the same, but sometimes the ifr_data 412 * union member needs to be converted to 64 bits... this 413 * is very driver specific and so we ignore it for now.. 414 */ 415 memcpy(s32p, p, sizeof *s32p); 416 if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) 417 NETBSD32PTR32(s32p->ifr_data, p->ifr_data); 418 } 419 420 static inline void 421 netbsd32_from_if_addrprefreq(const struct if_addrprefreq *ifap, 422 struct netbsd32_if_addrprefreq *ifap32, u_long cmd) 423 { 424 strlcpy(ifap32->ifap_name, ifap->ifap_name, sizeof(ifap32->ifap_name)); 425 ifap32->ifap_preference = ifap->ifap_preference; 426 memcpy(&ifap32->ifap_addr, &ifap->ifap_addr, 427 max(ifap->ifap_addr.ss_len, _SS_MAXSIZE)); 428 } 429 430 static inline void 431 netbsd32_from_ifconf(struct ifconf *p, struct netbsd32_ifconf *s32p, u_long cmd) 432 { 433 434 s32p->ifc_len = p->ifc_len; 435 /* ifc_buf & ifc_req are the same size so this works */ 436 NETBSD32PTR32(s32p->ifc_buf, p->ifc_buf); 437 } 438 439 static inline void 440 netbsd32_from_ifmediareq(struct ifmediareq *p, struct netbsd32_ifmediareq *s32p, u_long cmd) 441 { 442 443 memcpy(s32p, p, sizeof *p); 444 /* filled in? */ 445 #if 0 446 s32p->ifm_ulist = (netbsd32_intp_t)p->ifm_ulist; 447 #endif 448 } 449 450 static inline void 451 netbsd32_from_ifdrv(struct ifdrv *p, struct netbsd32_ifdrv *s32p, u_long cmd) 452 { 453 454 memcpy(s32p, p, sizeof *p); 455 /* filled in? */ 456 #if 0 457 s32p->ifm_data = (netbsd32_u_longp_t)p->ifm_data; 458 #endif 459 } 460 461 static inline void 462 netbsd32_from_sioc_vif_req(struct sioc_vif_req *p, struct netbsd32_sioc_vif_req *s32p, u_long cmd) 463 { 464 465 s32p->vifi = p->vifi; 466 s32p->icount = (netbsd32_u_long)p->icount; 467 s32p->ocount = (netbsd32_u_long)p->ocount; 468 s32p->ibytes = (netbsd32_u_long)p->ibytes; 469 s32p->obytes = (netbsd32_u_long)p->obytes; 470 } 471 472 static inline void 473 netbsd32_from_sioc_sg_req(struct sioc_sg_req *p, struct netbsd32_sioc_sg_req *s32p, u_long cmd) 474 { 475 476 s32p->src = p->src; 477 s32p->grp = p->grp; 478 s32p->pktcnt = (netbsd32_u_long)p->pktcnt; 479 s32p->bytecnt = (netbsd32_u_long)p->bytecnt; 480 s32p->wrong_if = (netbsd32_u_long)p->wrong_if; 481 } 482 483 static inline void 484 netbsd32_from_vnd_ioctl(struct vnd_ioctl *p, struct netbsd32_vnd_ioctl *s32p, u_long cmd) 485 { 486 487 s32p->vnd_flags = p->vnd_flags; 488 s32p->vnd_geom = p->vnd_geom; 489 s32p->vnd_osize = p->vnd_osize; 490 s32p->vnd_size = p->vnd_size; 491 } 492 493 static inline void 494 netbsd32_from_vnd_user(struct vnd_user *p, struct netbsd32_vnd_user *s32p, u_long cmd) 495 { 496 497 s32p->vnu_unit = p->vnu_unit; 498 s32p->vnu_dev = p->vnu_dev; 499 s32p->vnu_ino = p->vnu_ino; 500 } 501 502 static inline void 503 netbsd32_from_vnd_ioctl50(struct vnd_ioctl50 *p, struct netbsd32_vnd_ioctl50 *s32p, u_long cmd) 504 { 505 506 s32p->vnd_flags = p->vnd_flags; 507 s32p->vnd_geom = p->vnd_geom; 508 s32p->vnd_size = p->vnd_size; 509 } 510 511 static inline void 512 netbsd32_from_plistref(struct plistref *p, struct netbsd32_plistref *s32p, u_long cmd) 513 { 514 515 NETBSD32PTR32(s32p->pref_plist, p->pref_plist); 516 s32p->pref_len = p->pref_len; 517 } 518 519 static inline void 520 netbsd32_from_wdog_conf(struct wdog_conf *p, struct netbsd32_wdog_conf *s32p, u_long cmd) 521 { 522 523 NETBSD32PTR32(s32p->wc_names, p->wc_names); 524 s32p->wc_count = p->wc_count; 525 } 526 527 /* wsdisplay stuff */ 528 static inline void 529 netbsd32_from_wsdisplay_addscreendata(struct wsdisplay_addscreendata *asd, 530 struct netbsd32_wsdisplay_addscreendata *asd32, 531 u_long cmd) 532 { 533 NETBSD32PTR32(asd32->screentype, asd->screentype); 534 NETBSD32PTR32(asd32->emul, asd->emul); 535 asd32->idx = asd->idx; 536 } 537 538 static inline void 539 netbsd32_from_wsdisplay_cursor(struct wsdisplay_cursor *c, 540 struct netbsd32_wsdisplay_cursor *c32, 541 u_long cmd) 542 { 543 c32->which = c->which; 544 c32->enable = c->enable; 545 c32->pos.x = c->pos.x; 546 c32->pos.y = c->pos.y; 547 c32->hot.x = c->hot.x; 548 c32->hot.y = c->hot.y; 549 c32->size.x = c->size.x; 550 c32->size.y = c->size.y; 551 c32->cmap.index = c->cmap.index; 552 c32->cmap.count = c->cmap.count; 553 NETBSD32PTR32(c32->cmap.red, c->cmap.red); 554 NETBSD32PTR32(c32->cmap.green, c->cmap.green); 555 NETBSD32PTR32(c32->cmap.blue, c->cmap.blue); 556 NETBSD32PTR32(c32->image, c->image); 557 NETBSD32PTR32(c32->mask, c->mask); 558 } 559 560 static inline void 561 netbsd32_from_ieee80211req(struct ieee80211req *ireq, 562 struct netbsd32_ieee80211req *ireq32, u_long cmd) 563 { 564 strncpy(ireq32->i_name, ireq->i_name, IFNAMSIZ); 565 ireq32->i_type = ireq->i_type; 566 ireq32->i_val = ireq->i_val; 567 ireq32->i_len = ireq->i_len; 568 NETBSD32PTR32(ireq32->i_data, ireq->i_data); 569 } 570 571 static inline void 572 netbsd32_from_ieee80211_nwkey(struct ieee80211_nwkey *nwk, 573 struct netbsd32_ieee80211_nwkey *nwk32, 574 u_long cmd) 575 { 576 int i; 577 578 strncpy(nwk32->i_name, nwk->i_name, IFNAMSIZ); 579 nwk32->i_wepon = nwk->i_wepon; 580 nwk32->i_defkid = nwk->i_defkid; 581 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 582 nwk32->i_key[i].i_keylen = nwk->i_key[i].i_keylen; 583 NETBSD32PTR32(nwk32->i_key[i].i_keydat, 584 nwk->i_key[i].i_keydat); 585 } 586 } 587 588 static inline void 589 netbsd32_from_bpf_program(struct bpf_program *p, struct netbsd32_bpf_program *s32p, u_long cmd) 590 { 591 592 NETBSD32PTR32(s32p->bf_insns, p->bf_insns); 593 s32p->bf_len = p->bf_len; 594 } 595 596 static inline void 597 netbsd32_from_bpf_dltlist(struct bpf_dltlist *p, struct netbsd32_bpf_dltlist *s32p, u_long cmd) 598 { 599 600 NETBSD32PTR32(s32p->bfl_list, p->bfl_list); 601 s32p->bfl_len = p->bfl_len; 602 } 603 604 static inline void 605 netbsd32_from_u_long(u_long *p, netbsd32_u_long *s32p, u_long cmd) 606 { 607 608 *s32p = (netbsd32_u_long)*p; 609 } 610 611 static inline void 612 netbsd32_from_clockctl_settimeofday( 613 const struct clockctl_settimeofday *p, 614 struct netbsd32_clockctl_settimeofday *s32p, 615 u_long cmd) 616 { 617 618 NETBSD32PTR32(s32p->tv, p->tv); 619 NETBSD32PTR32(s32p->tzp, p->tzp); 620 } 621 622 static inline void 623 netbsd32_from_clockctl_adjtime( 624 const struct clockctl_adjtime *p, 625 struct netbsd32_clockctl_adjtime *s32p, 626 u_long cmd) 627 { 628 629 NETBSD32PTR32(s32p->delta, p->delta); 630 NETBSD32PTR32(s32p->olddelta, p->olddelta); 631 } 632 633 static inline void 634 netbsd32_from_clockctl_clock_settime( 635 const struct clockctl_clock_settime *p, 636 struct netbsd32_clockctl_clock_settime *s32p, 637 u_long cmd) 638 { 639 640 s32p->clock_id = p->clock_id; 641 NETBSD32PTR32(s32p->tp, p->tp); 642 } 643 644 static inline void 645 netbsd32_from_clockctl_ntp_adjtime( 646 const struct clockctl_ntp_adjtime *p, 647 struct netbsd32_clockctl_ntp_adjtime *s32p, 648 u_long cmd) 649 { 650 651 NETBSD32PTR32(s32p->tp, p->tp); 652 s32p->retval = p->retval; 653 } 654 655 /* 656 * main ioctl syscall. 657 * 658 * ok, here we are in the biggy. we have to do fix ups depending 659 * on the ioctl command before and afterwards. 660 */ 661 int 662 netbsd32_ioctl(struct lwp *l, const struct netbsd32_ioctl_args *uap, register_t *retval) 663 { 664 /* { 665 syscallarg(int) fd; 666 syscallarg(netbsd32_u_long) com; 667 syscallarg(netbsd32_voidp) data; 668 } */ 669 struct proc *p = l->l_proc; 670 struct file *fp; 671 struct filedesc *fdp; 672 u_long com; 673 int error = 0; 674 size_t size; 675 size_t alloc_size32, size32; 676 void *data, *memp = NULL; 677 void *data32, *memp32 = NULL; 678 unsigned int fd; 679 fdfile_t *ff; 680 int tmp; 681 #define STK_PARAMS 128 682 uint64_t stkbuf[STK_PARAMS/sizeof(uint64_t)]; 683 uint64_t stkbuf32[STK_PARAMS/sizeof(uint64_t)]; 684 685 /* 686 * we need to translate some commands (_IOW) before calling sys_ioctl, 687 * some after (_IOR), and some both (_IOWR). 688 */ 689 #if 0 690 { 691 const char * const dirs[8] = { 692 "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!", 693 "INOUT", "VOID|IN|OUT!" 694 }; 695 696 printf("netbsd32_ioctl(%d, %x, %x): " 697 "%s group %c base %d len %d\n", 698 SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data).i32, 699 dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)], 700 IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)), 701 IOCPARM_LEN(SCARG(uap, com))); 702 } 703 #endif 704 705 memp = NULL; 706 memp32 = NULL; 707 alloc_size32 = 0; 708 size32 = 0; 709 size = 0; 710 711 fdp = p->p_fd; 712 fd = SCARG(uap, fd); 713 if ((fp = fd_getfile(fd)) == NULL) 714 return (EBADF); 715 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 716 error = EBADF; 717 goto out; 718 } 719 720 ff = fdp->fd_dt->dt_ff[SCARG(uap, fd)]; 721 switch (com = SCARG(uap, com)) { 722 case FIOCLEX: 723 ff->ff_exclose = true; 724 fdp->fd_exclose = true; 725 goto out; 726 727 case FIONCLEX: 728 ff->ff_exclose = false; 729 goto out; 730 } 731 732 /* 733 * Interpret high order word to find amount of data to be 734 * copied to/from the user's address space. 735 */ 736 size32 = IOCPARM_LEN(com); 737 alloc_size32 = size32; 738 739 /* 740 * The disklabel is now padded to a multiple of 8 bytes however the old 741 * disklabel on 32bit platforms wasn't. This leaves a difference in 742 * size of 4 bytes between the two but are otherwise identical. 743 * To deal with this, we allocate enough space for the new disklabel 744 * but only copyin/out the smaller amount. 745 */ 746 if (IOCGROUP(com) == 'd') { 747 u_long ncom = com ^ (DIOCGDINFO ^ DIOCGDINFO32); 748 switch (ncom) { 749 case DIOCGDINFO: 750 case DIOCWDINFO: 751 case DIOCSDINFO: 752 case DIOCGDEFLABEL: 753 com = ncom; 754 if (IOCPARM_LEN(DIOCGDINFO32) < IOCPARM_LEN(DIOCGDINFO)) 755 alloc_size32 = IOCPARM_LEN(DIOCGDINFO); 756 break; 757 } 758 } 759 if (alloc_size32 > IOCPARM_MAX) { 760 error = ENOTTY; 761 goto out; 762 } 763 if (alloc_size32 > sizeof(stkbuf)) { 764 memp32 = kmem_alloc(alloc_size32, KM_SLEEP); 765 data32 = memp32; 766 } else 767 data32 = (void *)stkbuf32; 768 if ((com >> IOCPARM_SHIFT) == 0) { 769 /* UNIX-style ioctl. */ 770 data32 = SCARG_P32(uap, data); 771 } else { 772 if (com&IOC_IN) { 773 if (size32) { 774 error = copyin(SCARG_P32(uap, data), data32, 775 size32); 776 if (error) { 777 goto out; 778 } 779 /* 780 * The data between size and alloc_size has 781 * not been overwritten. It shouldn't matter 782 * but let's clear that anyway. 783 */ 784 if (__predict_false(size32 < alloc_size32)) { 785 memset((char *)data32+size32, 0, 786 alloc_size32 - size32); 787 } 788 ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data), 789 size32, 0); 790 } else 791 *(void **)data32 = SCARG_P32(uap, data); 792 } else if ((com&IOC_OUT) && size32) { 793 /* 794 * Zero the buffer so the user always 795 * gets back something deterministic. 796 */ 797 memset(data32, 0, alloc_size32); 798 } else if (com&IOC_VOID) { 799 *(void **)data32 = SCARG_P32(uap, data); 800 } 801 } 802 803 /* 804 * convert various structures, pointers, and other objects that 805 * change size from 32 bit -> 64 bit, for all ioctl commands. 806 */ 807 switch (SCARG(uap, com)) { 808 case FIONBIO: 809 mutex_enter(&fp->f_lock); 810 if ((tmp = *(int *)data32) != 0) 811 fp->f_flag |= FNONBLOCK; 812 else 813 fp->f_flag &= ~FNONBLOCK; 814 mutex_exit(&fp->f_lock); 815 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (void *)&tmp); 816 break; 817 818 case FIOASYNC: 819 mutex_enter(&fp->f_lock); 820 if ((tmp = *(int *)data32) != 0) 821 fp->f_flag |= FASYNC; 822 else 823 fp->f_flag &= ~FASYNC; 824 mutex_exit(&fp->f_lock); 825 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (void *)&tmp); 826 break; 827 828 case AUDIO_WSEEK32: 829 IOCTL_CONV_TO(AUDIO_WSEEK, u_long); 830 831 case DIOCGPART32: 832 IOCTL_STRUCT_CONV_TO(DIOCGPART, partinfo); 833 #if 0 /* not implemented by anything */ 834 case DIOCRFORMAT32: 835 IOCTL_STRUCT_CONV_TO(DIOCRFORMAT, format_op); 836 case DIOCWFORMAT32: 837 IOCTL_STRUCT_CONV_TO(DIOCWFORMAT, format_op); 838 #endif 839 840 /* 841 * only a few ifreq syscalls need conversion and those are 842 * all driver specific... XXX 843 */ 844 #if 0 845 case SIOCGADDRROM3232: 846 IOCTL_STRUCT_CONV_TO(SIOCGADDRROM32, ifreq); 847 case SIOCGCHIPID32: 848 IOCTL_STRUCT_CONV_TO(SIOCGCHIPID, ifreq); 849 case SIOCSIFADDR32: 850 IOCTL_STRUCT_CONV_TO(SIOCSIFADDR, ifreq); 851 case OSIOCGIFADDR32: 852 IOCTL_STRUCT_CONV_TO(OSIOCGIFADDR, ifreq); 853 case SIOCGIFADDR32: 854 IOCTL_STRUCT_CONV_TO(SIOCGIFADDR, ifreq); 855 case SIOCSIFDSTADDR32: 856 IOCTL_STRUCT_CONV_TO(SIOCSIFDSTADDR, ifreq); 857 case OSIOCGIFDSTADDR32: 858 IOCTL_STRUCT_CONV_TO(OSIOCGIFDSTADDR, ifreq); 859 case SIOCGIFDSTADDR32: 860 IOCTL_STRUCT_CONV_TO(SIOCGIFDSTADDR, ifreq); 861 case OSIOCGIFBRDADDR32: 862 IOCTL_STRUCT_CONV_TO(OSIOCGIFBRDADDR, ifreq); 863 case SIOCGIFBRDADDR32: 864 IOCTL_STRUCT_CONV_TO(SIOCGIFBRDADDR, ifreq); 865 case SIOCSIFBRDADDR32: 866 IOCTL_STRUCT_CONV_TO(SIOCSIFBRDADDR, ifreq); 867 case OSIOCGIFNETMASK32: 868 IOCTL_STRUCT_CONV_TO(OSIOCGIFNETMASK, ifreq); 869 case SIOCGIFNETMASK32: 870 IOCTL_STRUCT_CONV_TO(SIOCGIFNETMASK, ifreq); 871 case SIOCSIFNETMASK32: 872 IOCTL_STRUCT_CONV_TO(SIOCSIFNETMASK, ifreq); 873 case SIOCGIFMETRIC32: 874 IOCTL_STRUCT_CONV_TO(SIOCGIFMETRIC, ifreq); 875 case SIOCSIFMETRIC32: 876 IOCTL_STRUCT_CONV_TO(SIOCSIFMETRIC, ifreq); 877 case SIOCDIFADDR32: 878 IOCTL_STRUCT_CONV_TO(SIOCDIFADDR, ifreq); 879 case SIOCADDMULTI32: 880 IOCTL_STRUCT_CONV_TO(SIOCADDMULTI, ifreq); 881 case SIOCDELMULTI32: 882 IOCTL_STRUCT_CONV_TO(SIOCDELMULTI, ifreq); 883 case SIOCSIFMEDIA32: 884 IOCTL_STRUCT_CONV_TO(SIOCSIFMEDIA, ifreq); 885 case SIOCSIFMTU32: 886 IOCTL_STRUCT_CONV_TO(SIOCSIFMTU, ifreq); 887 case SIOCGIFMTU32: 888 IOCTL_STRUCT_CONV_TO(SIOCGIFMTU, ifreq); 889 case BIOCGETIF32: 890 IOCTL_STRUCT_CONV_TO(BIOCGETIF, ifreq); 891 case BIOCSETIF32: 892 IOCTL_STRUCT_CONV_TO(BIOCSETIF, ifreq); 893 case SIOCPHASE132: 894 IOCTL_STRUCT_CONV_TO(SIOCPHASE1, ifreq); 895 case SIOCPHASE232: 896 IOCTL_STRUCT_CONV_TO(SIOCPHASE2, ifreq); 897 #endif 898 899 case OOSIOCGIFCONF32: 900 IOCTL_STRUCT_CONV_TO(OOSIOCGIFCONF, ifconf); 901 case OSIOCGIFCONF32: 902 IOCTL_STRUCT_CONV_TO(OSIOCGIFCONF, ifconf); 903 case SIOCGIFCONF32: 904 IOCTL_STRUCT_CONV_TO(SIOCGIFCONF, ifconf); 905 906 case SIOCGIFFLAGS32: 907 IOCTL_STRUCT_CONV_TO(SIOCGIFFLAGS, ifreq); 908 case SIOCSIFFLAGS32: 909 IOCTL_STRUCT_CONV_TO(SIOCSIFFLAGS, ifreq); 910 911 case SIOCGIFADDRPREF32: 912 IOCTL_STRUCT_CONV_TO(SIOCGIFADDRPREF, if_addrprefreq); 913 case SIOCSIFADDRPREF32: 914 IOCTL_STRUCT_CONV_TO(SIOCSIFADDRPREF, if_addrprefreq); 915 916 917 case OSIOCGIFFLAGS32: 918 IOCTL_STRUCT_CONV_TO(OSIOCGIFFLAGS, oifreq); 919 case OSIOCSIFFLAGS32: 920 IOCTL_STRUCT_CONV_TO(OSIOCSIFFLAGS, oifreq); 921 922 case SIOCGIFMEDIA32: 923 IOCTL_STRUCT_CONV_TO(SIOCGIFMEDIA, ifmediareq); 924 925 case SIOCSDRVSPEC32: 926 IOCTL_STRUCT_CONV_TO(SIOCSDRVSPEC, ifdrv); 927 928 case SIOCGETVIFCNT32: 929 IOCTL_STRUCT_CONV_TO(SIOCGETVIFCNT, sioc_vif_req); 930 931 case SIOCGETSGCNT32: 932 IOCTL_STRUCT_CONV_TO(SIOCGETSGCNT, sioc_sg_req); 933 934 case VNDIOCSET32: 935 IOCTL_STRUCT_CONV_TO(VNDIOCSET, vnd_ioctl); 936 937 case VNDIOCCLR32: 938 IOCTL_STRUCT_CONV_TO(VNDIOCCLR, vnd_ioctl); 939 940 case VNDIOCGET32: 941 IOCTL_STRUCT_CONV_TO(VNDIOCGET, vnd_user); 942 943 case VNDIOCSET5032: 944 IOCTL_STRUCT_CONV_TO(VNDIOCSET50, vnd_ioctl50); 945 946 case VNDIOCCLR5032: 947 IOCTL_STRUCT_CONV_TO(VNDIOCCLR50, vnd_ioctl50); 948 949 case ENVSYS_GETDICTIONARY32: 950 IOCTL_STRUCT_CONV_TO(ENVSYS_GETDICTIONARY, plistref); 951 case ENVSYS_SETDICTIONARY32: 952 IOCTL_STRUCT_CONV_TO(ENVSYS_SETDICTIONARY, plistref); 953 case ENVSYS_REMOVEPROPS32: 954 IOCTL_STRUCT_CONV_TO(ENVSYS_REMOVEPROPS, plistref); 955 956 case WDOGIOC_GWDOGS32: 957 IOCTL_STRUCT_CONV_TO(WDOGIOC_GWDOGS, wdog_conf); 958 959 case BIOCSETF32: 960 IOCTL_STRUCT_CONV_TO(BIOCSETF, bpf_program); 961 case BIOCSTCPF32: 962 IOCTL_STRUCT_CONV_TO(BIOCSTCPF, bpf_program); 963 case BIOCSUDPF32: 964 IOCTL_STRUCT_CONV_TO(BIOCSUDPF, bpf_program); 965 case BIOCGDLTLIST32: 966 IOCTL_STRUCT_CONV_TO(BIOCGDLTLIST, bpf_dltlist); 967 968 case WSDISPLAYIO_ADDSCREEN32: 969 IOCTL_STRUCT_CONV_TO(WSDISPLAYIO_ADDSCREEN, wsdisplay_addscreendata); 970 971 case WSDISPLAYIO_GCURSOR32: 972 IOCTL_STRUCT_CONV_TO(WSDISPLAYIO_GCURSOR, wsdisplay_cursor); 973 case WSDISPLAYIO_SCURSOR32: 974 IOCTL_STRUCT_CONV_TO(WSDISPLAYIO_SCURSOR, wsdisplay_cursor); 975 976 case SIOCS8021132: 977 IOCTL_STRUCT_CONV_TO(SIOCS80211, ieee80211req); 978 case SIOCG8021132: 979 IOCTL_STRUCT_CONV_TO(SIOCG80211, ieee80211req); 980 case SIOCS80211NWKEY32: 981 IOCTL_STRUCT_CONV_TO(SIOCS80211NWKEY, ieee80211_nwkey); 982 case SIOCG80211NWKEY32: 983 IOCTL_STRUCT_CONV_TO(SIOCG80211NWKEY, ieee80211_nwkey); 984 985 case POWER_EVENT_RECVDICT32: 986 IOCTL_STRUCT_CONV_TO(POWER_EVENT_RECVDICT, plistref); 987 988 case CLOCKCTL_SETTIMEOFDAY32: 989 IOCTL_STRUCT_CONV_TO(CLOCKCTL_SETTIMEOFDAY, 990 clockctl_settimeofday); 991 case CLOCKCTL_ADJTIME32: 992 IOCTL_STRUCT_CONV_TO(CLOCKCTL_ADJTIME, clockctl_adjtime); 993 case CLOCKCTL_CLOCK_SETTIME32: 994 IOCTL_STRUCT_CONV_TO(CLOCKCTL_CLOCK_SETTIME, 995 clockctl_clock_settime); 996 case CLOCKCTL_NTP_ADJTIME32: 997 IOCTL_STRUCT_CONV_TO(CLOCKCTL_NTP_ADJTIME, 998 clockctl_ntp_adjtime); 999 1000 default: 1001 #ifdef NETBSD32_MD_IOCTL 1002 error = netbsd32_md_ioctl(fp, com, data32, l); 1003 #else 1004 error = (*fp->f_ops->fo_ioctl)(fp, com, data32); 1005 #endif 1006 break; 1007 } 1008 1009 if (error == EPASSTHROUGH) 1010 error = ENOTTY; 1011 1012 /* 1013 * Copy any data to user, size was 1014 * already set and checked above. 1015 */ 1016 if (error == 0 && (com&IOC_OUT) && size32) { 1017 error = copyout(data32, SCARG_P32(uap, data), size32); 1018 ktrgenio(fd, UIO_READ, SCARG_P32(uap, data), 1019 size32, error); 1020 } 1021 1022 out: 1023 /* If we allocated data, free it here. */ 1024 if (memp32) 1025 kmem_free(memp32, alloc_size32); 1026 if (memp) 1027 kmem_free(memp, size); 1028 fd_putfile(fd); 1029 return (error); 1030 } 1031