linux_socketcall.c revision 1.11 1 /* $NetBSD: linux_socketcall.c,v 1.11 1995/09/19 22:37:35 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1995 Frank van der Linden
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project
18 * by Frank van der Linden
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h>
37 #include <sys/buf.h>
38 #include <sys/malloc.h>
39 #include <sys/ioctl.h>
40 #include <sys/tty.h>
41 #include <sys/file.h>
42 #include <sys/filedesc.h>
43 #include <sys/select.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <net/if.h>
47 #include <netinet/in.h>
48 #include <netinet/tcp.h>
49 #include <sys/mount.h>
50 #include <sys/proc.h>
51 #include <sys/vnode.h>
52 #include <sys/device.h>
53
54 #include <sys/syscallargs.h>
55
56 #include <compat/linux/linux_types.h>
57 #include <compat/linux/linux_util.h>
58 #include <compat/linux/linux_signal.h>
59 #include <compat/linux/linux_syscallargs.h>
60 #include <compat/linux/linux_ioctl.h>
61 #include <compat/linux/linux_socket.h>
62 #include <compat/linux/linux_socketcall.h>
63 #include <compat/linux/linux_sockio.h>
64
65 /*
66 * All the calls in this file are entered via one common system
67 * call in Linux, represented here by linux_socketcall()
68 * Arguments for the various calls are on the user stack. A pointer
69 * to them is the only thing that is passed. It is up to the various
70 * calls to copy them in themselves. To make it look better, they
71 * are copied to structures.
72 */
73
74 /*
75 * Convert between Linux and BSD socket domain values
76 */
77 int
78 linux_to_bsd_domain(ldom)
79 int ldom;
80 {
81 switch (ldom) {
82 case LINUX_AF_UNSPEC:
83 return AF_UNSPEC;
84 case LINUX_AF_UNIX:
85 return AF_LOCAL;
86 case LINUX_AF_INET:
87 return AF_INET;
88 case LINUX_AF_AX25:
89 return AF_CCITT;
90 case LINUX_AF_IPX:
91 return AF_IPX;
92 case LINUX_AF_APPLETALK:
93 return AF_APPLETALK;
94 default:
95 return -1;
96 }
97 }
98
99 int
100 linux_socket(p, args, retval)
101 struct proc *p;
102 struct linux_socket_args /* {
103 syscallarg(int) domain;
104 syscallarg(int) type;
105 syscallarg(int) protocol;
106 } */ *args;
107 register_t *retval;
108 {
109 struct linux_socket_args lsa;
110 struct socket_args bsa;
111 int error;
112
113 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa)))
114 return error;
115
116 SCARG(&bsa, protocol) = lsa.protocol;
117 SCARG(&bsa, type) = lsa.type;
118 SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
119 if (SCARG(&bsa, domain) == -1)
120 return EINVAL;
121 return socket(p, &bsa, retval);
122 }
123
124 int
125 linux_bind(p, args, retval)
126 struct proc *p;
127 struct linux_bind_args /* {
128 syscallarg(int) s;
129 syscallarg(struct sockaddr *) name;
130 syscallarg(int) namelen;
131 } */ *args;
132 register_t *retval;
133 {
134 struct linux_bind_args lba;
135 struct bind_args bba;
136 int error;
137
138 if ((error = copyin((caddr_t) args, (caddr_t) &lba, sizeof lba)))
139 return error;
140
141 SCARG(&bba, s) = lba.s;
142 SCARG(&bba, name) = (caddr_t) lba.name;
143 SCARG(&bba, namelen) = lba.namelen;
144
145 return bind(p, &bba, retval);
146 }
147
148 int
149 linux_connect(p, args, retval)
150 struct proc *p;
151 struct linux_connect_args /* {
152 syscallarg(int) s;
153 syscallarg(struct sockaddr *) name;
154 syscallarg(int) namelen;
155 } */ *args;
156 register_t *retval;
157 {
158 struct linux_connect_args lca;
159 struct connect_args bca;
160 int error;
161
162 if ((error = copyin((caddr_t) args, (caddr_t) &lca, sizeof lca)))
163 return error;
164
165 SCARG(&bca, s) = lca.s;
166 SCARG(&bca, name) = (caddr_t) lca.name;
167 SCARG(&bca, namelen) = lca.namelen;
168
169 return connect(p, &bca, retval);
170 }
171
172 int
173 linux_listen(p, args, retval)
174 struct proc *p;
175 struct linux_listen_args /* {
176 syscallarg(int) s;
177 syscallarg(int) backlog;
178 } */ *args;
179 register *retval;
180 {
181 struct linux_listen_args lla;
182 struct listen_args bla;
183 int error;
184
185 if ((error = copyin((caddr_t) args, (caddr_t) &lla, sizeof lla)))
186 return error;
187
188 SCARG(&bla, s) = lla.s;
189 SCARG(&bla, backlog) = lla.backlog;
190
191 return listen(p, &bla, retval);
192 }
193
194 int
195 linux_accept(p, args, retval)
196 struct proc *p;
197 struct linux_accept_args /* {
198 syscallarg(int) s;
199 syscallarg(struct sockaddr *) addr;
200 syscallarg(int *) namelen;
201 } */ *args;
202 register_t *retval;
203 {
204 struct linux_accept_args laa;
205 struct compat_43_accept_args baa;
206 int error;
207
208 if ((error = copyin((caddr_t) args, (caddr_t) &laa, sizeof laa)))
209 return error;
210
211 SCARG(&baa, s) = laa.s;
212 SCARG(&baa, name) = (caddr_t) laa.addr;
213 SCARG(&baa, anamelen) = laa.namelen;
214
215 return compat_43_accept(p, &baa, retval);
216 }
217
218 int
219 linux_getsockname(p, args, retval)
220 struct proc *p;
221 struct linux_getsockname_args /* {
222 syscallarg(int) s;
223 syscallarg(struct sockaddr *) addr;
224 syscallarg(int *) namelen;
225 } */ *args;
226 register_t *retval;
227 {
228 struct linux_getsockname_args lga;
229 struct compat_43_getsockname_args bga;
230 int error;
231
232 if ((error = copyin((caddr_t) args, (caddr_t) &lga, sizeof lga)))
233 return error;
234
235 SCARG(&bga, fdec) = lga.s;
236 SCARG(&bga, asa) = (caddr_t) lga.addr;
237 SCARG(&bga, alen) = lga.namelen;
238
239 return compat_43_getsockname(p, &bga, retval);
240 }
241
242 int
243 linux_getpeername(p, args, retval)
244 struct proc *p;
245 struct linux_getpeername_args /* {
246 syscallarg(int) s;
247 syscallarg(struct sockaddr *) addr;
248 syscallarg(int *) namelen;
249 } */ *args;
250 register_t *retval;
251 {
252 struct linux_getpeername_args lga;
253 struct compat_43_getpeername_args bga;
254 int error;
255
256 if ((error = copyin((caddr_t) args, (caddr_t) &lga, sizeof lga)))
257 return error;
258
259 SCARG(&bga, fdes) = lga.s;
260 SCARG(&bga, asa) = (caddr_t) lga.addr;
261 SCARG(&bga, alen) = lga.namelen;
262
263 return compat_43_getpeername(p, &bga, retval);
264 }
265
266 int
267 linux_socketpair(p, args, retval)
268 struct proc *p;
269 struct linux_socketpair_args /* {
270 syscallarg(int) domain;
271 syscallarg(int) type;
272 syscallarg(int) protocol;
273 syscallarg(int *) rsv;
274 } */ *args;
275 register_t *retval;
276 {
277 struct linux_socketpair_args lsa;
278 struct socketpair_args bsa;
279 int error;
280
281 if ((error = copyin((caddr_t) args, &lsa, sizeof lsa)))
282 return error;
283
284 SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
285 if (SCARG(&bsa, domain) == -1)
286 return EINVAL;
287 SCARG(&bsa, type) = lsa.type;
288 SCARG(&bsa, protocol) = lsa.protocol;
289 SCARG(&bsa, rsv) = lsa.rsv;
290
291 return socketpair(p, &bsa, retval);
292 }
293
294 int
295 linux_send(p, args, retval)
296 struct proc *p;
297 struct linux_send_args /* {
298 syscallarg(int) s;
299 syscallarg(void *) msg;
300 syscallarg(int) len;
301 syscallarg(int) flags;
302 } */ *args;
303 register_t *retval;
304 {
305 struct linux_send_args lsa;
306 struct compat_43_send_args bsa;
307 int error;
308
309 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa)))
310 return error;
311
312 SCARG(&bsa, s) = lsa.s;
313 SCARG(&bsa, buf) = lsa.msg;
314 SCARG(&bsa, len) = lsa.len;
315 SCARG(&bsa, flags) = lsa.flags;
316
317 return compat_43_send(p, &bsa, retval);
318 }
319
320 int
321 linux_recv(p, args, retval)
322 struct proc *p;
323 struct linux_recv_args *args;
324 register_t *retval;
325 {
326 struct linux_recv_args lra;
327 struct compat_43_recv_args bra;
328 int error;
329
330 if ((error = copyin((caddr_t) args, (caddr_t) &lra, sizeof lra)))
331 return error;
332
333 SCARG(&bra, s) = lra.s;
334 SCARG(&bra, buf) = lra.msg;
335 SCARG(&bra, len) = lra.len;
336 SCARG(&bra, flags) = lra.flags;
337
338 return compat_43_recv(p, &bra, retval);
339 }
340
341 int
342 linux_sendto(p, args, retval)
343 struct proc *p;
344 struct linux_sendto_args /* {
345 syscallarg(int) s;
346 syscallarg(void *) msg;
347 syscallarg(int) len;
348 syscallarg(int) flags;
349 syscallarg(sockaddr *) to;
350 syscallarg(int) tolen;
351 } */ *args;
352 register_t *retval;
353 {
354 struct linux_sendto_args lsa;
355 struct sendto_args bsa;
356 int error;
357
358 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa)))
359 return error;
360
361 SCARG(&bsa, s) = lsa.s;
362 SCARG(&bsa, buf) = lsa.msg;
363 SCARG(&bsa, len) = lsa.len;
364 SCARG(&bsa, flags) = lsa.flags;
365 SCARG(&bsa, to) = (caddr_t) lsa.to;
366 SCARG(&bsa, tolen) = lsa.tolen;
367
368 return sendto(p, &bsa, retval);
369 }
370
371 int
372 linux_recvfrom(p, v, retval)
373 struct proc *p;
374 void *v;
375 register_t *retval;
376 {
377 struct linux_recvfrom_args /* {
378 syscallarg(int) s;
379 syscallarg(void *) buf;
380 syscallarg(int) len;
381 syscallarg(int) flags;
382 syscallarg(struct sockaddr *) from;
383 syscallarg(int *) fromlen;
384 } */ *args = v;
385 struct linux_recvfrom_args lra;
386 struct compat_43_recvfrom_args bra;
387 int error;
388
389 if ((error = copyin((caddr_t) args, (caddr_t) &lra, sizeof lra)))
390 return error;
391
392 SCARG(&bra, s) = lra.s;
393 SCARG(&bra, buf) = lra.buf;
394 SCARG(&bra, len) = lra.len;
395 SCARG(&bra, flags) = lra.flags;
396 SCARG(&bra, from) = (caddr_t) lra.from;
397 SCARG(&bra, fromlenaddr) = lra.fromlen;
398
399 return compat_43_recvfrom(p, &bra, retval);
400 }
401
402 int
403 linux_shutdown(p, args, retval)
404 struct proc *p;
405 struct linux_shutdown_args /* {
406 syscallarg(int) s;
407 syscallarg(int) how;
408 } */ *args;
409 register_t *retval;
410 {
411 struct linux_shutdown_args lsa;
412 struct shutdown_args bsa;
413 int error;
414
415 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa)))
416 return error;
417
418 SCARG(&bsa, s) = lsa.s;
419 SCARG(&bsa, how) = lsa.how;
420
421 return shutdown(p, &bsa, retval);
422 }
423
424 /*
425 * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
426 * is different, the rest matches IPPROTO_* on both systems.
427 */
428 int
429 linux_to_bsd_sopt_level(llevel)
430 int llevel;
431 {
432 switch (llevel) {
433 case LINUX_SOL_SOCKET:
434 return SOL_SOCKET;
435 case LINUX_SOL_IP:
436 return IPPROTO_IP;
437 case LINUX_SOL_TCP:
438 return IPPROTO_TCP;
439 case LINUX_SOL_UDP:
440 return IPPROTO_UDP;
441 default:
442 return -1;
443 }
444 }
445
446 /*
447 * Convert Linux socket level socket option numbers to NetBSD values.
448 */
449 int
450 linux_to_bsd_so_sockopt(lopt)
451 int lopt;
452 {
453 switch (lopt) {
454 case LINUX_SO_DEBUG:
455 return SO_DEBUG;
456 case LINUX_SO_REUSEADDR:
457 return SO_REUSEADDR;
458 case LINUX_SO_TYPE:
459 return SO_TYPE;
460 case LINUX_SO_ERROR:
461 return SO_ERROR;
462 case LINUX_SO_DONTROUTE:
463 return SO_DONTROUTE;
464 case LINUX_SO_BROADCAST:
465 return SO_BROADCAST;
466 case LINUX_SO_SNDBUF:
467 return SO_SNDBUF;
468 case LINUX_SO_RCVBUF:
469 return SO_RCVBUF;
470 case LINUX_SO_KEEPALIVE:
471 return SO_KEEPALIVE;
472 case LINUX_SO_OOBINLINE:
473 return SO_OOBINLINE;
474 case LINUX_SO_LINGER:
475 return SO_LINGER;
476 case LINUX_SO_PRIORITY:
477 case LINUX_SO_NO_CHECK:
478 default:
479 return -1;
480 }
481 }
482
483 /*
484 * Convert Linux IP level socket option number to NetBSD values.
485 */
486 int
487 linux_to_bsd_ip_sockopt(lopt)
488 int lopt;
489 {
490 switch (lopt) {
491 case LINUX_IP_TOS:
492 return IP_TOS;
493 case LINUX_IP_TTL:
494 return IP_TTL;
495 case LINUX_IP_MULTICAST_TTL:
496 return IP_MULTICAST_TTL;
497 case LINUX_IP_MULTICAST_LOOP:
498 return IP_MULTICAST_LOOP;
499 case LINUX_IP_MULTICAST_IF:
500 return IP_MULTICAST_IF;
501 case LINUX_IP_ADD_MEMBERSHIP:
502 return IP_ADD_MEMBERSHIP;
503 case LINUX_IP_DROP_MEMBERSHIP:
504 return IP_DROP_MEMBERSHIP;
505 default:
506 return -1;
507 }
508 }
509
510 /*
511 * Convert Linux TCP level socket option number to NetBSD values.
512 */
513 int
514 linux_to_bsd_tcp_sockopt(lopt)
515 int lopt;
516 {
517 switch (lopt) {
518 case LINUX_TCP_NODELAY:
519 return TCP_NODELAY;
520 case LINUX_TCP_MAXSEG:
521 return TCP_MAXSEG;
522 default:
523 return -1;
524 }
525 }
526
527 /*
528 * Convert Linux UDP level socket option number to NetBSD values.
529 */
530 int
531 linux_to_bsd_udp_sockopt(lopt)
532 int lopt;
533 {
534 switch (lopt) {
535 default:
536 return -1;
537 }
538 }
539
540 /*
541 * Another reasonably straightforward function: setsockopt(2).
542 * The level and option numbers are converted; the values passed
543 * are not (yet) converted, the ones currently implemented don't
544 * need conversion, as they are the same on both systems.
545 */
546 int
547 linux_setsockopt(p, args, retval)
548 struct proc *p;
549 struct linux_setsockopt_args /* {
550 syscallarg(int) s;
551 syscallarg(int) level;
552 syscallarg(int) optname;
553 syscallarg(void *) optval;
554 syscallarg(int) optlen;
555 } */ *args;
556 register_t *retval;
557 {
558 struct linux_setsockopt_args lsa;
559 struct setsockopt_args bsa;
560 int error, name;
561
562 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa)))
563 return error;
564
565 SCARG(&bsa, s) = lsa.s;
566 SCARG(&bsa, level) = linux_to_bsd_sopt_level(lsa.level);
567 SCARG(&bsa, val) = lsa.optval;
568 SCARG(&bsa, valsize) = lsa.optlen;
569
570 switch (SCARG(&bsa, level)) {
571 case SOL_SOCKET:
572 name = linux_to_bsd_so_sockopt(lsa.optname);
573 break;
574 case IPPROTO_IP:
575 name = linux_to_bsd_ip_sockopt(lsa.optname);
576 break;
577 case IPPROTO_TCP:
578 name = linux_to_bsd_tcp_sockopt(lsa.optname);
579 break;
580 case IPPROTO_UDP:
581 name = linux_to_bsd_udp_sockopt(lsa.optname);
582 break;
583 default:
584 return EINVAL;
585 }
586
587 if (name == -1)
588 return EINVAL;
589 SCARG(&bsa, name) = name;
590
591 return setsockopt(p, &bsa, retval);
592 }
593
594 /*
595 * getsockopt(2) is very much the same as setsockopt(2) (see above)
596 */
597 int
598 linux_getsockopt(p, args, retval)
599 struct proc *p;
600 struct linux_getsockopt_args /* {
601 syscallarg(int) s;
602 syscallarg(int) level;
603 syscallarg(int) optname;
604 syscallarg(void *) optval;
605 syscallarg(int) *optlen;
606 } */ *args;
607 register_t *retval;
608 {
609 struct linux_getsockopt_args lga;
610 struct getsockopt_args bga;
611 int error, name;
612
613 if ((error = copyin((caddr_t) args, (caddr_t) &lga, sizeof lga)))
614 return error;
615
616 SCARG(&bga, s) = lga.s;
617 SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level);
618 SCARG(&bga, val) = lga.optval;
619 SCARG(&bga, avalsize) = lga.optlen;
620
621 switch (SCARG(&bga, level)) {
622 case SOL_SOCKET:
623 name = linux_to_bsd_so_sockopt(lga.optname);
624 break;
625 case IPPROTO_IP:
626 name = linux_to_bsd_ip_sockopt(lga.optname);
627 break;
628 case IPPROTO_TCP:
629 name = linux_to_bsd_tcp_sockopt(lga.optname);
630 break;
631 case IPPROTO_UDP:
632 name = linux_to_bsd_udp_sockopt(lga.optname);
633 break;
634 default:
635 return EINVAL;
636 }
637
638 if (name == -1)
639 return EINVAL;
640 SCARG(&bga, name) = name;
641
642 return getsockopt(p, &bga, retval);
643 }
644
645 /*
646 * Entry point to all Linux socket calls. Just check which call to
647 * make and take appropriate action.
648 */
649 int
650 linux_socketcall(p, v, retval)
651 struct proc *p;
652 void *v;
653 register_t *retval;
654 {
655 struct linux_socketcall_args /* {
656 syscallarg(int) what;
657 syscallarg(void *) args;
658 } */ *uap = v;
659
660 switch (SCARG(uap, what)) {
661 case LINUX_SYS_socket:
662 return linux_socket(p, SCARG(uap, args), retval);
663 case LINUX_SYS_bind:
664 return linux_bind(p, SCARG(uap, args), retval);
665 case LINUX_SYS_connect:
666 return linux_connect(p, SCARG(uap, args), retval);
667 case LINUX_SYS_listen:
668 return linux_listen(p, SCARG(uap, args), retval);
669 case LINUX_SYS_accept:
670 return linux_accept(p, SCARG(uap, args), retval);
671 case LINUX_SYS_getsockname:
672 return linux_getsockname(p, SCARG(uap, args), retval);
673 case LINUX_SYS_getpeername:
674 return linux_getpeername(p, SCARG(uap, args), retval);
675 case LINUX_SYS_socketpair:
676 return linux_socketpair(p, SCARG(uap, args), retval);
677 case LINUX_SYS_send:
678 return linux_send(p, SCARG(uap, args), retval);
679 case LINUX_SYS_recv:
680 return linux_recv(p, SCARG(uap, args), retval);
681 case LINUX_SYS_sendto:
682 return linux_sendto(p, SCARG(uap, args), retval);
683 case LINUX_SYS_recvfrom:
684 return linux_recvfrom(p, SCARG(uap, args), retval);
685 case LINUX_SYS_shutdown:
686 return linux_shutdown(p, SCARG(uap, args), retval);
687 case LINUX_SYS_setsockopt:
688 return linux_setsockopt(p, SCARG(uap, args), retval);
689 case LINUX_SYS_getsockopt:
690 return linux_getsockopt(p, SCARG(uap, args), retval);
691 default:
692 return ENOSYS;
693 }
694 }
695