linux_socketcall.c revision 1.10 1 /* $NetBSD: linux_socketcall.c,v 1.10 1995/08/14 01:27:55 mycroft 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, args, retval)
373 struct proc *p;
374 struct linux_recvfrom_args /* {
375 syscallarg(int) s;
376 syscallarg(void *) buf;
377 syscallarg(int) len;
378 syscallarg(int) flags;
379 syscallarg(struct sockaddr *) from;
380 syscallarg(int *) fromlen;
381 } */ *args;
382 {
383 struct linux_recvfrom_args lra;
384 struct compat_43_recvfrom_args bra;
385 int error;
386
387 if ((error = copyin((caddr_t) args, (caddr_t) &lra, sizeof lra)))
388 return error;
389
390 SCARG(&bra, s) = lra.s;
391 SCARG(&bra, buf) = lra.buf;
392 SCARG(&bra, len) = lra.len;
393 SCARG(&bra, flags) = lra.flags;
394 SCARG(&bra, from) = (caddr_t) lra.from;
395 SCARG(&bra, fromlenaddr) = lra.fromlen;
396
397 return compat_43_recvfrom(p, &bra, retval);
398 }
399
400 int
401 linux_shutdown(p, args, retval)
402 struct proc *p;
403 struct linux_shutdown_args /* {
404 syscallarg(int) s;
405 syscallarg(int) how;
406 } */ *args;
407 register_t *retval;
408 {
409 struct linux_shutdown_args lsa;
410 struct shutdown_args bsa;
411 int error;
412
413 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa)))
414 return error;
415
416 SCARG(&bsa, s) = lsa.s;
417 SCARG(&bsa, how) = lsa.how;
418
419 return shutdown(p, &bsa, retval);
420 }
421
422 /*
423 * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
424 * is different, the rest matches IPPROTO_* on both systems.
425 */
426 int
427 linux_to_bsd_sopt_level(llevel)
428 int llevel;
429 {
430 switch (llevel) {
431 case LINUX_SOL_SOCKET:
432 return SOL_SOCKET;
433 case LINUX_SOL_IP:
434 return IPPROTO_IP;
435 case LINUX_SOL_TCP:
436 return IPPROTO_TCP;
437 case LINUX_SOL_UDP:
438 return IPPROTO_UDP;
439 default:
440 return -1;
441 }
442 }
443
444 /*
445 * Convert Linux socket level socket option numbers to NetBSD values.
446 */
447 int
448 linux_to_bsd_so_sockopt(lopt)
449 int lopt;
450 {
451 switch (lopt) {
452 case LINUX_SO_DEBUG:
453 return SO_DEBUG;
454 case LINUX_SO_REUSEADDR:
455 return SO_REUSEADDR;
456 case LINUX_SO_TYPE:
457 return SO_TYPE;
458 case LINUX_SO_ERROR:
459 return SO_ERROR;
460 case LINUX_SO_DONTROUTE:
461 return SO_DONTROUTE;
462 case LINUX_SO_BROADCAST:
463 return SO_BROADCAST;
464 case LINUX_SO_SNDBUF:
465 return SO_SNDBUF;
466 case LINUX_SO_RCVBUF:
467 return SO_RCVBUF;
468 case LINUX_SO_KEEPALIVE:
469 return SO_KEEPALIVE;
470 case LINUX_SO_OOBINLINE:
471 return SO_OOBINLINE;
472 case LINUX_SO_LINGER:
473 return SO_LINGER;
474 case LINUX_SO_PRIORITY:
475 case LINUX_SO_NO_CHECK:
476 default:
477 return -1;
478 }
479 }
480
481 /*
482 * Convert Linux IP level socket option number to NetBSD values.
483 */
484 int
485 linux_to_bsd_ip_sockopt(lopt)
486 int lopt;
487 {
488 switch (lopt) {
489 case LINUX_IP_TOS:
490 return IP_TOS;
491 case LINUX_IP_TTL:
492 return IP_TTL;
493 case LINUX_IP_MULTICAST_TTL:
494 return IP_MULTICAST_TTL;
495 case LINUX_IP_MULTICAST_LOOP:
496 return IP_MULTICAST_LOOP;
497 case LINUX_IP_MULTICAST_IF:
498 return IP_MULTICAST_IF;
499 case LINUX_IP_ADD_MEMBERSHIP:
500 return IP_ADD_MEMBERSHIP;
501 case LINUX_IP_DROP_MEMBERSHIP:
502 return IP_DROP_MEMBERSHIP;
503 default:
504 return -1;
505 }
506 }
507
508 /*
509 * Convert Linux TCP level socket option number to NetBSD values.
510 */
511 int
512 linux_to_bsd_tcp_sockopt(lopt)
513 int lopt;
514 {
515 switch (lopt) {
516 case LINUX_TCP_NODELAY:
517 return TCP_NODELAY;
518 case LINUX_TCP_MAXSEG:
519 return TCP_MAXSEG;
520 default:
521 return -1;
522 }
523 }
524
525 /*
526 * Convert Linux UDP level socket option number to NetBSD values.
527 */
528 int
529 linux_to_bsd_udp_sockopt(lopt)
530 int lopt;
531 {
532 switch (lopt) {
533 default:
534 return -1;
535 }
536 }
537
538 /*
539 * Another reasonably straightforward function: setsockopt(2).
540 * The level and option numbers are converted; the values passed
541 * are not (yet) converted, the ones currently implemented don't
542 * need conversion, as they are the same on both systems.
543 */
544 int
545 linux_setsockopt(p, args, retval)
546 struct proc *p;
547 struct linux_setsockopt_args /* {
548 syscallarg(int) s;
549 syscallarg(int) level;
550 syscallarg(int) optname;
551 syscallarg(void *) optval;
552 syscallarg(int) optlen;
553 } */ *args;
554 register_t *retval;
555 {
556 struct linux_setsockopt_args lsa;
557 struct setsockopt_args bsa;
558 int error, name;
559
560 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa)))
561 return error;
562
563 SCARG(&bsa, s) = lsa.s;
564 SCARG(&bsa, level) = linux_to_bsd_sopt_level(lsa.level);
565 SCARG(&bsa, val) = lsa.optval;
566 SCARG(&bsa, valsize) = lsa.optlen;
567
568 switch (SCARG(&bsa, level)) {
569 case SOL_SOCKET:
570 name = linux_to_bsd_so_sockopt(lsa.optname);
571 break;
572 case IPPROTO_IP:
573 name = linux_to_bsd_ip_sockopt(lsa.optname);
574 break;
575 case IPPROTO_TCP:
576 name = linux_to_bsd_tcp_sockopt(lsa.optname);
577 break;
578 case IPPROTO_UDP:
579 name = linux_to_bsd_udp_sockopt(lsa.optname);
580 break;
581 default:
582 return EINVAL;
583 }
584
585 if (name == -1)
586 return EINVAL;
587 SCARG(&bsa, name) = name;
588
589 return setsockopt(p, &bsa, retval);
590 }
591
592 /*
593 * getsockopt(2) is very much the same as setsockopt(2) (see above)
594 */
595 int
596 linux_getsockopt(p, args, retval)
597 struct proc *p;
598 struct linux_getsockopt_args /* {
599 syscallarg(int) s;
600 syscallarg(int) level;
601 syscallarg(int) optname;
602 syscallarg(void *) optval;
603 syscallarg(int) *optlen;
604 } */ *args;
605 register_t *retval;
606 {
607 struct linux_getsockopt_args lga;
608 struct getsockopt_args bga;
609 int error, name;
610
611 if ((error = copyin((caddr_t) args, (caddr_t) &lga, sizeof lga)))
612 return error;
613
614 SCARG(&bga, s) = lga.s;
615 SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level);
616 SCARG(&bga, val) = lga.optval;
617 SCARG(&bga, avalsize) = lga.optlen;
618
619 switch (SCARG(&bga, level)) {
620 case SOL_SOCKET:
621 name = linux_to_bsd_so_sockopt(lga.optname);
622 break;
623 case IPPROTO_IP:
624 name = linux_to_bsd_ip_sockopt(lga.optname);
625 break;
626 case IPPROTO_TCP:
627 name = linux_to_bsd_tcp_sockopt(lga.optname);
628 break;
629 case IPPROTO_UDP:
630 name = linux_to_bsd_udp_sockopt(lga.optname);
631 break;
632 default:
633 return EINVAL;
634 }
635
636 if (name == -1)
637 return EINVAL;
638 SCARG(&bga, name) = name;
639
640 return getsockopt(p, &bga, retval);
641 }
642
643 /*
644 * Entry point to all Linux socket calls. Just check which call to
645 * make and take appropriate action.
646 */
647 int
648 linux_socketcall(p, uap, retval)
649 struct proc *p;
650 struct linux_socketcall_args /* {
651 syscallarg(int) what;
652 syscallarg(void *) args;
653 } */ *uap;
654 register_t *retval;
655 {
656 switch (SCARG(uap, what)) {
657 case LINUX_SYS_socket:
658 return linux_socket(p, SCARG(uap, args), retval);
659 case LINUX_SYS_bind:
660 return linux_bind(p, SCARG(uap, args), retval);
661 case LINUX_SYS_connect:
662 return linux_connect(p, SCARG(uap, args), retval);
663 case LINUX_SYS_listen:
664 return linux_listen(p, SCARG(uap, args), retval);
665 case LINUX_SYS_accept:
666 return linux_accept(p, SCARG(uap, args), retval);
667 case LINUX_SYS_getsockname:
668 return linux_getsockname(p, SCARG(uap, args), retval);
669 case LINUX_SYS_getpeername:
670 return linux_getpeername(p, SCARG(uap, args), retval);
671 case LINUX_SYS_socketpair:
672 return linux_socketpair(p, SCARG(uap, args), retval);
673 case LINUX_SYS_send:
674 return linux_send(p, SCARG(uap, args), retval);
675 case LINUX_SYS_recv:
676 return linux_recv(p, SCARG(uap, args), retval);
677 case LINUX_SYS_sendto:
678 return linux_sendto(p, SCARG(uap, args), retval);
679 case LINUX_SYS_recvfrom:
680 return linux_recvfrom(p, SCARG(uap, args), retval);
681 case LINUX_SYS_shutdown:
682 return linux_shutdown(p, SCARG(uap, args), retval);
683 case LINUX_SYS_setsockopt:
684 return linux_setsockopt(p, SCARG(uap, args), retval);
685 case LINUX_SYS_getsockopt:
686 return linux_getsockopt(p, SCARG(uap, args), retval);
687 default:
688 return ENOSYS;
689 }
690 }
691