linux_socket.c revision 12458
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.1 1995/06/25 17:32:41 sos 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/sysproto.h>
45
46static int
47linux_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
67static int
68linux_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
78static 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
90static int
91linux_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
123struct linux_socket_args {
124    int domain;
125    int type;
126    int protocol;
127};
128
129static int
130linux_socket(struct proc *p, struct linux_socket_args *args, int *retval)
131{
132    struct linux_socket_args linux_args;
133    struct {
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
150struct linux_bind_args {
151    int s;
152    struct sockaddr *name;
153    int namelen;
154};
155
156static int
157linux_bind(struct proc *p, struct linux_bind_args *args, int *retval)
158{
159    struct linux_bind_args linux_args;
160    struct {
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
175struct linux_connect_args {
176    int s;
177    struct sockaddr * name;
178    int namelen;
179};
180
181static int
182linux_connect(struct proc *p, struct linux_connect_args *args, int *retval)
183{
184    struct linux_connect_args linux_args;
185    struct {
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
200struct linux_listen_args {
201    int s;
202    int backlog;
203};
204
205static int
206linux_listen(struct proc *p, struct linux_listen_args *args, int *retval)
207{
208    struct linux_listen_args linux_args;
209    struct {
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
222struct linux_accept_args {
223    int s;
224    struct sockaddr *addr;
225    int *namelen;
226};
227
228static int
229linux_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
247struct linux_getsockname_args {
248    int s;
249    struct sockaddr *addr;
250    int *namelen;
251};
252
253static int
254linux_getsockname(struct proc *p, struct linux_getsockname_args *args, int *retval)
255{
256    struct linux_getsockname_args linux_args;
257    struct {
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
272struct linux_getpeername_args {
273    int s;
274    struct sockaddr *addr;
275    int *namelen;
276};
277
278static int
279linux_getpeername(struct proc *p, struct linux_getpeername_args *args, int *retval)
280{
281    struct linux_getpeername_args linux_args;
282    struct getpeername_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
297struct linux_socketpair_args {
298    int domain;
299    int type;
300    int protocol;
301    int *rsv;
302};
303
304static int
305linux_socketpair(struct proc *p, struct linux_socketpair_args *args, int *retval)
306{
307    struct linux_socketpair_args linux_args;
308    struct {
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
327struct linux_send_args {
328    int s;
329    void *msg;
330    int len;
331    int flags;
332};
333
334static int
335linux_send(struct proc *p, struct linux_send_args *args, int *retval)
336{
337    struct linux_send_args linux_args;
338    struct {
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
355struct linux_recv_args {
356    int s;
357    void *msg;
358    int len;
359    int flags;
360};
361
362static int
363linux_recv(struct proc *p, struct linux_recv_args *args, int *retval)
364{
365    struct linux_recv_args linux_args;
366    struct {
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
383struct linux_sendto_args {
384    int s;
385    void *msg;
386    int len;
387    int flags;
388    caddr_t to;
389    int tolen;
390};
391
392static int
393linux_sendto(struct proc *p, struct linux_sendto_args *args, int *retval)
394{
395    struct linux_sendto_args linux_args;
396    struct {
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
417struct linux_recvfrom_args {
418    int s;
419    void *buf;
420    int len;
421    int flags;
422    caddr_t from;
423    int *fromlen;
424};
425
426static int
427linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args, int *retval)
428{
429    struct linux_recvfrom_args linux_args;
430    struct {
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
451struct linux_shutdown_args {
452    int s;
453    int how;
454};
455
456static int
457linux_shutdown(struct proc *p, struct linux_shutdown_args *args, int *retval)
458{
459    struct linux_shutdown_args linux_args;
460    struct {
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
473struct linux_setsockopt_args {
474    int s;
475    int level;
476    int optname;
477    void *optval;
478    int optlen;
479};
480
481static int
482linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args, int *retval)
483{
484    struct linux_setsockopt_args linux_args;
485    struct {
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
516struct linux_getsockopt_args {
517    int s;
518    int level;
519    int optname;
520    void *optval;
521    int *optlen;
522};
523
524static int
525linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval)
526{
527    struct linux_getsockopt_args linux_args;
528    struct {
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
558struct linux_socketcall_args {
559    int what;
560    void *args;
561};
562
563int
564linux_socketcall(struct proc *p, struct linux_socketcall_args *args,int *retval)
565{
566    switch (args->what) {
567    case LINUX_SOCKET:
568	return linux_socket(p, args->args, retval);
569    case LINUX_BIND:
570	return linux_bind(p, args->args, retval);
571    case LINUX_CONNECT:
572	return linux_connect(p, args->args, retval);
573    case LINUX_LISTEN:
574	return linux_listen(p, args->args, retval);
575    case LINUX_ACCEPT:
576	return linux_accept(p, args->args, retval);
577    case LINUX_GETSOCKNAME:
578	return linux_getsockname(p, args->args, retval);
579    case LINUX_GETPEERNAME:
580	return linux_getpeername(p, args->args, retval);
581    case LINUX_SOCKETPAIR:
582	return linux_socketpair(p, args->args, retval);
583    case LINUX_SEND:
584	return linux_send(p, args->args, retval);
585    case LINUX_RECV:
586	return linux_recv(p, args->args, retval);
587    case LINUX_SENDTO:
588	return linux_sendto(p, args->args, retval);
589    case LINUX_RECVFROM:
590	return linux_recvfrom(p, args->args, retval);
591    case LINUX_SHUTDOWN:
592	return linux_shutdown(p, args->args, retval);
593    case LINUX_SETSOCKOPT:
594	return linux_setsockopt(p, args->args, retval);
595    case LINUX_GETSOCKOPT:
596	return linux_getsockopt(p, args->args, retval);
597    default:
598	uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
599	return ENOSYS;
600    }
601}
602