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