linux32_socket.c revision 1.6
1/* $NetBSD: linux32_socket.c,v 1.6 2008/06/19 16:09:25 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Emmanuel Dreyfus 17 * 4. The name of the author may not be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS'' 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include <sys/cdefs.h> 35 36__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.6 2008/06/19 16:09:25 christos Exp $"); 37 38#include <sys/types.h> 39#include <sys/param.h> 40#include <sys/fstypes.h> 41#include <sys/signal.h> 42#include <sys/dirent.h> 43#include <sys/kernel.h> 44#include <sys/fcntl.h> 45#include <sys/select.h> 46#include <sys/proc.h> 47#include <sys/ucred.h> 48#include <sys/swap.h> 49#include <sys/file.h> 50#include <sys/vnode.h> 51#include <sys/filedesc.h> 52 53#include <machine/types.h> 54 55#include <net/if.h> 56 57#include <sys/syscallargs.h> 58 59#include <compat/netbsd32/netbsd32.h> 60#include <compat/netbsd32/netbsd32_conv.h> 61#include <compat/netbsd32/netbsd32_syscallargs.h> 62#include <compat/sys/sockio.h> 63 64#include <compat/linux/common/linux_types.h> 65#include <compat/linux/common/linux_types.h> 66#include <compat/linux/common/linux_signal.h> 67#include <compat/linux/common/linux_machdep.h> 68#include <compat/linux/common/linux_misc.h> 69#include <compat/linux/common/linux_oldolduname.h> 70#include <compat/linux/common/linux_ioctl.h> 71#include <compat/linux/common/linux_sockio.h> 72#include <compat/linux/linux_syscallargs.h> 73 74#include <compat/linux32/common/linux32_types.h> 75#include <compat/linux32/common/linux32_signal.h> 76#include <compat/linux32/common/linux32_machdep.h> 77#include <compat/linux32/common/linux32_sysctl.h> 78#include <compat/linux32/common/linux32_socketcall.h> 79#include <compat/linux32/common/linux32_ioctl.h> 80#include <compat/linux32/linux32_syscallargs.h> 81 82int 83linux32_sys_socketpair(struct lwp *l, const struct linux32_sys_socketpair_args *uap, register_t *retval) 84{ 85 /* { 86 syscallarg(int) domain; 87 syscallarg(int) type; 88 syscallarg(int) protocol; 89 syscallarg(netbsd32_intp) rsv; 90 } */ 91 struct linux_sys_socketpair_args ua; 92 93 NETBSD32TO64_UAP(domain); 94 NETBSD32TO64_UAP(type); 95 NETBSD32TO64_UAP(protocol); 96 NETBSD32TOP_UAP(rsv, int) 97 98 return linux_sys_socketpair(l, &ua, retval); 99} 100 101int 102linux32_sys_sendto(struct lwp *l, const struct linux32_sys_sendto_args *uap, register_t *retval) 103{ 104 /* { 105 syscallarg(int) s; 106 syscallarg(netbsd32_voidp) msg; 107 syscallarg(int) len; 108 syscallarg(int) flags; 109 syscallarg(netbsd32_osockaddrp_t) to; 110 syscallarg(int) tolen; 111 } */ 112 struct linux_sys_sendto_args ua; 113 114 NETBSD32TO64_UAP(s); 115 NETBSD32TOP_UAP(msg, void); 116 NETBSD32TO64_UAP(len); 117 NETBSD32TO64_UAP(flags); 118 NETBSD32TOP_UAP(to, struct osockaddr); 119 NETBSD32TO64_UAP(tolen); 120 121 return linux_sys_sendto(l, &ua, retval); 122} 123 124 125int 126linux32_sys_recvfrom(struct lwp *l, const struct linux32_sys_recvfrom_args *uap, register_t *retval) 127{ 128 /* { 129 syscallarg(int) s; 130 syscallarg(netbsd32_voidp) buf; 131 syscallarg(netbsd32_size_t) len; 132 syscallarg(int) flags; 133 syscallarg(netbsd32_osockaddrp_t) from; 134 syscallarg(netbsd32_intp) fromlenaddr; 135 } */ 136 struct linux_sys_recvfrom_args ua; 137 138 NETBSD32TO64_UAP(s); 139 NETBSD32TOP_UAP(buf, void); 140 NETBSD32TO64_UAP(len); 141 NETBSD32TO64_UAP(flags); 142 NETBSD32TOP_UAP(from, struct osockaddr); 143 NETBSD32TOP_UAP(fromlenaddr, unsigned int); 144 145 return linux_sys_recvfrom(l, &ua, retval); 146} 147 148int 149linux32_sys_setsockopt(struct lwp *l, const struct linux32_sys_setsockopt_args *uap, register_t *retval) 150{ 151 /* { 152 syscallarg(int) s; 153 syscallarg(int) level; 154 syscallarg(int) optname; 155 syscallarg(netbsd32_voidp) optval; 156 syscallarg(int) optlen; 157 } */ 158 struct linux_sys_setsockopt_args ua; 159 160 NETBSD32TO64_UAP(s); 161 NETBSD32TO64_UAP(level); 162 NETBSD32TO64_UAP(optname); 163 NETBSD32TOP_UAP(optval, void); 164 NETBSD32TO64_UAP(optlen); 165 166 return linux_sys_setsockopt(l, &ua, retval); 167} 168 169 170int 171linux32_sys_getsockopt(struct lwp *l, const struct linux32_sys_getsockopt_args *uap, register_t *retval) 172{ 173 /* { 174 syscallarg(int) s; 175 syscallarg(int) level; 176 syscallarg(int) optname; 177 syscallarg(netbsd32_voidp) optval; 178 syscallarg(netbsd32_intp) optlen; 179 } */ 180 struct linux_sys_getsockopt_args ua; 181 182 NETBSD32TO64_UAP(s); 183 NETBSD32TO64_UAP(level); 184 NETBSD32TO64_UAP(optname); 185 NETBSD32TOP_UAP(optval, void); 186 NETBSD32TOP_UAP(optlen, int); 187 188 return linux_sys_getsockopt(l, &ua, retval); 189} 190 191int 192linux32_sys_socket(struct lwp *l, const struct linux32_sys_socket_args *uap, register_t *retval) 193{ 194 /* { 195 syscallarg(int) domain; 196 syscallarg(int) type; 197 syscallarg(int) protocol; 198 } */ 199 struct linux_sys_socket_args ua; 200 201 NETBSD32TO64_UAP(domain); 202 NETBSD32TO64_UAP(type); 203 NETBSD32TO64_UAP(protocol); 204 205 return linux_sys_socket(l, &ua, retval); 206} 207 208int 209linux32_sys_bind(struct lwp *l, const struct linux32_sys_bind_args *uap, register_t *retval) 210{ 211 /* { 212 syscallarg(int) s; 213 syscallarg(netbsd32_osockaddrp_t) name; 214 syscallarg(int) namelen; 215 } */ 216 struct linux_sys_bind_args ua; 217 218 NETBSD32TO64_UAP(s); 219 NETBSD32TOP_UAP(name, struct osockaddr) 220 NETBSD32TO64_UAP(namelen); 221 222 return linux_sys_bind(l, &ua, retval); 223} 224 225int 226linux32_sys_connect(struct lwp *l, const struct linux32_sys_connect_args *uap, register_t *retval) 227{ 228 /* { 229 syscallarg(int) s; 230 syscallarg(netbsd32_osockaddrp_t) name; 231 syscallarg(int) namelen; 232 } */ 233 struct linux_sys_connect_args ua; 234 235 NETBSD32TO64_UAP(s); 236 NETBSD32TOP_UAP(name, struct osockaddr) 237 NETBSD32TO64_UAP(namelen); 238 239#ifdef DEBUG_LINUX 240 printf("linux32_sys_connect: s = %d, name = %p, namelen = %d\n", 241 SCARG(&ua, s), SCARG(&ua, name), SCARG(&ua, namelen)); 242#endif 243 244 return linux_sys_connect(l, &ua, retval); 245} 246 247int 248linux32_sys_accept(struct lwp *l, const struct linux32_sys_accept_args *uap, register_t *retval) 249{ 250 /* { 251 syscallarg(int) s; 252 syscallarg(netbsd32_osockaddrp_t) name; 253 syscallarg(netbsd32_intp) anamelen; 254 } */ 255 struct linux_sys_accept_args ua; 256 257 NETBSD32TO64_UAP(s); 258 NETBSD32TOP_UAP(name, struct osockaddr) 259 NETBSD32TOP_UAP(anamelen, int); 260 261 return linux_sys_accept(l, &ua, retval); 262} 263 264int 265linux32_sys_getpeername(struct lwp *l, const struct linux32_sys_getpeername_args *uap, register_t *retval) 266{ 267 /* { 268 syscallarg(int) fdes; 269 syscallarg(netbsd32_sockaddrp_t) asa; 270 syscallarg(netbsd32_intp) alen; 271 } */ 272 struct linux_sys_getpeername_args ua; 273 274 NETBSD32TO64_UAP(fdes); 275 NETBSD32TOP_UAP(asa, struct sockaddr) 276 NETBSD32TOP_UAP(alen, int); 277 278 return linux_sys_getpeername(l, &ua, retval); 279} 280 281int 282linux32_sys_getsockname(struct lwp *l, const struct linux32_sys_getsockname_args *uap, register_t *retval) 283{ 284 /* { 285 syscallarg(int) fdec; 286 syscallarg(netbsd32_charp) asa; 287 syscallarg(netbsd32_intp) alen; 288 } */ 289 struct linux_sys_getsockname_args ua; 290 291 NETBSD32TO64_UAP(fdec); 292 NETBSD32TOP_UAP(asa, char) 293 NETBSD32TOP_UAP(alen, int); 294 295 return linux_sys_getsockname(l, &ua, retval); 296} 297 298int 299linux32_sys_sendmsg(struct lwp *l, const struct linux32_sys_sendmsg_args *uap, register_t *retval) 300{ 301 /* { 302 syscallarg(int) s; 303 syscallarg(netbsd32_msghdrp_t) msg; 304 syscallarg(int) flags; 305 } */ 306 struct linux_sys_sendmsg_args ua; 307 308 NETBSD32TO64_UAP(s); 309 NETBSD32TOP_UAP(msg, struct msghdr); 310 NETBSD32TO64_UAP(flags); 311 312 return linux_sys_sendmsg(l, &ua, retval); 313} 314 315int 316linux32_sys_recvmsg(struct lwp *l, const struct linux32_sys_recvmsg_args *uap, register_t *retval) 317{ 318 /* { 319 syscallarg(int) s; 320 syscallarg(netbsd32_msghdrp_t) msg; 321 syscallarg(int) flags; 322 } */ 323 struct linux_sys_recvmsg_args ua; 324 325 NETBSD32TO64_UAP(s); 326 NETBSD32TOP_UAP(msg, struct msghdr); 327 NETBSD32TO64_UAP(flags); 328 329 return linux_sys_recvmsg(l, &ua, retval); 330} 331 332int 333linux32_sys_send(struct lwp *l, const struct linux32_sys_send_args *uap, register_t *retval) 334{ 335 /* { 336 syscallarg(int) s; 337 syscallarg(netbsd32_voidp) buf; 338 syscallarg(int) len; 339 syscallarg(int) flags; 340 } */ 341 struct sys_sendto_args ua; 342 343 NETBSD32TO64_UAP(s); 344 NETBSD32TOP_UAP(buf, void); 345 NETBSD32TO64_UAP(len); 346 NETBSD32TO64_UAP(flags); 347 SCARG(&ua, to) = NULL; 348 SCARG(&ua, tolen) = 0; 349 350 return sys_sendto(l, &ua, retval); 351} 352 353int 354linux32_sys_recv(struct lwp *l, const struct linux32_sys_recv_args *uap, register_t *retval) 355{ 356 /* { 357 syscallarg(int) s; 358 syscallarg(netbsd32_voidp) buf; 359 syscallarg(int) len; 360 syscallarg(int) flags; 361 } */ 362 struct sys_recvfrom_args ua; 363 364 NETBSD32TO64_UAP(s); 365 NETBSD32TOP_UAP(buf, void); 366 NETBSD32TO64_UAP(len); 367 NETBSD32TO64_UAP(flags); 368 SCARG(&ua, from) = NULL; 369 SCARG(&ua, fromlenaddr) = NULL; 370 371 return sys_recvfrom(l, &ua, retval); 372} 373 374int 375linux32_ioctl_socket(struct lwp *l, const struct linux32_sys_ioctl_args *uap, register_t *retval) 376{ 377 /* { 378 syscallarg(int) fd; 379 syscallarg(u_long) com; 380 syscallarg(void *) data; 381 } */ 382 u_long com; 383 int error = 0, isdev = 0, dosys = 1; 384 struct netbsd32_ioctl_args ia; 385 file_t *fp; 386 struct vnode *vp; 387 int (*ioctlf)(file_t *, u_long, void *); 388 struct ioctl_pt pt; 389 390 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) 391 return (EBADF); 392 393 if (fp->f_type == DTYPE_VNODE) { 394 vp = (struct vnode *)fp->f_data; 395 isdev = vp->v_type == VCHR; 396 } 397 398 /* 399 * Don't try to interpret socket ioctl calls that are done 400 * on a device filedescriptor, just pass them through, to 401 * emulate Linux behaviour. Use PTIOCLINUX so that the 402 * device will only handle these if it's prepared to do 403 * so, to avoid unexpected things from happening. 404 */ 405 if (isdev) { 406 dosys = 0; 407 ioctlf = fp->f_ops->fo_ioctl; 408 pt.com = SCARG(uap, com); 409 pt.data = (void *)NETBSD32PTR64(SCARG(uap, data)); 410 error = ioctlf(fp, PTIOCLINUX, &pt); 411 /* 412 * XXX hack: if the function returns EJUSTRETURN, 413 * it has stuffed a sysctl return value in pt.data. 414 */ 415 if (error == EJUSTRETURN) { 416 retval[0] = (register_t)pt.data; 417 error = 0; 418 } 419 goto out; 420 } 421 422 com = SCARG(uap, com); 423 retval[0] = 0; 424 425 switch (com) { 426 case LINUX_SIOCGIFCONF: 427 SCARG(&ia, com) = OOSIOCGIFCONF; 428 break; 429 case LINUX_SIOCGIFFLAGS: 430 SCARG(&ia, com) = OSIOCGIFFLAGS; 431 break; 432 case LINUX_SIOCSIFFLAGS: 433 SCARG(&ia, com) = OSIOCSIFFLAGS; 434 break; 435 case LINUX_SIOCGIFADDR: 436 SCARG(&ia, com) = OOSIOCGIFADDR; 437 break; 438 case LINUX_SIOCGIFDSTADDR: 439 SCARG(&ia, com) = OOSIOCGIFDSTADDR; 440 break; 441 case LINUX_SIOCGIFBRDADDR: 442 SCARG(&ia, com) = OOSIOCGIFBRDADDR; 443 break; 444 case LINUX_SIOCGIFNETMASK: 445 SCARG(&ia, com) = OOSIOCGIFNETMASK; 446 break; 447 case LINUX_SIOCADDMULTI: 448 SCARG(&ia, com) = OSIOCADDMULTI; 449 break; 450 case LINUX_SIOCDELMULTI: 451 SCARG(&ia, com) = OSIOCDELMULTI; 452 break; 453#ifdef notyet 454 case LINUX_SIOCGIFHWADDR: 455 error = linux_getifhwaddr(l, retval, SCARG(uap, fd), 456 SCARG(uap, data)); 457 dosys = 0; 458 break; 459#endif 460 default: 461 error = EINVAL; 462 } 463 464 out: 465 fd_putfile(SCARG(uap, fd)); 466 467 if (error == 0 && dosys) { 468 SCARG(&ia, fd) = SCARG(uap, fd); 469 SCARG(&ia, data) = SCARG(uap, data); 470 error = netbsd32_ioctl(curlwp, &ia, retval); 471 } 472 473 return error; 474} 475