xref: /f-stack/lib/ff_syscall_wrapper.c (revision a9643ea8)
1*a9643ea8Slogwang /*
2*a9643ea8Slogwang  * Copyright (c) 2010 Kip Macy. All rights reserved.
3*a9643ea8Slogwang  * Copyright (C) 2017 THL A29 Limited, a Tencent company.
4*a9643ea8Slogwang  * All rights reserved.
5*a9643ea8Slogwang  *
6*a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
7*a9643ea8Slogwang  * modification, are permitted provided that the following conditions are met:
8*a9643ea8Slogwang  *
9*a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright notice, this
10*a9643ea8Slogwang  *   list of conditions and the following disclaimer.
11*a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*a9643ea8Slogwang  *   this list of conditions and the following disclaimer in the documentation
13*a9643ea8Slogwang  *   and/or other materials provided with the distribution.
14*a9643ea8Slogwang  *
15*a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16*a9643ea8Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17*a9643ea8Slogwang  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18*a9643ea8Slogwang  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19*a9643ea8Slogwang  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20*a9643ea8Slogwang  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21*a9643ea8Slogwang  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22*a9643ea8Slogwang  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*a9643ea8Slogwang  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24*a9643ea8Slogwang  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*a9643ea8Slogwang  *
26*a9643ea8Slogwang  * Derived in part from libplebnet's pn_syscall_wrapper.c.
27*a9643ea8Slogwang  */
28*a9643ea8Slogwang 
29*a9643ea8Slogwang #include <sys/param.h>
30*a9643ea8Slogwang #include <sys/limits.h>
31*a9643ea8Slogwang #include <sys/uio.h>
32*a9643ea8Slogwang #include <sys/proc.h>
33*a9643ea8Slogwang #include <sys/syscallsubr.h>
34*a9643ea8Slogwang #include <sys/module.h>
35*a9643ea8Slogwang #include <sys/param.h>
36*a9643ea8Slogwang #include <sys/malloc.h>
37*a9643ea8Slogwang #include <sys/socketvar.h>
38*a9643ea8Slogwang #include <sys/event.h>
39*a9643ea8Slogwang #include <sys/kernel.h>
40*a9643ea8Slogwang #include <sys/refcount.h>
41*a9643ea8Slogwang #include <sys/sysctl.h>
42*a9643ea8Slogwang #include <sys/pcpu.h>
43*a9643ea8Slogwang #include <sys/select.h>
44*a9643ea8Slogwang #include <sys/poll.h>
45*a9643ea8Slogwang #include <sys/event.h>
46*a9643ea8Slogwang #include <sys/file.h>
47*a9643ea8Slogwang #include <netinet/in.h>
48*a9643ea8Slogwang #include <netinet/tcp.h>
49*a9643ea8Slogwang #include <sys/ttycom.h>
50*a9643ea8Slogwang #include <sys/filio.h>
51*a9643ea8Slogwang #include <sys/sysproto.h>
52*a9643ea8Slogwang #include <sys/fcntl.h>
53*a9643ea8Slogwang 
54*a9643ea8Slogwang #include <machine/stdarg.h>
55*a9643ea8Slogwang 
56*a9643ea8Slogwang #include "ff_api.h"
57*a9643ea8Slogwang #include "ff_host_interface.h"
58*a9643ea8Slogwang 
59*a9643ea8Slogwang /* setsockopt/getsockopt define start */
60*a9643ea8Slogwang 
61*a9643ea8Slogwang #define LINUX_SOL_SOCKET      1
62*a9643ea8Slogwang 
63*a9643ea8Slogwang #define LINUX_SO_DEBUG        1
64*a9643ea8Slogwang #define LINUX_SO_REUSEADDR    2
65*a9643ea8Slogwang #define LINUX_SO_ERROR        4
66*a9643ea8Slogwang #define LINUX_SO_DONTROUTE    5
67*a9643ea8Slogwang #define LINUX_SO_BROADCAST    6
68*a9643ea8Slogwang #define LINUX_SO_SNDBUF       7
69*a9643ea8Slogwang #define LINUX_SO_RCVBUF       8
70*a9643ea8Slogwang #define LINUX_SO_KEEPALIVE    9
71*a9643ea8Slogwang #define LINUX_SO_OOBINLINE    10
72*a9643ea8Slogwang #define LINUX_SO_LINGER       13
73*a9643ea8Slogwang #define LINUX_SO_RCVLOWAT     18
74*a9643ea8Slogwang #define LINUX_SO_SNDLOWAT     19
75*a9643ea8Slogwang #define LINUX_SO_RCVTIMEO     20
76*a9643ea8Slogwang #define LINUX_SO_SNDTIMEO     21
77*a9643ea8Slogwang #define LINUX_SO_ACCEPTCONN   30
78*a9643ea8Slogwang #define LINUX_SO_PROTOCOL     38
79*a9643ea8Slogwang 
80*a9643ea8Slogwang 
81*a9643ea8Slogwang #define LINUX_IP_TOS        1
82*a9643ea8Slogwang #define LINUX_IP_TTL        2
83*a9643ea8Slogwang #define LINUX_IP_HDRINCL    3
84*a9643ea8Slogwang #define LINUX_IP_OPTIONS    4
85*a9643ea8Slogwang 
86*a9643ea8Slogwang #define LINUX_IP_MULTICAST_IF       32
87*a9643ea8Slogwang #define LINUX_IP_MULTICAST_TTL      33
88*a9643ea8Slogwang #define LINUX_IP_MULTICAST_LOOP     34
89*a9643ea8Slogwang #define LINUX_IP_ADD_MEMBERSHIP     35
90*a9643ea8Slogwang #define LINUX_IP_DROP_MEMBERSHIP    36
91*a9643ea8Slogwang 
92*a9643ea8Slogwang #define LINUX_TCP_NODELAY     1
93*a9643ea8Slogwang #define LINUX_TCP_MAXSEG      2
94*a9643ea8Slogwang #define LINUX_TCP_KEEPIDLE    4
95*a9643ea8Slogwang #define LINUX_TCP_KEEPINTVL   5
96*a9643ea8Slogwang #define LINUX_TCP_KEEPCNT     6
97*a9643ea8Slogwang #define LINUX_TCP_MD5SIG      14
98*a9643ea8Slogwang 
99*a9643ea8Slogwang /* setsockopt/getsockopt define end */
100*a9643ea8Slogwang 
101*a9643ea8Slogwang 
102*a9643ea8Slogwang /* ioctl define start */
103*a9643ea8Slogwang 
104*a9643ea8Slogwang #define LINUX_TIOCEXCL    0x540C
105*a9643ea8Slogwang #define LINUX_TIOCNXCL    0x540D
106*a9643ea8Slogwang #define LINUX_TIOCSCTTY   0x540E
107*a9643ea8Slogwang #define LINUX_TIOCGPGRP   0x540F
108*a9643ea8Slogwang #define LINUX_TIOCSPGRP   0x5410
109*a9643ea8Slogwang #define LINUX_TIOCOUTQ    0x5411
110*a9643ea8Slogwang #define LINUX_TIOCSTI     0x5412
111*a9643ea8Slogwang #define LINUX_TIOCGWINSZ  0x5413
112*a9643ea8Slogwang #define LINUX_TIOCSWINSZ  0x5414
113*a9643ea8Slogwang #define LINUX_TIOCMGET    0x5415
114*a9643ea8Slogwang #define LINUX_TIOCMBIS    0x5416
115*a9643ea8Slogwang #define LINUX_TIOCMBIC    0x5417
116*a9643ea8Slogwang #define LINUX_TIOCMSET    0x5418
117*a9643ea8Slogwang 
118*a9643ea8Slogwang #define LINUX_FIONREAD    0x541B
119*a9643ea8Slogwang #define LINUX_TIOCCONS    0x541D
120*a9643ea8Slogwang #define LINUX_TIOCPKT     0x5420
121*a9643ea8Slogwang #define LINUX_FIONBIO     0x5421
122*a9643ea8Slogwang #define LINUX_TIOCNOTTY   0x5422
123*a9643ea8Slogwang #define LINUX_TIOCSETD    0x5423
124*a9643ea8Slogwang #define LINUX_TIOCGETD    0x5424
125*a9643ea8Slogwang #define LINUX_TIOCSBRK    0x5427
126*a9643ea8Slogwang #define LINUX_TIOCCBRK    0x5428
127*a9643ea8Slogwang #define LINUX_TIOCGSID    0x5429
128*a9643ea8Slogwang 
129*a9643ea8Slogwang #define LINUX_FIONCLEX    0x5450
130*a9643ea8Slogwang #define LINUX_FIOCLEX     0x5451
131*a9643ea8Slogwang #define LINUX_FIOASYNC    0x5452
132*a9643ea8Slogwang 
133*a9643ea8Slogwang #define LINUX_TIOCPKT_DATA          0
134*a9643ea8Slogwang #define LINUX_TIOCPKT_FLUSHREAD     1
135*a9643ea8Slogwang #define LINUX_TIOCPKT_FLUSHWRITE    2
136*a9643ea8Slogwang #define LINUX_TIOCPKT_STOP          4
137*a9643ea8Slogwang #define LINUX_TIOCPKT_START         8
138*a9643ea8Slogwang #define LINUX_TIOCPKT_NOSTOP        16
139*a9643ea8Slogwang #define LINUX_TIOCPKT_DOSTOP        32
140*a9643ea8Slogwang #define LINUX_TIOCPKT_IOCTL         64
141*a9643ea8Slogwang 
142*a9643ea8Slogwang /* ioctl define end */
143*a9643ea8Slogwang 
144*a9643ea8Slogwang 
145*a9643ea8Slogwang extern int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
146*a9643ea8Slogwang 
147*a9643ea8Slogwang static long
148*a9643ea8Slogwang linux2freebsd_ioctl(unsigned long request)
149*a9643ea8Slogwang {
150*a9643ea8Slogwang     switch(request) {
151*a9643ea8Slogwang         case LINUX_TIOCEXCL:
152*a9643ea8Slogwang             return TIOCEXCL;
153*a9643ea8Slogwang         case LINUX_TIOCNXCL:
154*a9643ea8Slogwang             return TIOCNXCL;
155*a9643ea8Slogwang         case LINUX_TIOCSCTTY:
156*a9643ea8Slogwang             return TIOCSCTTY;
157*a9643ea8Slogwang         case LINUX_TIOCGPGRP:
158*a9643ea8Slogwang             return TIOCGPGRP;
159*a9643ea8Slogwang         case LINUX_TIOCSPGRP:
160*a9643ea8Slogwang             return TIOCSPGRP;
161*a9643ea8Slogwang         case LINUX_TIOCOUTQ:
162*a9643ea8Slogwang             return TIOCOUTQ;
163*a9643ea8Slogwang         case LINUX_TIOCSTI:
164*a9643ea8Slogwang             return TIOCSTI;
165*a9643ea8Slogwang         case LINUX_TIOCGWINSZ:
166*a9643ea8Slogwang             return TIOCGWINSZ;
167*a9643ea8Slogwang         case LINUX_TIOCSWINSZ:
168*a9643ea8Slogwang             return TIOCSWINSZ;
169*a9643ea8Slogwang         case LINUX_TIOCMGET:
170*a9643ea8Slogwang             return TIOCMGET;
171*a9643ea8Slogwang         case LINUX_TIOCMBIS:
172*a9643ea8Slogwang             return TIOCMBIS;
173*a9643ea8Slogwang         case LINUX_TIOCMBIC:
174*a9643ea8Slogwang             return TIOCMBIC;
175*a9643ea8Slogwang         case LINUX_TIOCMSET:
176*a9643ea8Slogwang             return TIOCMSET;
177*a9643ea8Slogwang         case LINUX_FIONREAD:
178*a9643ea8Slogwang             return FIONREAD;
179*a9643ea8Slogwang         case LINUX_TIOCCONS:
180*a9643ea8Slogwang             return TIOCCONS;
181*a9643ea8Slogwang         case LINUX_TIOCPKT:
182*a9643ea8Slogwang             return TIOCPKT;
183*a9643ea8Slogwang         case LINUX_FIONBIO:
184*a9643ea8Slogwang             return FIONBIO;
185*a9643ea8Slogwang         case LINUX_TIOCNOTTY:
186*a9643ea8Slogwang             return TIOCNOTTY;
187*a9643ea8Slogwang         case LINUX_TIOCSETD:
188*a9643ea8Slogwang             return TIOCSETD;
189*a9643ea8Slogwang         case LINUX_TIOCGETD:
190*a9643ea8Slogwang             return TIOCGETD;
191*a9643ea8Slogwang         case LINUX_TIOCSBRK:
192*a9643ea8Slogwang             return TIOCSBRK;
193*a9643ea8Slogwang         case LINUX_TIOCCBRK:
194*a9643ea8Slogwang             return TIOCCBRK;
195*a9643ea8Slogwang         case LINUX_TIOCGSID:
196*a9643ea8Slogwang             return TIOCGSID;
197*a9643ea8Slogwang         case LINUX_FIONCLEX:
198*a9643ea8Slogwang             return FIONCLEX;
199*a9643ea8Slogwang         case LINUX_FIOCLEX:
200*a9643ea8Slogwang             return FIOCLEX;
201*a9643ea8Slogwang         case LINUX_FIOASYNC:
202*a9643ea8Slogwang             return FIOASYNC;
203*a9643ea8Slogwang         case LINUX_TIOCPKT_DATA:
204*a9643ea8Slogwang             return TIOCPKT_DATA;
205*a9643ea8Slogwang         case LINUX_TIOCPKT_FLUSHREAD:
206*a9643ea8Slogwang             return TIOCPKT_FLUSHREAD;
207*a9643ea8Slogwang         case LINUX_TIOCPKT_FLUSHWRITE:
208*a9643ea8Slogwang             return TIOCPKT_FLUSHWRITE;
209*a9643ea8Slogwang         case LINUX_TIOCPKT_STOP:
210*a9643ea8Slogwang             return TIOCPKT_STOP;
211*a9643ea8Slogwang         case LINUX_TIOCPKT_START:
212*a9643ea8Slogwang             return TIOCPKT_START;
213*a9643ea8Slogwang         case LINUX_TIOCPKT_NOSTOP:
214*a9643ea8Slogwang             return TIOCPKT_NOSTOP;
215*a9643ea8Slogwang         case LINUX_TIOCPKT_DOSTOP:
216*a9643ea8Slogwang             return TIOCPKT_DOSTOP;
217*a9643ea8Slogwang         case LINUX_TIOCPKT_IOCTL:
218*a9643ea8Slogwang             return TIOCPKT_IOCTL;
219*a9643ea8Slogwang         default:
220*a9643ea8Slogwang             return (-1);
221*a9643ea8Slogwang     }
222*a9643ea8Slogwang }
223*a9643ea8Slogwang 
224*a9643ea8Slogwang static int
225*a9643ea8Slogwang so_opt_convert(int optname)
226*a9643ea8Slogwang {
227*a9643ea8Slogwang     switch(optname) {
228*a9643ea8Slogwang         case LINUX_SO_DEBUG:
229*a9643ea8Slogwang             return SO_DEBUG;
230*a9643ea8Slogwang         case LINUX_SO_REUSEADDR:
231*a9643ea8Slogwang             return SO_REUSEADDR;
232*a9643ea8Slogwang         case LINUX_SO_ERROR:
233*a9643ea8Slogwang             return SO_ERROR;
234*a9643ea8Slogwang         case LINUX_SO_DONTROUTE:
235*a9643ea8Slogwang             return SO_DONTROUTE;
236*a9643ea8Slogwang         case LINUX_SO_BROADCAST:
237*a9643ea8Slogwang             return SO_BROADCAST;
238*a9643ea8Slogwang         case LINUX_SO_SNDBUF:
239*a9643ea8Slogwang             return SO_SNDBUF;
240*a9643ea8Slogwang         case LINUX_SO_RCVBUF:
241*a9643ea8Slogwang             return SO_RCVBUF;
242*a9643ea8Slogwang         case LINUX_SO_KEEPALIVE:
243*a9643ea8Slogwang             return SO_KEEPALIVE;
244*a9643ea8Slogwang         case LINUX_SO_OOBINLINE:
245*a9643ea8Slogwang             return SO_OOBINLINE;
246*a9643ea8Slogwang         case LINUX_SO_LINGER:
247*a9643ea8Slogwang             return SO_LINGER;
248*a9643ea8Slogwang         case LINUX_SO_RCVLOWAT:
249*a9643ea8Slogwang             return SO_RCVLOWAT;
250*a9643ea8Slogwang         case LINUX_SO_SNDLOWAT:
251*a9643ea8Slogwang             return SO_SNDLOWAT;
252*a9643ea8Slogwang         case LINUX_SO_RCVTIMEO:
253*a9643ea8Slogwang             return SO_RCVTIMEO;
254*a9643ea8Slogwang         case LINUX_SO_SNDTIMEO:
255*a9643ea8Slogwang             return SO_SNDTIMEO;
256*a9643ea8Slogwang         case LINUX_SO_ACCEPTCONN:
257*a9643ea8Slogwang             return SO_ACCEPTCONN;
258*a9643ea8Slogwang         case LINUX_SO_PROTOCOL:
259*a9643ea8Slogwang             return SO_PROTOCOL;
260*a9643ea8Slogwang         default:
261*a9643ea8Slogwang             return (-1);
262*a9643ea8Slogwang     }
263*a9643ea8Slogwang }
264*a9643ea8Slogwang 
265*a9643ea8Slogwang static int
266*a9643ea8Slogwang ip_opt_convert(int optname)
267*a9643ea8Slogwang {
268*a9643ea8Slogwang     switch(optname) {
269*a9643ea8Slogwang         case LINUX_IP_TOS:
270*a9643ea8Slogwang             return IP_TOS;
271*a9643ea8Slogwang         case LINUX_IP_TTL:
272*a9643ea8Slogwang             return IP_TTL;
273*a9643ea8Slogwang         case LINUX_IP_HDRINCL:
274*a9643ea8Slogwang             return IP_HDRINCL;
275*a9643ea8Slogwang         case LINUX_IP_OPTIONS:
276*a9643ea8Slogwang             return IP_OPTIONS;
277*a9643ea8Slogwang         case LINUX_IP_MULTICAST_IF:
278*a9643ea8Slogwang             return IP_MULTICAST_IF;
279*a9643ea8Slogwang         case LINUX_IP_MULTICAST_TTL:
280*a9643ea8Slogwang             return IP_MULTICAST_TTL;
281*a9643ea8Slogwang         case LINUX_IP_MULTICAST_LOOP:
282*a9643ea8Slogwang             return IP_MULTICAST_LOOP;
283*a9643ea8Slogwang         case LINUX_IP_ADD_MEMBERSHIP:
284*a9643ea8Slogwang             return IP_ADD_MEMBERSHIP;
285*a9643ea8Slogwang         case LINUX_IP_DROP_MEMBERSHIP:
286*a9643ea8Slogwang             return IP_DROP_MEMBERSHIP;
287*a9643ea8Slogwang         default:
288*a9643ea8Slogwang             return (-1);
289*a9643ea8Slogwang     }
290*a9643ea8Slogwang }
291*a9643ea8Slogwang 
292*a9643ea8Slogwang static int
293*a9643ea8Slogwang tcp_opt_convert(int optname)
294*a9643ea8Slogwang {
295*a9643ea8Slogwang     switch(optname) {
296*a9643ea8Slogwang         case LINUX_TCP_NODELAY:
297*a9643ea8Slogwang             return TCP_NODELAY;
298*a9643ea8Slogwang         case LINUX_TCP_MAXSEG:
299*a9643ea8Slogwang             return TCP_MAXSEG;
300*a9643ea8Slogwang         case LINUX_TCP_KEEPIDLE:
301*a9643ea8Slogwang             return TCP_KEEPIDLE;
302*a9643ea8Slogwang         case LINUX_TCP_KEEPINTVL:
303*a9643ea8Slogwang             return TCP_KEEPINTVL;
304*a9643ea8Slogwang         case LINUX_TCP_KEEPCNT:
305*a9643ea8Slogwang             return TCP_KEEPCNT;
306*a9643ea8Slogwang         case LINUX_TCP_MD5SIG:
307*a9643ea8Slogwang             return TCP_MD5SIG;
308*a9643ea8Slogwang         default:
309*a9643ea8Slogwang             return (-1);
310*a9643ea8Slogwang     }
311*a9643ea8Slogwang }
312*a9643ea8Slogwang 
313*a9643ea8Slogwang static int
314*a9643ea8Slogwang linux2freebsd_opt(int level, int optname)
315*a9643ea8Slogwang {
316*a9643ea8Slogwang     switch(level) {
317*a9643ea8Slogwang         case SOL_SOCKET:
318*a9643ea8Slogwang             return so_opt_convert(optname);
319*a9643ea8Slogwang         case IPPROTO_IP:
320*a9643ea8Slogwang             return ip_opt_convert(optname);
321*a9643ea8Slogwang         case IPPROTO_TCP:
322*a9643ea8Slogwang             return tcp_opt_convert(optname);
323*a9643ea8Slogwang         default:
324*a9643ea8Slogwang             return (-1);
325*a9643ea8Slogwang     }
326*a9643ea8Slogwang }
327*a9643ea8Slogwang 
328*a9643ea8Slogwang static void
329*a9643ea8Slogwang linux2freebsd_sockaddr(const struct linux_sockaddr *linux,
330*a9643ea8Slogwang     socklen_t addrlen, struct sockaddr *freebsd)
331*a9643ea8Slogwang {
332*a9643ea8Slogwang     if (linux == NULL) {
333*a9643ea8Slogwang         return;
334*a9643ea8Slogwang     }
335*a9643ea8Slogwang 
336*a9643ea8Slogwang     bzero(freebsd, sizeof(struct sockaddr));
337*a9643ea8Slogwang     freebsd->sa_len = addrlen;
338*a9643ea8Slogwang     freebsd->sa_family = linux->sa_family;
339*a9643ea8Slogwang     bcopy(linux->sa_data, freebsd->sa_data, sizeof(linux->sa_data));
340*a9643ea8Slogwang }
341*a9643ea8Slogwang 
342*a9643ea8Slogwang static void
343*a9643ea8Slogwang freebsd2linux_sockaddr(struct linux_sockaddr *linux,
344*a9643ea8Slogwang     struct sockaddr *freebsd)
345*a9643ea8Slogwang {
346*a9643ea8Slogwang     if (linux == NULL) {
347*a9643ea8Slogwang         return;
348*a9643ea8Slogwang     }
349*a9643ea8Slogwang 
350*a9643ea8Slogwang     linux->sa_family = freebsd->sa_family;
351*a9643ea8Slogwang     bcopy(freebsd->sa_data, linux->sa_data, sizeof(freebsd->sa_data));
352*a9643ea8Slogwang }
353*a9643ea8Slogwang 
354*a9643ea8Slogwang int
355*a9643ea8Slogwang ff_socket(int domain, int type, int protocol)
356*a9643ea8Slogwang {
357*a9643ea8Slogwang     int rc;
358*a9643ea8Slogwang     struct socket_args sa;
359*a9643ea8Slogwang     sa.domain = domain;
360*a9643ea8Slogwang     sa.type = type;
361*a9643ea8Slogwang     sa.protocol = protocol;
362*a9643ea8Slogwang     if ((rc = sys_socket(curthread, &sa)))
363*a9643ea8Slogwang         goto kern_fail;
364*a9643ea8Slogwang 
365*a9643ea8Slogwang     return curthread->td_retval[0];
366*a9643ea8Slogwang kern_fail:
367*a9643ea8Slogwang     ff_os_errno(rc);
368*a9643ea8Slogwang     return (-1);
369*a9643ea8Slogwang }
370*a9643ea8Slogwang 
371*a9643ea8Slogwang int
372*a9643ea8Slogwang ff_getsockopt(int s, int level, int optname, void *optval,
373*a9643ea8Slogwang     socklen_t *optlen)
374*a9643ea8Slogwang {
375*a9643ea8Slogwang     int rc;
376*a9643ea8Slogwang     if (level == LINUX_SOL_SOCKET)
377*a9643ea8Slogwang         level = SOL_SOCKET;
378*a9643ea8Slogwang 
379*a9643ea8Slogwang     optname = linux2freebsd_opt(level, optname);
380*a9643ea8Slogwang     if (optname < 0) {
381*a9643ea8Slogwang         rc = EINVAL;
382*a9643ea8Slogwang         goto kern_fail;
383*a9643ea8Slogwang     }
384*a9643ea8Slogwang 
385*a9643ea8Slogwang     if ((rc = kern_getsockopt(curthread, s, level, optname,
386*a9643ea8Slogwang             optval, UIO_SYSSPACE, optlen)))
387*a9643ea8Slogwang         goto kern_fail;
388*a9643ea8Slogwang 
389*a9643ea8Slogwang     return (rc);
390*a9643ea8Slogwang 
391*a9643ea8Slogwang kern_fail:
392*a9643ea8Slogwang     ff_os_errno(rc);
393*a9643ea8Slogwang     return (-1);
394*a9643ea8Slogwang }
395*a9643ea8Slogwang 
396*a9643ea8Slogwang int
397*a9643ea8Slogwang ff_setsockopt(int s, int level, int optname, const void *optval,
398*a9643ea8Slogwang     socklen_t optlen)
399*a9643ea8Slogwang {
400*a9643ea8Slogwang     int rc;
401*a9643ea8Slogwang 
402*a9643ea8Slogwang     if (level == LINUX_SOL_SOCKET)
403*a9643ea8Slogwang         level = SOL_SOCKET;
404*a9643ea8Slogwang 
405*a9643ea8Slogwang     optname = linux2freebsd_opt(level, optname);
406*a9643ea8Slogwang     if (optname < 0) {
407*a9643ea8Slogwang         rc = EINVAL;
408*a9643ea8Slogwang         goto kern_fail;
409*a9643ea8Slogwang     }
410*a9643ea8Slogwang 
411*a9643ea8Slogwang     if ((rc = kern_setsockopt(curthread, s, level, optname,
412*a9643ea8Slogwang             __DECONST(void *, optval), UIO_SYSSPACE, optlen)))
413*a9643ea8Slogwang         goto kern_fail;
414*a9643ea8Slogwang 
415*a9643ea8Slogwang     return (rc);
416*a9643ea8Slogwang 
417*a9643ea8Slogwang kern_fail:
418*a9643ea8Slogwang     ff_os_errno(rc);
419*a9643ea8Slogwang     return (-1);
420*a9643ea8Slogwang }
421*a9643ea8Slogwang 
422*a9643ea8Slogwang int
423*a9643ea8Slogwang ff_ioctl(int fd, unsigned long request, ...)
424*a9643ea8Slogwang {
425*a9643ea8Slogwang     int rc;
426*a9643ea8Slogwang     va_list ap;
427*a9643ea8Slogwang     caddr_t argp;
428*a9643ea8Slogwang 
429*a9643ea8Slogwang     long req = linux2freebsd_ioctl(request);
430*a9643ea8Slogwang     if (req < 0) {
431*a9643ea8Slogwang         rc = EINVAL;
432*a9643ea8Slogwang         goto kern_fail;
433*a9643ea8Slogwang     }
434*a9643ea8Slogwang 
435*a9643ea8Slogwang     va_start(ap, request);
436*a9643ea8Slogwang 
437*a9643ea8Slogwang     argp = va_arg(ap, caddr_t);
438*a9643ea8Slogwang     va_end(ap);
439*a9643ea8Slogwang     if ((rc = kern_ioctl(curthread, fd, req, argp)))
440*a9643ea8Slogwang         goto kern_fail;
441*a9643ea8Slogwang 
442*a9643ea8Slogwang     return (rc);
443*a9643ea8Slogwang 
444*a9643ea8Slogwang kern_fail:
445*a9643ea8Slogwang     ff_os_errno(rc);
446*a9643ea8Slogwang     return (-1);
447*a9643ea8Slogwang }
448*a9643ea8Slogwang 
449*a9643ea8Slogwang int
450*a9643ea8Slogwang ff_close(int fd)
451*a9643ea8Slogwang {
452*a9643ea8Slogwang     int rc;
453*a9643ea8Slogwang 
454*a9643ea8Slogwang     if ((rc = kern_close(curthread, fd)))
455*a9643ea8Slogwang         goto kern_fail;
456*a9643ea8Slogwang 
457*a9643ea8Slogwang     return (rc);
458*a9643ea8Slogwang kern_fail:
459*a9643ea8Slogwang     ff_os_errno(rc);
460*a9643ea8Slogwang     return (-1);
461*a9643ea8Slogwang }
462*a9643ea8Slogwang 
463*a9643ea8Slogwang ssize_t
464*a9643ea8Slogwang ff_read(int fd, void *buf, size_t nbytes)
465*a9643ea8Slogwang {
466*a9643ea8Slogwang     struct uio auio;
467*a9643ea8Slogwang     struct iovec aiov;
468*a9643ea8Slogwang     int rc;
469*a9643ea8Slogwang 
470*a9643ea8Slogwang     if (nbytes > INT_MAX) {
471*a9643ea8Slogwang         rc = EINVAL;
472*a9643ea8Slogwang         goto kern_fail;
473*a9643ea8Slogwang     }
474*a9643ea8Slogwang 
475*a9643ea8Slogwang     aiov.iov_base = buf;
476*a9643ea8Slogwang     aiov.iov_len = nbytes;
477*a9643ea8Slogwang     auio.uio_iov = &aiov;
478*a9643ea8Slogwang     auio.uio_iovcnt = 1;
479*a9643ea8Slogwang     auio.uio_resid = nbytes;
480*a9643ea8Slogwang     auio.uio_segflg = UIO_SYSSPACE;
481*a9643ea8Slogwang     if ((rc = kern_readv(curthread, fd, &auio)))
482*a9643ea8Slogwang         goto kern_fail;
483*a9643ea8Slogwang     rc = curthread->td_retval[0];
484*a9643ea8Slogwang 
485*a9643ea8Slogwang     return (rc);
486*a9643ea8Slogwang kern_fail:
487*a9643ea8Slogwang     ff_os_errno(rc);
488*a9643ea8Slogwang     return (-1);
489*a9643ea8Slogwang }
490*a9643ea8Slogwang 
491*a9643ea8Slogwang ssize_t
492*a9643ea8Slogwang ff_readv(int fd, const struct iovec *iov, int iovcnt)
493*a9643ea8Slogwang {
494*a9643ea8Slogwang     struct uio auio;
495*a9643ea8Slogwang     int rc, len, i;
496*a9643ea8Slogwang 
497*a9643ea8Slogwang     len = 0;
498*a9643ea8Slogwang     for (i = 0; i < iovcnt; i++)
499*a9643ea8Slogwang         len += iov[i].iov_len;
500*a9643ea8Slogwang     auio.uio_iov = __DECONST(struct iovec *, iov);
501*a9643ea8Slogwang     auio.uio_iovcnt = iovcnt;
502*a9643ea8Slogwang     auio.uio_resid = len;
503*a9643ea8Slogwang     auio.uio_segflg = UIO_SYSSPACE;
504*a9643ea8Slogwang 
505*a9643ea8Slogwang     if ((rc = kern_readv(curthread, fd, &auio)))
506*a9643ea8Slogwang         goto kern_fail;
507*a9643ea8Slogwang     rc = curthread->td_retval[0];
508*a9643ea8Slogwang 
509*a9643ea8Slogwang     return (rc);
510*a9643ea8Slogwang kern_fail:
511*a9643ea8Slogwang     ff_os_errno(rc);
512*a9643ea8Slogwang     return (-1);
513*a9643ea8Slogwang }
514*a9643ea8Slogwang 
515*a9643ea8Slogwang ssize_t
516*a9643ea8Slogwang ff_write(int fd, const void *buf, size_t nbytes)
517*a9643ea8Slogwang {
518*a9643ea8Slogwang     struct uio auio;
519*a9643ea8Slogwang     struct iovec aiov;
520*a9643ea8Slogwang     int rc;
521*a9643ea8Slogwang 
522*a9643ea8Slogwang     if (nbytes > INT_MAX) {
523*a9643ea8Slogwang         rc = EINVAL;
524*a9643ea8Slogwang         goto kern_fail;
525*a9643ea8Slogwang     }
526*a9643ea8Slogwang 
527*a9643ea8Slogwang     aiov.iov_base = (void *)(uintptr_t)buf;
528*a9643ea8Slogwang     aiov.iov_len = nbytes;
529*a9643ea8Slogwang     auio.uio_iov = &aiov;
530*a9643ea8Slogwang     auio.uio_iovcnt = 1;
531*a9643ea8Slogwang     auio.uio_resid = nbytes;
532*a9643ea8Slogwang     auio.uio_segflg = UIO_SYSSPACE;
533*a9643ea8Slogwang     if ((rc = kern_writev(curthread, fd, &auio)))
534*a9643ea8Slogwang         goto kern_fail;
535*a9643ea8Slogwang     rc = curthread->td_retval[0];
536*a9643ea8Slogwang 
537*a9643ea8Slogwang     return (rc);
538*a9643ea8Slogwang kern_fail:
539*a9643ea8Slogwang     ff_os_errno(rc);
540*a9643ea8Slogwang     return (-1);
541*a9643ea8Slogwang }
542*a9643ea8Slogwang 
543*a9643ea8Slogwang ssize_t
544*a9643ea8Slogwang ff_writev(int fd, const struct iovec *iov, int iovcnt)
545*a9643ea8Slogwang {
546*a9643ea8Slogwang     struct uio auio;
547*a9643ea8Slogwang     int i, rc, len;
548*a9643ea8Slogwang 
549*a9643ea8Slogwang     len = 0;
550*a9643ea8Slogwang     for (i = 0; i < iovcnt; i++)
551*a9643ea8Slogwang         len += iov[i].iov_len;
552*a9643ea8Slogwang     auio.uio_iov = __DECONST(struct iovec *, iov);
553*a9643ea8Slogwang     auio.uio_iovcnt = iovcnt;
554*a9643ea8Slogwang     auio.uio_resid = len;
555*a9643ea8Slogwang     auio.uio_segflg = UIO_SYSSPACE;
556*a9643ea8Slogwang     if ((rc = kern_writev(curthread, fd, &auio)))
557*a9643ea8Slogwang         goto kern_fail;
558*a9643ea8Slogwang     rc = curthread->td_retval[0];
559*a9643ea8Slogwang 
560*a9643ea8Slogwang     return (rc);
561*a9643ea8Slogwang kern_fail:
562*a9643ea8Slogwang     ff_os_errno(rc);
563*a9643ea8Slogwang     return (-1);
564*a9643ea8Slogwang }
565*a9643ea8Slogwang 
566*a9643ea8Slogwang ssize_t
567*a9643ea8Slogwang ff_send(int s, const void *buf, size_t len, int flags)
568*a9643ea8Slogwang {
569*a9643ea8Slogwang     return (ff_sendto(s, buf, len, flags, NULL, 0));
570*a9643ea8Slogwang }
571*a9643ea8Slogwang 
572*a9643ea8Slogwang ssize_t
573*a9643ea8Slogwang ff_sendto(int s, const void *buf, size_t len, int flags,
574*a9643ea8Slogwang          const struct linux_sockaddr *to, socklen_t tolen)
575*a9643ea8Slogwang {
576*a9643ea8Slogwang     struct msghdr msg;
577*a9643ea8Slogwang     struct iovec aiov;
578*a9643ea8Slogwang     int rc;
579*a9643ea8Slogwang 
580*a9643ea8Slogwang     struct sockaddr bsdaddr;
581*a9643ea8Slogwang     struct sockaddr *pf = &bsdaddr;
582*a9643ea8Slogwang 
583*a9643ea8Slogwang     if (to) {
584*a9643ea8Slogwang         linux2freebsd_sockaddr(to, tolen, pf);
585*a9643ea8Slogwang     } else {
586*a9643ea8Slogwang         pf = NULL;
587*a9643ea8Slogwang     }
588*a9643ea8Slogwang 
589*a9643ea8Slogwang     msg.msg_name = pf;
590*a9643ea8Slogwang     msg.msg_namelen = tolen;
591*a9643ea8Slogwang     msg.msg_iov = &aiov;
592*a9643ea8Slogwang     msg.msg_iovlen = 1;
593*a9643ea8Slogwang     msg.msg_control = 0;
594*a9643ea8Slogwang     aiov.iov_base = __DECONST(void *, buf);
595*a9643ea8Slogwang     aiov.iov_len = len;
596*a9643ea8Slogwang     if ((rc = sendit(curthread, s, &msg, flags)))
597*a9643ea8Slogwang         goto kern_fail;
598*a9643ea8Slogwang 
599*a9643ea8Slogwang     rc = curthread->td_retval[0];
600*a9643ea8Slogwang 
601*a9643ea8Slogwang     return (rc);
602*a9643ea8Slogwang kern_fail:
603*a9643ea8Slogwang     ff_os_errno(rc);
604*a9643ea8Slogwang     return (-1);
605*a9643ea8Slogwang }
606*a9643ea8Slogwang 
607*a9643ea8Slogwang ssize_t
608*a9643ea8Slogwang ff_sendmsg(int s, const struct msghdr *msg, int flags)
609*a9643ea8Slogwang {
610*a9643ea8Slogwang     int rc;
611*a9643ea8Slogwang 
612*a9643ea8Slogwang     if ((rc = sendit(curthread, s, __DECONST(struct msghdr *, msg), flags)))
613*a9643ea8Slogwang         goto kern_fail;
614*a9643ea8Slogwang 
615*a9643ea8Slogwang     return (rc);
616*a9643ea8Slogwang kern_fail:
617*a9643ea8Slogwang     ff_os_errno(rc);
618*a9643ea8Slogwang     return (-1);
619*a9643ea8Slogwang }
620*a9643ea8Slogwang 
621*a9643ea8Slogwang 
622*a9643ea8Slogwang ssize_t
623*a9643ea8Slogwang ff_recv(int s, void *buf, size_t len, int flags)
624*a9643ea8Slogwang {
625*a9643ea8Slogwang     return (ff_recvfrom(s, buf, len, flags, NULL, 0));
626*a9643ea8Slogwang }
627*a9643ea8Slogwang 
628*a9643ea8Slogwang ssize_t
629*a9643ea8Slogwang ff_recvfrom(int s, void *buf, size_t len, int flags,
630*a9643ea8Slogwang     struct linux_sockaddr *from, socklen_t *fromlen)
631*a9643ea8Slogwang {
632*a9643ea8Slogwang     struct msghdr msg;
633*a9643ea8Slogwang     struct iovec aiov;
634*a9643ea8Slogwang     int rc;
635*a9643ea8Slogwang     struct sockaddr bsdaddr;
636*a9643ea8Slogwang 
637*a9643ea8Slogwang     if (fromlen != NULL)
638*a9643ea8Slogwang         msg.msg_namelen = *fromlen;
639*a9643ea8Slogwang     else
640*a9643ea8Slogwang         msg.msg_namelen = 0;
641*a9643ea8Slogwang 
642*a9643ea8Slogwang     msg.msg_name = &bsdaddr;
643*a9643ea8Slogwang     msg.msg_iov = &aiov;
644*a9643ea8Slogwang     msg.msg_iovlen = 1;
645*a9643ea8Slogwang     aiov.iov_base = buf;
646*a9643ea8Slogwang     aiov.iov_len = len;
647*a9643ea8Slogwang     msg.msg_control = 0;
648*a9643ea8Slogwang     msg.msg_flags = flags;
649*a9643ea8Slogwang     if ((rc = kern_recvit(curthread, s, &msg, UIO_SYSSPACE, NULL)))
650*a9643ea8Slogwang         goto kern_fail;
651*a9643ea8Slogwang     rc = curthread->td_retval[0];
652*a9643ea8Slogwang     if (fromlen != NULL)
653*a9643ea8Slogwang         *fromlen = msg.msg_namelen;
654*a9643ea8Slogwang 
655*a9643ea8Slogwang     if (from)
656*a9643ea8Slogwang         freebsd2linux_sockaddr(from, &bsdaddr);
657*a9643ea8Slogwang 
658*a9643ea8Slogwang     return (rc);
659*a9643ea8Slogwang kern_fail:
660*a9643ea8Slogwang     ff_os_errno(rc);
661*a9643ea8Slogwang     return (-1);
662*a9643ea8Slogwang }
663*a9643ea8Slogwang 
664*a9643ea8Slogwang ssize_t
665*a9643ea8Slogwang ff_recvmsg(int s, struct msghdr *msg, int flags)
666*a9643ea8Slogwang {
667*a9643ea8Slogwang     int rc, oldflags;
668*a9643ea8Slogwang 
669*a9643ea8Slogwang     oldflags = msg->msg_flags;
670*a9643ea8Slogwang     msg->msg_flags = flags;
671*a9643ea8Slogwang 
672*a9643ea8Slogwang     if ((rc = kern_recvit(curthread, s, msg, UIO_SYSSPACE, NULL))) {
673*a9643ea8Slogwang         msg->msg_flags = oldflags;
674*a9643ea8Slogwang         goto kern_fail;
675*a9643ea8Slogwang     }
676*a9643ea8Slogwang     rc = curthread->td_retval[0];
677*a9643ea8Slogwang 
678*a9643ea8Slogwang     return (rc);
679*a9643ea8Slogwang kern_fail:
680*a9643ea8Slogwang     ff_os_errno(rc);
681*a9643ea8Slogwang     return (-1);
682*a9643ea8Slogwang }
683*a9643ea8Slogwang 
684*a9643ea8Slogwang int
685*a9643ea8Slogwang ff_fcntl(int fd, int cmd, ...)
686*a9643ea8Slogwang {
687*a9643ea8Slogwang     int rc;
688*a9643ea8Slogwang     va_list ap;
689*a9643ea8Slogwang     uintptr_t argp;
690*a9643ea8Slogwang 
691*a9643ea8Slogwang     va_start(ap, cmd);
692*a9643ea8Slogwang 
693*a9643ea8Slogwang     argp = va_arg(ap, uintptr_t);
694*a9643ea8Slogwang     va_end(ap);
695*a9643ea8Slogwang 
696*a9643ea8Slogwang     if ((rc = kern_fcntl(curthread, fd, cmd, argp)))
697*a9643ea8Slogwang         goto kern_fail;
698*a9643ea8Slogwang     rc = curthread->td_retval[0];
699*a9643ea8Slogwang     return (rc);
700*a9643ea8Slogwang kern_fail:
701*a9643ea8Slogwang     ff_os_errno(rc);
702*a9643ea8Slogwang     return (-1);
703*a9643ea8Slogwang }
704*a9643ea8Slogwang 
705*a9643ea8Slogwang int
706*a9643ea8Slogwang ff_socketpair(int domain, int type, int protocol, int *sv)
707*a9643ea8Slogwang {
708*a9643ea8Slogwang     int rc;
709*a9643ea8Slogwang     if ((rc = kern_socketpair(curthread, domain, type, protocol, sv)))
710*a9643ea8Slogwang         goto kern_fail;
711*a9643ea8Slogwang 
712*a9643ea8Slogwang     return (rc);
713*a9643ea8Slogwang kern_fail:
714*a9643ea8Slogwang     ff_os_errno(rc);
715*a9643ea8Slogwang     return (-1);
716*a9643ea8Slogwang }
717*a9643ea8Slogwang 
718*a9643ea8Slogwang int
719*a9643ea8Slogwang ff_accept(int s, struct linux_sockaddr * addr,
720*a9643ea8Slogwang     socklen_t * addrlen)
721*a9643ea8Slogwang {
722*a9643ea8Slogwang     int rc;
723*a9643ea8Slogwang     struct file *fp;
724*a9643ea8Slogwang     struct sockaddr bsdaddr;
725*a9643ea8Slogwang     struct sockaddr *pf = &bsdaddr;
726*a9643ea8Slogwang     socklen_t socklen = sizeof(struct sockaddr);
727*a9643ea8Slogwang 
728*a9643ea8Slogwang     if ((rc = kern_accept(curthread, s, &pf, &socklen, &fp)))
729*a9643ea8Slogwang         goto kern_fail;
730*a9643ea8Slogwang 
731*a9643ea8Slogwang     rc = curthread->td_retval[0];
732*a9643ea8Slogwang     fdrop(fp, curthread);
733*a9643ea8Slogwang 
734*a9643ea8Slogwang     if (addr)
735*a9643ea8Slogwang         freebsd2linux_sockaddr(addr, pf);
736*a9643ea8Slogwang 
737*a9643ea8Slogwang     if (addrlen)
738*a9643ea8Slogwang         *addrlen = socklen;
739*a9643ea8Slogwang 
740*a9643ea8Slogwang     return (rc);
741*a9643ea8Slogwang kern_fail:
742*a9643ea8Slogwang     ff_os_errno(rc);
743*a9643ea8Slogwang     return (-1);
744*a9643ea8Slogwang }
745*a9643ea8Slogwang 
746*a9643ea8Slogwang int
747*a9643ea8Slogwang ff_listen(int s, int backlog)
748*a9643ea8Slogwang {
749*a9643ea8Slogwang     int rc;
750*a9643ea8Slogwang     struct listen_args la = {
751*a9643ea8Slogwang         .s = s,
752*a9643ea8Slogwang         .backlog = backlog,
753*a9643ea8Slogwang     };
754*a9643ea8Slogwang     if ((rc = sys_listen(curthread, &la)))
755*a9643ea8Slogwang         goto kern_fail;
756*a9643ea8Slogwang 
757*a9643ea8Slogwang     return (rc);
758*a9643ea8Slogwang kern_fail:
759*a9643ea8Slogwang     ff_os_errno(rc);
760*a9643ea8Slogwang     return (-1);
761*a9643ea8Slogwang }
762*a9643ea8Slogwang 
763*a9643ea8Slogwang int
764*a9643ea8Slogwang ff_bind(int s, const struct linux_sockaddr *addr, socklen_t addrlen)
765*a9643ea8Slogwang {
766*a9643ea8Slogwang     int rc;
767*a9643ea8Slogwang     struct sockaddr bsdaddr;
768*a9643ea8Slogwang     linux2freebsd_sockaddr(addr, addrlen, &bsdaddr);
769*a9643ea8Slogwang 
770*a9643ea8Slogwang     if ((rc = kern_bindat(curthread, AT_FDCWD, s, &bsdaddr)))
771*a9643ea8Slogwang         goto kern_fail;
772*a9643ea8Slogwang 
773*a9643ea8Slogwang     return (rc);
774*a9643ea8Slogwang kern_fail:
775*a9643ea8Slogwang     ff_os_errno(rc);
776*a9643ea8Slogwang     return (-1);
777*a9643ea8Slogwang }
778*a9643ea8Slogwang 
779*a9643ea8Slogwang int
780*a9643ea8Slogwang ff_connect(int s, const struct linux_sockaddr *name, socklen_t namelen)
781*a9643ea8Slogwang {
782*a9643ea8Slogwang     int rc;
783*a9643ea8Slogwang     struct sockaddr bsdaddr;
784*a9643ea8Slogwang     linux2freebsd_sockaddr(name, namelen, &bsdaddr);
785*a9643ea8Slogwang 
786*a9643ea8Slogwang     if ((rc = kern_connectat(curthread, AT_FDCWD, s, &bsdaddr)))
787*a9643ea8Slogwang         goto kern_fail;
788*a9643ea8Slogwang     rc = curthread->td_retval[0];
789*a9643ea8Slogwang     return (rc);
790*a9643ea8Slogwang kern_fail:
791*a9643ea8Slogwang     ff_os_errno(rc);
792*a9643ea8Slogwang     return (-1);
793*a9643ea8Slogwang }
794*a9643ea8Slogwang 
795*a9643ea8Slogwang int
796*a9643ea8Slogwang ff_getpeername(int s, struct linux_sockaddr * name,
797*a9643ea8Slogwang     socklen_t *namelen)
798*a9643ea8Slogwang {
799*a9643ea8Slogwang     int rc;
800*a9643ea8Slogwang     struct sockaddr bsdaddr;
801*a9643ea8Slogwang     struct sockaddr *pf = &bsdaddr;
802*a9643ea8Slogwang 
803*a9643ea8Slogwang     if ((rc = kern_getpeername(curthread, s, &pf, namelen)))
804*a9643ea8Slogwang         goto kern_fail;
805*a9643ea8Slogwang 
806*a9643ea8Slogwang     if (name)
807*a9643ea8Slogwang         freebsd2linux_sockaddr(name, pf);
808*a9643ea8Slogwang 
809*a9643ea8Slogwang     return (rc);
810*a9643ea8Slogwang kern_fail:
811*a9643ea8Slogwang     ff_os_errno(rc);
812*a9643ea8Slogwang     return (-1);
813*a9643ea8Slogwang }
814*a9643ea8Slogwang 
815*a9643ea8Slogwang int
816*a9643ea8Slogwang ff_getsockname(int s, struct linux_sockaddr *name,
817*a9643ea8Slogwang     socklen_t *namelen)
818*a9643ea8Slogwang {
819*a9643ea8Slogwang     int rc;
820*a9643ea8Slogwang     struct sockaddr bsdaddr;
821*a9643ea8Slogwang     struct sockaddr *pf = &bsdaddr;
822*a9643ea8Slogwang 
823*a9643ea8Slogwang     if ((rc = kern_getsockname(curthread, s, &pf, namelen)))
824*a9643ea8Slogwang         goto kern_fail;
825*a9643ea8Slogwang 
826*a9643ea8Slogwang     if (name)
827*a9643ea8Slogwang         freebsd2linux_sockaddr(name, pf);
828*a9643ea8Slogwang 
829*a9643ea8Slogwang     return (rc);
830*a9643ea8Slogwang 
831*a9643ea8Slogwang kern_fail:
832*a9643ea8Slogwang     ff_os_errno(rc);
833*a9643ea8Slogwang     return (-1);
834*a9643ea8Slogwang }
835*a9643ea8Slogwang 
836*a9643ea8Slogwang int
837*a9643ea8Slogwang ff_shutdown(int s, int how)
838*a9643ea8Slogwang {
839*a9643ea8Slogwang     int rc;
840*a9643ea8Slogwang 
841*a9643ea8Slogwang     struct shutdown_args sa = {
842*a9643ea8Slogwang         .s = s,
843*a9643ea8Slogwang         .how = how,
844*a9643ea8Slogwang     };
845*a9643ea8Slogwang     if ((rc = sys_shutdown(curthread, &sa)))
846*a9643ea8Slogwang         goto kern_fail;
847*a9643ea8Slogwang 
848*a9643ea8Slogwang     return (rc);
849*a9643ea8Slogwang kern_fail:
850*a9643ea8Slogwang     ff_os_errno(rc);
851*a9643ea8Slogwang     return (-1);
852*a9643ea8Slogwang }
853*a9643ea8Slogwang 
854*a9643ea8Slogwang int
855*a9643ea8Slogwang ff_sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
856*a9643ea8Slogwang          const void *newp, size_t newlen)
857*a9643ea8Slogwang {
858*a9643ea8Slogwang     int rc;
859*a9643ea8Slogwang     size_t retval;
860*a9643ea8Slogwang 
861*a9643ea8Slogwang     rc = userland_sysctl(curthread, __DECONST(int *, name), namelen, oldp, oldlenp,
862*a9643ea8Slogwang         1, __DECONST(void *, newp), newlen, &retval, 0);
863*a9643ea8Slogwang     if (rc)
864*a9643ea8Slogwang         goto kern_fail;
865*a9643ea8Slogwang     if (oldlenp)
866*a9643ea8Slogwang         *oldlenp = retval;
867*a9643ea8Slogwang     return (0);
868*a9643ea8Slogwang kern_fail:
869*a9643ea8Slogwang     ff_os_errno(rc);
870*a9643ea8Slogwang     return (-1);
871*a9643ea8Slogwang }
872*a9643ea8Slogwang 
873*a9643ea8Slogwang int
874*a9643ea8Slogwang ff_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
875*a9643ea8Slogwang     struct timeval *timeout)
876*a9643ea8Slogwang 
877*a9643ea8Slogwang {
878*a9643ea8Slogwang     int rc;
879*a9643ea8Slogwang 
880*a9643ea8Slogwang     rc = kern_select(curthread, nfds, readfds, writefds, exceptfds, timeout, 64);
881*a9643ea8Slogwang     if (rc)
882*a9643ea8Slogwang         goto kern_fail;
883*a9643ea8Slogwang     rc = curthread->td_retval[0];
884*a9643ea8Slogwang 
885*a9643ea8Slogwang     return (rc);
886*a9643ea8Slogwang kern_fail:
887*a9643ea8Slogwang     ff_os_errno(rc);
888*a9643ea8Slogwang     return (-1);
889*a9643ea8Slogwang 
890*a9643ea8Slogwang }
891*a9643ea8Slogwang 
892*a9643ea8Slogwang int
893*a9643ea8Slogwang ff_poll(struct pollfd fds[], nfds_t nfds, int timeout)
894*a9643ea8Slogwang {
895*a9643ea8Slogwang     int rc;
896*a9643ea8Slogwang     struct timespec ts;
897*a9643ea8Slogwang     ts.tv_sec = 0;
898*a9643ea8Slogwang     ts.tv_nsec = 0;
899*a9643ea8Slogwang     if ((rc = kern_poll(curthread, fds, nfds, &ts, NULL)))
900*a9643ea8Slogwang         goto kern_fail;
901*a9643ea8Slogwang     rc = curthread->td_retval[0];
902*a9643ea8Slogwang     return (rc);
903*a9643ea8Slogwang 
904*a9643ea8Slogwang kern_fail:
905*a9643ea8Slogwang     ff_os_errno(rc);
906*a9643ea8Slogwang     return (-1);
907*a9643ea8Slogwang }
908*a9643ea8Slogwang 
909*a9643ea8Slogwang int
910*a9643ea8Slogwang ff_kqueue(void)
911*a9643ea8Slogwang {
912*a9643ea8Slogwang     int rc;
913*a9643ea8Slogwang     if ((rc = kern_kqueue(curthread, 0, NULL)))
914*a9643ea8Slogwang         goto kern_fail;
915*a9643ea8Slogwang 
916*a9643ea8Slogwang     rc = curthread->td_retval[0];
917*a9643ea8Slogwang     return (rc);
918*a9643ea8Slogwang 
919*a9643ea8Slogwang kern_fail:
920*a9643ea8Slogwang     ff_os_errno(rc);
921*a9643ea8Slogwang     return (-1);
922*a9643ea8Slogwang }
923*a9643ea8Slogwang 
924*a9643ea8Slogwang struct sys_kevent_args {
925*a9643ea8Slogwang     int fd;
926*a9643ea8Slogwang     const struct kevent *changelist;
927*a9643ea8Slogwang     int nchanges;
928*a9643ea8Slogwang     struct kevent *eventlist;
929*a9643ea8Slogwang     int nevents;
930*a9643ea8Slogwang     const struct timespec *timeout;
931*a9643ea8Slogwang };
932*a9643ea8Slogwang 
933*a9643ea8Slogwang static int
934*a9643ea8Slogwang kevent_copyout(void *arg, struct kevent *kevp, int count)
935*a9643ea8Slogwang {
936*a9643ea8Slogwang     struct sys_kevent_args *uap;
937*a9643ea8Slogwang 
938*a9643ea8Slogwang     uap = (struct sys_kevent_args *)arg;
939*a9643ea8Slogwang     bcopy(kevp, uap->eventlist, count * sizeof *kevp);
940*a9643ea8Slogwang 
941*a9643ea8Slogwang     uap->eventlist += count;
942*a9643ea8Slogwang 
943*a9643ea8Slogwang     return (0);
944*a9643ea8Slogwang }
945*a9643ea8Slogwang 
946*a9643ea8Slogwang /*
947*a9643ea8Slogwang  * Copy 'count' items from the list pointed to by uap->changelist.
948*a9643ea8Slogwang  */
949*a9643ea8Slogwang static int
950*a9643ea8Slogwang kevent_copyin(void *arg, struct kevent *kevp, int count)
951*a9643ea8Slogwang {
952*a9643ea8Slogwang     struct sys_kevent_args *uap;
953*a9643ea8Slogwang 
954*a9643ea8Slogwang     uap = (struct sys_kevent_args *)arg;
955*a9643ea8Slogwang     bcopy(uap->changelist, kevp, count * sizeof *kevp);
956*a9643ea8Slogwang 
957*a9643ea8Slogwang     uap->changelist += count;
958*a9643ea8Slogwang 
959*a9643ea8Slogwang     return (0);
960*a9643ea8Slogwang }
961*a9643ea8Slogwang 
962*a9643ea8Slogwang int
963*a9643ea8Slogwang ff_kevent(int kq, const struct kevent *changelist, int nchanges,
964*a9643ea8Slogwang     struct kevent *eventlist, int nevents, const struct timespec *timeout)
965*a9643ea8Slogwang {
966*a9643ea8Slogwang     int rc;
967*a9643ea8Slogwang     struct timespec ts;
968*a9643ea8Slogwang     ts.tv_sec = 0;
969*a9643ea8Slogwang     ts.tv_nsec = 0;
970*a9643ea8Slogwang     struct sys_kevent_args ska = {
971*a9643ea8Slogwang         kq,
972*a9643ea8Slogwang         changelist,
973*a9643ea8Slogwang         nchanges,
974*a9643ea8Slogwang         eventlist,
975*a9643ea8Slogwang         nevents,
976*a9643ea8Slogwang         &ts
977*a9643ea8Slogwang     };
978*a9643ea8Slogwang     struct kevent_copyops k_ops = {
979*a9643ea8Slogwang         &ska,
980*a9643ea8Slogwang         kevent_copyout,
981*a9643ea8Slogwang         kevent_copyin
982*a9643ea8Slogwang     };
983*a9643ea8Slogwang 
984*a9643ea8Slogwang     if ((rc = kern_kevent(curthread, kq, nchanges, nevents, &k_ops,
985*a9643ea8Slogwang             &ts)))
986*a9643ea8Slogwang         goto kern_fail;
987*a9643ea8Slogwang 
988*a9643ea8Slogwang     rc = curthread->td_retval[0];
989*a9643ea8Slogwang     return (rc);
990*a9643ea8Slogwang kern_fail:
991*a9643ea8Slogwang     ff_os_errno(rc);
992*a9643ea8Slogwang     return (-1);
993*a9643ea8Slogwang }
994