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