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