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