linux_socket.c revision 21673
1/*- 2 * Copyright (c) 1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 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. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD: head/sys/compat/linux/linux_socket.c 21673 1997-01-14 07:20:47Z jkh $ 29 */ 30 31/* XXX we use functions that might not exist. */ 32#define COMPAT_43 1 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/sysproto.h> 37#include <sys/proc.h> 38#include <sys/socket.h> 39#include <sys/socketvar.h> 40 41#include <netinet/in.h> 42 43#include <i386/linux/linux.h> 44#include <i386/linux/linux_proto.h> 45 46static int 47linux_to_bsd_domain(int domain) 48{ 49 switch (domain) { 50 case LINUX_AF_UNSPEC: 51 return AF_UNSPEC; 52 case LINUX_AF_UNIX: 53 return AF_LOCAL; 54 case LINUX_AF_INET: 55 return AF_INET; 56 case LINUX_AF_AX25: 57 return AF_CCITT; 58 case LINUX_AF_IPX: 59 return AF_IPX; 60 case LINUX_AF_APPLETALK: 61 return AF_APPLETALK; 62 default: 63 return -1; 64 } 65} 66 67static int 68linux_to_bsd_sockopt_level(int level) 69{ 70 switch (level) { 71 case LINUX_SOL_SOCKET: 72 return SOL_SOCKET; 73 default: 74 return level; 75 } 76} 77 78static int linux_to_bsd_ip_sockopt(int opt) 79{ 80 switch (opt) { 81 case LINUX_IP_TOS: 82 return IP_TOS; 83 case LINUX_IP_TTL: 84 return IP_TTL; 85 case LINUX_IP_OPTIONS: 86 return IP_OPTIONS; 87 case LINUX_IP_MULTICAST_IF: 88 return IP_MULTICAST_IF; 89 case LINUX_IP_MULTICAST_TTL: 90 return IP_MULTICAST_TTL; 91 case LINUX_IP_MULTICAST_LOOP: 92 return IP_MULTICAST_LOOP; 93 case LINUX_IP_ADD_MEMBERSHIP: 94 return IP_ADD_MEMBERSHIP; 95 case LINUX_IP_DROP_MEMBERSHIP: 96 return IP_DROP_MEMBERSHIP; 97 case LINUX_IP_HDRINCL: 98 default: 99 return -1; 100 } 101} 102 103static int 104linux_to_bsd_so_sockopt(int opt) 105{ 106 switch (opt) { 107 case LINUX_SO_DEBUG: 108 return SO_DEBUG; 109 case LINUX_SO_REUSEADDR: 110 return SO_REUSEADDR; 111 case LINUX_SO_TYPE: 112 return SO_TYPE; 113 case LINUX_SO_ERROR: 114 return SO_ERROR; 115 case LINUX_SO_DONTROUTE: 116 return SO_DONTROUTE; 117 case LINUX_SO_BROADCAST: 118 return SO_BROADCAST; 119 case LINUX_SO_SNDBUF: 120 return SO_SNDBUF; 121 case LINUX_SO_RCVBUF: 122 return SO_RCVBUF; 123 case LINUX_SO_KEEPALIVE: 124 return SO_KEEPALIVE; 125 case LINUX_SO_OOBINLINE: 126 return SO_OOBINLINE; 127 case LINUX_SO_LINGER: 128 return SO_LINGER; 129 case LINUX_SO_PRIORITY: 130 case LINUX_SO_NO_CHECK: 131 default: 132 return -1; 133 } 134} 135 136struct linux_socket_args { 137 int domain; 138 int type; 139 int protocol; 140}; 141 142static int 143linux_socket(struct proc *p, struct linux_socket_args *args, int *retval) 144{ 145 struct linux_socket_args linux_args; 146 struct socket_args /* { 147 int domain; 148 int type; 149 int protocol; 150 } */ bsd_args; 151 int error; 152 153 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 154 return error; 155 bsd_args.protocol = linux_args.protocol; 156 bsd_args.type = linux_args.type; 157 bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 158 if (bsd_args.domain == -1) 159 return EINVAL; 160 return socket(p, &bsd_args, retval); 161} 162 163struct linux_bind_args { 164 int s; 165 struct sockaddr *name; 166 int namelen; 167}; 168 169static int 170linux_bind(struct proc *p, struct linux_bind_args *args, int *retval) 171{ 172 struct linux_bind_args linux_args; 173 struct bind_args /* { 174 int s; 175 caddr_t name; 176 int namelen; 177 } */ bsd_args; 178 int error; 179 180 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 181 return error; 182 bsd_args.s = linux_args.s; 183 bsd_args.name = (caddr_t)linux_args.name; 184 bsd_args.namelen = linux_args.namelen; 185 return bind(p, &bsd_args, retval); 186} 187 188struct linux_connect_args { 189 int s; 190 struct sockaddr * name; 191 int namelen; 192}; 193 194static int 195linux_connect(struct proc *p, struct linux_connect_args *args, int *retval) 196{ 197 struct linux_connect_args linux_args; 198 struct connect_args /* { 199 int s; 200 caddr_t name; 201 int namelen; 202 } */ bsd_args; 203 int error; 204 205 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 206 return error; 207 bsd_args.s = linux_args.s; 208 bsd_args.name = (caddr_t)linux_args.name; 209 bsd_args.namelen = linux_args.namelen; 210 return connect(p, &bsd_args, retval); 211} 212 213struct linux_listen_args { 214 int s; 215 int backlog; 216}; 217 218static int 219linux_listen(struct proc *p, struct linux_listen_args *args, int *retval) 220{ 221 struct linux_listen_args linux_args; 222 struct listen_args /* { 223 int s; 224 int backlog; 225 } */ bsd_args; 226 int error; 227 228 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 229 return error; 230 bsd_args.s = linux_args.s; 231 bsd_args.backlog = linux_args.backlog; 232 return listen(p, &bsd_args, retval); 233} 234 235struct linux_accept_args { 236 int s; 237 struct sockaddr *addr; 238 int *namelen; 239}; 240 241static int 242linux_accept(struct proc *p, struct linux_accept_args *args, int *retval) 243{ 244 struct linux_accept_args linux_args; 245 struct accept_args /* { 246 int s; 247 caddr_t name; 248 int *anamelen; 249 } */ bsd_args; 250 int error; 251 252 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 253 return error; 254 bsd_args.s = linux_args.s; 255 bsd_args.name = (caddr_t)linux_args.addr; 256 bsd_args.anamelen = linux_args.namelen; 257 return oaccept(p, &bsd_args, retval); 258} 259 260struct linux_getsockname_args { 261 int s; 262 struct sockaddr *addr; 263 int *namelen; 264}; 265 266static int 267linux_getsockname(struct proc *p, struct linux_getsockname_args *args, int *retval) 268{ 269 struct linux_getsockname_args linux_args; 270 struct getsockname_args /* { 271 int fdes; 272 caddr_t asa; 273 int *alen; 274 } */ bsd_args; 275 int error; 276 277 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 278 return error; 279 bsd_args.fdes = linux_args.s; 280 bsd_args.asa = (caddr_t) linux_args.addr; 281 bsd_args.alen = linux_args.namelen; 282 return ogetsockname(p, &bsd_args, retval); 283} 284 285struct linux_getpeername_args { 286 int s; 287 struct sockaddr *addr; 288 int *namelen; 289}; 290 291static int 292linux_getpeername(struct proc *p, struct linux_getpeername_args *args, int *retval) 293{ 294 struct linux_getpeername_args linux_args; 295 struct ogetpeername_args /* { 296 int fdes; 297 caddr_t asa; 298 int *alen; 299 } */ bsd_args; 300 int error; 301 302 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 303 return error; 304 bsd_args.fdes = linux_args.s; 305 bsd_args.asa = (caddr_t) linux_args.addr; 306 bsd_args.alen = linux_args.namelen; 307 return ogetpeername(p, &bsd_args, retval); 308} 309 310struct linux_socketpair_args { 311 int domain; 312 int type; 313 int protocol; 314 int *rsv; 315}; 316 317static int 318linux_socketpair(struct proc *p, struct linux_socketpair_args *args, int *retval) 319{ 320 struct linux_socketpair_args linux_args; 321 struct socketpair_args /* { 322 int domain; 323 int type; 324 int protocol; 325 int *rsv; 326 } */ bsd_args; 327 int error; 328 329 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 330 return error; 331 bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 332 if (bsd_args.domain == -1) 333 return EINVAL; 334 bsd_args.type = linux_args.type; 335 bsd_args.protocol = linux_args.protocol; 336 bsd_args.rsv = linux_args.rsv; 337 return socketpair(p, &bsd_args, retval); 338} 339 340struct linux_send_args { 341 int s; 342 void *msg; 343 int len; 344 int flags; 345}; 346 347static int 348linux_send(struct proc *p, struct linux_send_args *args, int *retval) 349{ 350 struct linux_send_args linux_args; 351 struct osend_args /* { 352 int s; 353 caddr_t buf; 354 int len; 355 int flags; 356 } */ bsd_args; 357 int error; 358 359 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 360 return error; 361 bsd_args.s = linux_args.s; 362 bsd_args.buf = linux_args.msg; 363 bsd_args.len = linux_args.len; 364 bsd_args.flags = linux_args.flags; 365 return osend(p, &bsd_args, retval); 366} 367 368struct linux_recv_args { 369 int s; 370 void *msg; 371 int len; 372 int flags; 373}; 374 375static int 376linux_recv(struct proc *p, struct linux_recv_args *args, int *retval) 377{ 378 struct linux_recv_args linux_args; 379 struct orecv_args /* { 380 int s; 381 caddr_t buf; 382 int len; 383 int flags; 384 } */ bsd_args; 385 int error; 386 387 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 388 return error; 389 bsd_args.s = linux_args.s; 390 bsd_args.buf = linux_args.msg; 391 bsd_args.len = linux_args.len; 392 bsd_args.flags = linux_args.flags; 393 return orecv(p, &bsd_args, retval); 394} 395 396struct linux_sendto_args { 397 int s; 398 void *msg; 399 int len; 400 int flags; 401 caddr_t to; 402 int tolen; 403}; 404 405static int 406linux_sendto(struct proc *p, struct linux_sendto_args *args, int *retval) 407{ 408 struct linux_sendto_args linux_args; 409 struct sendto_args /* { 410 int s; 411 caddr_t buf; 412 size_t len; 413 int flags; 414 caddr_t to; 415 int tolen; 416 } */ bsd_args; 417 int error; 418 419 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 420 return error; 421 bsd_args.s = linux_args.s; 422 bsd_args.buf = linux_args.msg; 423 bsd_args.len = linux_args.len; 424 bsd_args.flags = linux_args.flags; 425 bsd_args.to = linux_args.to; 426 bsd_args.tolen = linux_args.tolen; 427 return sendto(p, &bsd_args, retval); 428} 429 430struct linux_recvfrom_args { 431 int s; 432 void *buf; 433 int len; 434 int flags; 435 caddr_t from; 436 int *fromlen; 437}; 438 439static int 440linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args, int *retval) 441{ 442 struct linux_recvfrom_args linux_args; 443 struct recvfrom_args /* { 444 int s; 445 caddr_t buf; 446 size_t len; 447 int flags; 448 caddr_t from; 449 int *fromlenaddr; 450 } */ bsd_args; 451 int error; 452 453 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 454 return error; 455 bsd_args.s = linux_args.s; 456 bsd_args.buf = linux_args.buf; 457 bsd_args.len = linux_args.len; 458 bsd_args.flags = linux_args.flags; 459 bsd_args.from = linux_args.from; 460 bsd_args.fromlenaddr = linux_args.fromlen; 461 return orecvfrom(p, &bsd_args, retval); 462} 463 464struct linux_shutdown_args { 465 int s; 466 int how; 467}; 468 469static int 470linux_shutdown(struct proc *p, struct linux_shutdown_args *args, int *retval) 471{ 472 struct linux_shutdown_args linux_args; 473 struct shutdown_args /* { 474 int s; 475 int how; 476 } */ bsd_args; 477 int error; 478 479 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 480 return error; 481 bsd_args.s = linux_args.s; 482 bsd_args.how = linux_args.how; 483 return shutdown(p, &bsd_args, retval); 484} 485 486struct linux_setsockopt_args { 487 int s; 488 int level; 489 int optname; 490 void *optval; 491 int optlen; 492}; 493 494static int 495linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args, int *retval) 496{ 497 struct linux_setsockopt_args linux_args; 498 struct setsockopt_args /* { 499 int s; 500 int level; 501 int name; 502 caddr_t val; 503 int valsize; 504 } */ bsd_args; 505 int error, name; 506 507 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 508 return error; 509 bsd_args.s = linux_args.s; 510 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 511 switch (bsd_args.level) { 512 case SOL_SOCKET: 513 name = linux_to_bsd_so_sockopt(linux_args.optname); 514 break; 515 case IPPROTO_IP: 516 name = linux_to_bsd_ip_sockopt(linux_args.optname); 517 break; 518 default: 519 return EINVAL; 520 } 521 if (name == -1) 522 return EINVAL; 523 bsd_args.name = name; 524 bsd_args.val = linux_args.optval; 525 bsd_args.valsize = linux_args.optlen; 526 return setsockopt(p, &bsd_args, retval); 527} 528 529struct linux_getsockopt_args { 530 int s; 531 int level; 532 int optname; 533 void *optval; 534 int *optlen; 535}; 536 537static int 538linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval) 539{ 540 struct linux_getsockopt_args linux_args; 541 struct getsockopt_args /* { 542 int s; 543 int level; 544 int name; 545 caddr_t val; 546 int *avalsize; 547 } */ bsd_args; 548 int error, name; 549 550 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) 551 return error; 552 bsd_args.s = linux_args.s; 553 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 554 switch (bsd_args.level) { 555 case SOL_SOCKET: 556 name = linux_to_bsd_so_sockopt(linux_args.optname); 557 break; 558 case IPPROTO_IP: 559 name = linux_to_bsd_ip_sockopt(linux_args.optname); 560 break; 561 default: 562 return EINVAL; 563 } 564 if (name == -1) 565 return EINVAL; 566 bsd_args.val = linux_args.optval; 567 bsd_args.avalsize = linux_args.optlen; 568 return getsockopt(p, &bsd_args, retval); 569} 570 571int 572linux_socketcall(struct proc *p, struct linux_socketcall_args *args,int *retval) 573{ 574 switch (args->what) { 575 case LINUX_SOCKET: 576 return linux_socket(p, args->args, retval); 577 case LINUX_BIND: 578 return linux_bind(p, args->args, retval); 579 case LINUX_CONNECT: 580 return linux_connect(p, args->args, retval); 581 case LINUX_LISTEN: 582 return linux_listen(p, args->args, retval); 583 case LINUX_ACCEPT: 584 return linux_accept(p, args->args, retval); 585 case LINUX_GETSOCKNAME: 586 return linux_getsockname(p, args->args, retval); 587 case LINUX_GETPEERNAME: 588 return linux_getpeername(p, args->args, retval); 589 case LINUX_SOCKETPAIR: 590 return linux_socketpair(p, args->args, retval); 591 case LINUX_SEND: 592 return linux_send(p, args->args, retval); 593 case LINUX_RECV: 594 return linux_recv(p, args->args, retval); 595 case LINUX_SENDTO: 596 return linux_sendto(p, args->args, retval); 597 case LINUX_RECVFROM: 598 return linux_recvfrom(p, args->args, retval); 599 case LINUX_SHUTDOWN: 600 return linux_shutdown(p, args->args, retval); 601 case LINUX_SETSOCKOPT: 602 return linux_setsockopt(p, args->args, retval); 603 case LINUX_GETSOCKOPT: 604 return linux_getsockopt(p, args->args, retval); 605 default: 606 uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 607 return ENOSYS; 608 } 609} 610