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