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