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: src/sys/i386/linux/linux_socket.c,v 1.4.4.4 1999/09/05 08:14:18 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/fcntl.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41
42 #include <netinet/in.h>
43 #include <netinet/in_systm.h>
44 #include <netinet/ip.h>
45
46 #include <i386/linux/linux.h>
47 #include <i386/linux/linux_proto.h>
48 #include <i386/linux/linux_util.h>
49
50 static int
51 linux_to_bsd_domain(int domain)
52 {
53 switch (domain) {
54 case LINUX_AF_UNSPEC:
55 return AF_UNSPEC;
56 case LINUX_AF_UNIX:
57 return AF_LOCAL;
58 case LINUX_AF_INET:
59 return AF_INET;
60 case LINUX_AF_AX25:
61 return AF_CCITT;
62 case LINUX_AF_IPX:
63 return AF_IPX;
64 case LINUX_AF_APPLETALK:
65 return AF_APPLETALK;
66 default:
67 return -1;
68 }
69 }
70
71 static int
72 linux_to_bsd_sockopt_level(int level)
73 {
74 switch (level) {
75 case LINUX_SOL_SOCKET:
76 return SOL_SOCKET;
77 default:
78 return level;
79 }
80 }
81
82 static int linux_to_bsd_ip_sockopt(int opt)
83 {
84 switch (opt) {
85 case LINUX_IP_TOS:
86 return IP_TOS;
87 case LINUX_IP_TTL:
88 return IP_TTL;
89 case LINUX_IP_OPTIONS:
90 return IP_OPTIONS;
91 case LINUX_IP_MULTICAST_IF:
92 return IP_MULTICAST_IF;
93 case LINUX_IP_MULTICAST_TTL:
94 return IP_MULTICAST_TTL;
95 case LINUX_IP_MULTICAST_LOOP:
96 return IP_MULTICAST_LOOP;
97 case LINUX_IP_ADD_MEMBERSHIP:
98 return IP_ADD_MEMBERSHIP;
99 case LINUX_IP_DROP_MEMBERSHIP:
100 return IP_DROP_MEMBERSHIP;
101 case LINUX_IP_HDRINCL:
102 return IP_HDRINCL;
103 default:
104 return -1;
105 }
106 }
107
108 static int
109 linux_to_bsd_so_sockopt(int opt)
110 {
111 switch (opt) {
112 case LINUX_SO_DEBUG:
113 return SO_DEBUG;
114 case LINUX_SO_REUSEADDR:
115 return SO_REUSEADDR;
116 case LINUX_SO_TYPE:
117 return SO_TYPE;
118 case LINUX_SO_ERROR:
119 return SO_ERROR;
120 case LINUX_SO_DONTROUTE:
121 return SO_DONTROUTE;
122 case LINUX_SO_BROADCAST:
123 return SO_BROADCAST;
124 case LINUX_SO_SNDBUF:
125 return SO_SNDBUF;
126 case LINUX_SO_RCVBUF:
127 return SO_RCVBUF;
128 case LINUX_SO_KEEPALIVE:
129 return SO_KEEPALIVE;
130 case LINUX_SO_OOBINLINE:
131 return SO_OOBINLINE;
132 case LINUX_SO_LINGER:
133 return SO_LINGER;
134 case LINUX_SO_PRIORITY:
135 case LINUX_SO_NO_CHECK:
136 default:
137 return -1;
138 }
139 }
140
141 static int
142 linux_check_hdrincl(struct proc *p, int s)
143 {
144 struct getsockopt_args /* {
145 int s;
146 int level;
147 int name;
148 caddr_t val;
149 int *avalsize;
150 } */ bsd_args;
151 int error;
152 int retval_getsockopt;
153 caddr_t sg, val, valsize;
154 int size_val = sizeof val;
155 int optval;
156
157 sg = stackgap_init();
158 val = stackgap_alloc(&sg, sizeof(int));
159 valsize = stackgap_alloc(&sg, sizeof(int));
160
161 if ((error=copyout(&size_val, valsize, sizeof(size_val))))
162 return error;
163 bsd_args.s = s;
164 bsd_args.level = IPPROTO_IP;
165 bsd_args.name = IP_HDRINCL;
166 bsd_args.val = val;
167 bsd_args.avalsize = (int *)valsize;
168 if ((error=getsockopt(p, &bsd_args, &retval_getsockopt)))
169 return error;
170 if ((error=copyin(val, &optval, sizeof(optval))))
171 return error;
172 return optval == 0;
173 }
174
175 static int
176 linux_sendto_hdrincl(struct proc *p, struct sendto_args *bsd_args, int *retval)
177 {
178 /*
179 * linux_ip_copysize defines how many bytes we should copy
180 * from the beginning of the IP packet before we customize it for BSD.
181 * It should include all the fields we modify (ip_len and ip_off)
182 * and be as small as possible to minimize copying overhead.
183 */
184 #define linux_ip_copysize 8
185
186 caddr_t sg;
187 struct ip *packet;
188 struct msghdr *msg;
189 struct iovec *iov;
190
191 int error;
192 struct sendmsg_args /* {
193 int s;
194 caddr_t msg;
195 int flags;
196 } */ sendmsg_args;
197
198 /* Check the packet isn't too small before we mess with it */
199 if (bsd_args->len < linux_ip_copysize)
200 return EINVAL;
201
202 /*
203 * Tweaking the user buffer in place would be bad manners.
204 * We create a corrected IP header with just the needed length,
205 * then use an iovec to glue it to the rest of the user packet
206 * when calling sendmsg().
207 */
208 sg = stackgap_init();
209 packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize);
210 msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg));
211 iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2);
212
213 /* Make a copy of the beginning of the packet to be sent */
214 if ((error = copyin(bsd_args->buf, (caddr_t)packet, linux_ip_copysize)))
215 return error;
216
217 /* Convert fields from Linux to BSD raw IP socket format */
218 packet->ip_len = bsd_args->len;
219 packet->ip_off = ntohs(packet->ip_off);
220
221 /* Prepare the msghdr and iovec structures describing the new packet */
222 msg->msg_name = bsd_args->to;
223 msg->msg_namelen = bsd_args->tolen;
224 msg->msg_iov = iov;
225 msg->msg_iovlen = 2;
226 msg->msg_control = NULL;
227 msg->msg_controllen = 0;
228 msg->msg_flags = 0;
229 iov[0].iov_base = (char *)packet;
230 iov[0].iov_len = linux_ip_copysize;
231 iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize;
232 iov[1].iov_len = bsd_args->len - linux_ip_copysize;
233
234 sendmsg_args.s = bsd_args->s;
235 sendmsg_args.msg = (caddr_t)msg;
236 sendmsg_args.flags = bsd_args->flags;
237 return sendmsg(p, &sendmsg_args, retval);
238 }
239
240 struct linux_socket_args {
241 int domain;
242 int type;
243 int protocol;
244 };
245
246 static int
247 linux_socket(struct proc *p, struct linux_socket_args *args, int *retval)
248 {
249 struct linux_socket_args linux_args;
250 struct socket_args /* {
251 int domain;
252 int type;
253 int protocol;
254 } */ bsd_args;
255 int error;
256 int retval_socket;
257
258 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
259 return error;
260 bsd_args.protocol = linux_args.protocol;
261 bsd_args.type = linux_args.type;
262 bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
263 if (bsd_args.domain == -1)
264 return EINVAL;
265
266 retval_socket = socket(p, &bsd_args, retval);
267
268 if (retval_socket >= 0
269 && bsd_args.type == SOCK_RAW
270 && bsd_args.domain == AF_INET
271 && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)) {
272 /* It's a raw IP socket: set the IP_HDRINCL option. */
273 struct setsockopt_args /* {
274 int s;
275 int level;
276 int name;
277 caddr_t val;
278 int valsize;
279 } */ bsd_setsockopt_args;
280
281 int retval_setsockopt, r;
282 caddr_t sg;
283 //, hdrincl;
284 // int hdrinclval = 1;
285 int *hdrincl;
286
287 sg = stackgap_init();
288 hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl));
289 *hdrincl = 1;
290
291 bsd_setsockopt_args.s = *retval;
292 bsd_setsockopt_args.level = IPPROTO_IP;
293 bsd_setsockopt_args.name = IP_HDRINCL;
294 bsd_setsockopt_args.val = (caddr_t)hdrincl;
295 bsd_setsockopt_args.valsize = sizeof(*hdrincl);
296 r = setsockopt(p, &bsd_setsockopt_args, &retval_setsockopt);
297 }
298 return retval_socket;
299 }
300
301 struct linux_bind_args {
302 int s;
303 struct sockaddr *name;
304 int namelen;
305 };
306
307 static int
308 linux_bind(struct proc *p, struct linux_bind_args *args, int *retval)
309 {
310 struct linux_bind_args linux_args;
311 struct bind_args /* {
312 int s;
313 caddr_t name;
314 int namelen;
315 } */ bsd_args;
316 int error;
317
318 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
319 return error;
320 bsd_args.s = linux_args.s;
321 bsd_args.name = (caddr_t)linux_args.name;
322 bsd_args.namelen = linux_args.namelen;
323 return bind(p, &bsd_args, retval);
324 }
325
326 struct linux_connect_args {
327 int s;
328 struct sockaddr * name;
329 int namelen;
330 };
331
332 static int
333 linux_connect(struct proc *p, struct linux_connect_args *args, int *retval)
334 {
335 struct linux_connect_args linux_args;
336 struct connect_args /* {
337 int s;
338 caddr_t name;
339 int namelen;
340 } */ bsd_args;
341 int error;
342
343 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
344 return error;
345 bsd_args.s = linux_args.s;
346 bsd_args.name = (caddr_t)linux_args.name;
347 bsd_args.namelen = linux_args.namelen;
348 error = connect(p, &bsd_args, retval);
349 if (error == EISCONN) {
350 /*
351 * Linux doesn't return EISCONN the first time it occurs,
352 * when on a non-blocking socket. Instead it returns the
353 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
354 */
355 struct fcntl_args /* {
356 int fd;
357 int cmd;
358 int arg;
359 } */ bsd_fcntl_args;
360 struct getsockopt_args /* {
361 int s;
362 int level;
363 int name;
364 caddr_t val;
365 int *avalsize;
366 } */ bsd_getsockopt_args;
367 void *status, *statusl;
368 int stat, statl = sizeof stat;
369 caddr_t sg;
370
371 /* Check for non-blocking */
372 bsd_fcntl_args.fd = linux_args.s;
373 bsd_fcntl_args.cmd = F_GETFL;
374 bsd_fcntl_args.arg = 0;
375 error = fcntl(p, &bsd_fcntl_args, retval);
376 if (error == 0 && (*retval & O_NONBLOCK)) {
377 sg = stackgap_init();
378 status = stackgap_alloc(&sg, sizeof stat);
379 statusl = stackgap_alloc(&sg, sizeof statusl);
380
381 if ((error = copyout(&statl, statusl, sizeof statl)))
382 return error;
383
384 bsd_getsockopt_args.s = linux_args.s;
385 bsd_getsockopt_args.level = SOL_SOCKET;
386 bsd_getsockopt_args.name = SO_ERROR;
387 bsd_getsockopt_args.val = status;
388 bsd_getsockopt_args.avalsize = statusl;
389
390 error = getsockopt(p, &bsd_getsockopt_args, retval);
391 if (error)
392 return error;
393 if ((error = copyin(status, &stat, sizeof stat)))
394 return error;
395 *retval = stat;
396 return 0;
397 }
398 }
399 return error;
400 }
401
402 struct linux_listen_args {
403 int s;
404 int backlog;
405 };
406
407 static int
408 linux_listen(struct proc *p, struct linux_listen_args *args, int *retval)
409 {
410 struct linux_listen_args linux_args;
411 struct listen_args /* {
412 int s;
413 int backlog;
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.backlog = linux_args.backlog;
421 return listen(p, &bsd_args, retval);
422 }
423
424 struct linux_accept_args {
425 int s;
426 struct sockaddr *addr;
427 int *namelen;
428 };
429
430 static int
431 linux_accept(struct proc *p, struct linux_accept_args *args, int *retval)
432 {
433 struct linux_accept_args linux_args;
434 struct accept_args /* {
435 int s;
436 caddr_t name;
437 int *anamelen;
438 } */ bsd_args;
439 int error;
440
441 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
442 return error;
443 bsd_args.s = linux_args.s;
444 bsd_args.name = (caddr_t)linux_args.addr;
445 bsd_args.anamelen = linux_args.namelen;
446 return oaccept(p, &bsd_args, retval);
447 }
448
449 struct linux_getsockname_args {
450 int s;
451 struct sockaddr *addr;
452 int *namelen;
453 };
454
455 static int
456 linux_getsockname(struct proc *p, struct linux_getsockname_args *args, int *retval)
457 {
458 struct linux_getsockname_args linux_args;
459 struct getsockname_args /* {
460 int fdes;
461 caddr_t asa;
462 int *alen;
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.fdes = linux_args.s;
469 bsd_args.asa = (caddr_t) linux_args.addr;
470 bsd_args.alen = linux_args.namelen;
471 return ogetsockname(p, &bsd_args, retval);
472 }
473
474 struct linux_getpeername_args {
475 int s;
476 struct sockaddr *addr;
477 int *namelen;
478 };
479
480 static int
481 linux_getpeername(struct proc *p, struct linux_getpeername_args *args, int *retval)
482 {
483 struct linux_getpeername_args linux_args;
484 struct ogetpeername_args /* {
485 int fdes;
486 caddr_t asa;
487 int *alen;
488 } */ bsd_args;
489 int error;
490
491 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
492 return error;
493 bsd_args.fdes = linux_args.s;
494 bsd_args.asa = (caddr_t) linux_args.addr;
495 bsd_args.alen = linux_args.namelen;
496 return ogetpeername(p, &bsd_args, retval);
497 }
498
499 struct linux_socketpair_args {
500 int domain;
501 int type;
502 int protocol;
503 int *rsv;
504 };
505
506 static int
507 linux_socketpair(struct proc *p, struct linux_socketpair_args *args, int *retval)
508 {
509 struct linux_socketpair_args linux_args;
510 struct socketpair_args /* {
511 int domain;
512 int type;
513 int protocol;
514 int *rsv;
515 } */ bsd_args;
516 int error;
517
518 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
519 return error;
520 bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
521 if (bsd_args.domain == -1)
522 return EINVAL;
523 bsd_args.type = linux_args.type;
524 bsd_args.protocol = linux_args.protocol;
525 bsd_args.rsv = linux_args.rsv;
526 return socketpair(p, &bsd_args, retval);
527 }
528
529 struct linux_send_args {
530 int s;
531 void *msg;
532 int len;
533 int flags;
534 };
535
536 static int
537 linux_send(struct proc *p, struct linux_send_args *args, int *retval)
538 {
539 struct linux_send_args linux_args;
540 struct osend_args /* {
541 int s;
542 caddr_t buf;
543 int len;
544 int flags;
545 } */ bsd_args;
546 int error;
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.buf = linux_args.msg;
552 bsd_args.len = linux_args.len;
553 bsd_args.flags = linux_args.flags;
554 return osend(p, &bsd_args, retval);
555 }
556
557 struct linux_recv_args {
558 int s;
559 void *msg;
560 int len;
561 int flags;
562 };
563
564 static int
565 linux_recv(struct proc *p, struct linux_recv_args *args, int *retval)
566 {
567 struct linux_recv_args linux_args;
568 struct orecv_args /* {
569 int s;
570 caddr_t buf;
571 int len;
572 int flags;
573 } */ bsd_args;
574 int error;
575
576 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
577 return error;
578 bsd_args.s = linux_args.s;
579 bsd_args.buf = linux_args.msg;
580 bsd_args.len = linux_args.len;
581 bsd_args.flags = linux_args.flags;
582 return orecv(p, &bsd_args, retval);
583 }
584
585 struct linux_sendto_args {
586 int s;
587 void *msg;
588 int len;
589 int flags;
590 caddr_t to;
591 int tolen;
592 };
593
594 static int
595 linux_sendto(struct proc *p, struct linux_sendto_args *args, int *retval)
596 {
597 struct linux_sendto_args linux_args;
598 struct sendto_args /* {
599 int s;
600 caddr_t buf;
601 size_t len;
602 int flags;
603 caddr_t to;
604 int tolen;
605 } */ bsd_args;
606 int error;
607
608 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
609 return error;
610
611 bsd_args.s = linux_args.s;
612 bsd_args.buf = linux_args.msg;
613 bsd_args.len = linux_args.len;
614 bsd_args.flags = linux_args.flags;
615 bsd_args.to = linux_args.to;
616 bsd_args.tolen = linux_args.tolen;
617
618 if (linux_check_hdrincl(p, linux_args.s) == 0)
619 return linux_sendto_hdrincl(p, &bsd_args, retval);
620
621 return sendto(p, &bsd_args, retval);
622 }
623
624 struct linux_recvfrom_args {
625 int s;
626 void *buf;
627 int len;
628 int flags;
629 caddr_t from;
630 int *fromlen;
631 };
632
633 static int
634 linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args, int *retval)
635 {
636 struct linux_recvfrom_args linux_args;
637 struct recvfrom_args /* {
638 int s;
639 caddr_t buf;
640 size_t len;
641 int flags;
642 caddr_t from;
643 int *fromlenaddr;
644 } */ bsd_args;
645 int error;
646
647 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
648 return error;
649 bsd_args.s = linux_args.s;
650 bsd_args.buf = linux_args.buf;
651 bsd_args.len = linux_args.len;
652 bsd_args.flags = linux_args.flags;
653 bsd_args.from = linux_args.from;
654 bsd_args.fromlenaddr = linux_args.fromlen;
655 return orecvfrom(p, &bsd_args, retval);
656 }
657
658 struct linux_shutdown_args {
659 int s;
660 int how;
661 };
662
663 static int
664 linux_shutdown(struct proc *p, struct linux_shutdown_args *args, int *retval)
665 {
666 struct linux_shutdown_args linux_args;
667 struct shutdown_args /* {
668 int s;
669 int how;
670 } */ bsd_args;
671 int error;
672
673 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
674 return error;
675 bsd_args.s = linux_args.s;
676 bsd_args.how = linux_args.how;
677 return shutdown(p, &bsd_args, retval);
678 }
679
680 struct linux_setsockopt_args {
681 int s;
682 int level;
683 int optname;
684 void *optval;
685 int optlen;
686 };
687
688 static int
689 linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args, int *retval)
690 {
691 struct linux_setsockopt_args linux_args;
692 struct setsockopt_args /* {
693 int s;
694 int level;
695 int name;
696 caddr_t val;
697 int valsize;
698 } */ bsd_args;
699 int error, name;
700
701 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
702 return error;
703 bsd_args.s = linux_args.s;
704 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
705 switch (bsd_args.level) {
706 case SOL_SOCKET:
707 name = linux_to_bsd_so_sockopt(linux_args.optname);
708 break;
709 case IPPROTO_IP:
710 name = linux_to_bsd_ip_sockopt(linux_args.optname);
711 break;
712 case IPPROTO_TCP:
713 /* Linux TCP option values match BSD's */
714 name = linux_args.optname;
715 break;
716 default:
717 return EINVAL;
718 }
719 if (name == -1)
720 return EINVAL;
721 bsd_args.name = name;
722 bsd_args.val = linux_args.optval;
723 bsd_args.valsize = linux_args.optlen;
724 return setsockopt(p, &bsd_args, retval);
725 }
726
727 struct linux_getsockopt_args {
728 int s;
729 int level;
730 int optname;
731 void *optval;
732 int *optlen;
733 };
734
735 static int
736 linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval)
737 {
738 struct linux_getsockopt_args linux_args;
739 struct getsockopt_args /* {
740 int s;
741 int level;
742 int name;
743 caddr_t val;
744 int *avalsize;
745 } */ bsd_args;
746 int error, name;
747
748 if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
749 return error;
750 bsd_args.s = linux_args.s;
751 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
752 switch (bsd_args.level) {
753 case SOL_SOCKET:
754 name = linux_to_bsd_so_sockopt(linux_args.optname);
755 break;
756 case IPPROTO_IP:
757 name = linux_to_bsd_ip_sockopt(linux_args.optname);
758 break;
759 case IPPROTO_TCP:
760 /* Linux TCP option values match BSD's */
761 name = linux_args.optname;
762 break;
763 default:
764 return EINVAL;
765 }
766 if (name == -1)
767 return EINVAL;
768 bsd_args.name = name;
769 bsd_args.val = linux_args.optval;
770 bsd_args.avalsize = linux_args.optlen;
771 return getsockopt(p, &bsd_args, retval);
772 }
773
774 int
775 linux_socketcall(struct proc *p, struct linux_socketcall_args *args,int *retval)
776 {
777 switch (args->what) {
778 case LINUX_SOCKET:
779 return linux_socket(p, args->args, retval);
780 case LINUX_BIND:
781 return linux_bind(p, args->args, retval);
782 case LINUX_CONNECT:
783 return linux_connect(p, args->args, retval);
784 case LINUX_LISTEN:
785 return linux_listen(p, args->args, retval);
786 case LINUX_ACCEPT:
787 return linux_accept(p, args->args, retval);
788 case LINUX_GETSOCKNAME:
789 return linux_getsockname(p, args->args, retval);
790 case LINUX_GETPEERNAME:
791 return linux_getpeername(p, args->args, retval);
792 case LINUX_SOCKETPAIR:
793 return linux_socketpair(p, args->args, retval);
794 case LINUX_SEND:
795 return linux_send(p, args->args, retval);
796 case LINUX_RECV:
797 return linux_recv(p, args->args, retval);
798 case LINUX_SENDTO:
799 return linux_sendto(p, args->args, retval);
800 case LINUX_RECVFROM:
801 return linux_recvfrom(p, args->args, retval);
802 case LINUX_SHUTDOWN:
803 return linux_shutdown(p, args->args, retval);
804 case LINUX_SETSOCKOPT:
805 return linux_setsockopt(p, args->args, retval);
806 case LINUX_GETSOCKOPT:
807 return linux_getsockopt(p, args->args, retval);
808 default:
809 uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
810 return ENOSYS;
811 }
812 }
Cache object: 1ff56088d17a8164966a694274cde90e
|