aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2016-01-05 18:31:40 -0800
committerH. Peter Anvin <hpa@linux.intel.com>2016-01-05 18:35:16 -0800
commitcf8147c43a60d9eb6a6713d16f30364a698a6936 (patch)
tree0060aa600ef88e900329b69575e77b77685c2e49
parent4a7ac3d2d9602d06b301cca62e2382f17fa6d43b (diff)
downloadklibc-cf8147c43a60d9eb6a6713d16f30364a698a6936.tar.gz
[klibc] Add accept4(), handle fallback from accept() to accept4()
Add support for the accept4() system call. Some architectures now have accept4() but not accept(), so introduce a standard fallback. However, since accept() is a socketcall, we have to do some special hacks. While we are at it, handle conditional socketcall stubs based on their existence <linux/net.h>, analogous to <asm/unistd.h>. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--usr/include/sys/socket.h1
-rw-r--r--usr/klibc/Kbuild2
-rw-r--r--usr/klibc/SOCKETCALLS.def1
-rw-r--r--usr/klibc/accept.c16
-rw-r--r--usr/klibc/socketcalls.pl15
5 files changed, 32 insertions, 3 deletions
diff --git a/usr/include/sys/socket.h b/usr/include/sys/socket.h
index 3334212a43ba06..d0ba9ebec630e6 100644
--- a/usr/include/sys/socket.h
+++ b/usr/include/sys/socket.h
@@ -251,6 +251,7 @@ __extern int bind(int, const struct sockaddr *, int);
__extern int connect(int, const struct sockaddr *, socklen_t);
__extern int listen(int, int);
__extern int accept(int, struct sockaddr *, socklen_t *);
+__extern int accept4(int, struct sockaddr *, socklen_t *, int);
__extern int getsockname(int, struct sockaddr *, socklen_t *);
__extern int getpeername(int, struct sockaddr *, socklen_t *);
__extern int socketpair(int, int, int, int *);
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index 55210382637db1..f797166a2967e0 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -58,7 +58,7 @@ klib-y += vsnprintf.o snprintf.o vsprintf.o sprintf.o \
lrand48.o jrand48.o mrand48.o nrand48.o srand48.o seed48.o \
inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \
inet/inet_ntop.o inet/inet_pton.o inet/bindresvport.o \
- send.o recv.o \
+ accept.o send.o recv.o \
access.o chmod.o chown.o dup2.o mknod.o poll.o rename.o stat.o \
lchown.o link.o rmdir.o unlink.o utimes.o lstat.o mkdir.o \
readlink.o realpath.o select.o symlink.o pipe.o \
diff --git a/usr/klibc/SOCKETCALLS.def b/usr/klibc/SOCKETCALLS.def
index 39f7db52c8b8f5..97413dec014d56 100644
--- a/usr/klibc/SOCKETCALLS.def
+++ b/usr/klibc/SOCKETCALLS.def
@@ -9,6 +9,7 @@
<?> int connect(int, const struct sockaddr *, socklen_t);
<?> int listen(int, int);
<?> int accept(int, struct sockaddr *, socklen_t *);
+<?> int accept4(int, struct sockaddr *, socklen_t *, int);
<?> int getsockname(int, struct sockaddr *, socklen_t *);
<?> int getpeername(int, struct sockaddr *, socklen_t *);
<?> int socketpair(int, int, int, int *);
diff --git a/usr/klibc/accept.c b/usr/klibc/accept.c
new file mode 100644
index 00000000000000..3ae7bcd68a3722
--- /dev/null
+++ b/usr/klibc/accept.c
@@ -0,0 +1,16 @@
+/*
+ * pread.c
+ *
+ * Some architectures need to wrap the system call
+ */
+
+#include <sys/socket.h>
+
+#if !_KLIBC_SYS_SOCKETCALL && defined(__NR_accept4) && !defined(__NR_accept)
+
+int accept(int socket, struct sockaddr *address, socklen_t *addr_len)
+{
+ return accept4(socket, address, addr_len, 0);
+}
+
+#endif
diff --git a/usr/klibc/socketcalls.pl b/usr/klibc/socketcalls.pl
index 9df5949417a723..70ded0b0b126a7 100644
--- a/usr/klibc/socketcalls.pl
+++ b/usr/klibc/socketcalls.pl
@@ -47,11 +47,22 @@ while ( defined($line = <FILE>) ) {
print OUT "#include \"socketcommon.h\"\n";
print OUT "\n";
- print OUT "#if _KLIBC_SYS_SOCKETCALL || !defined(__NR_${name})\n\n";
+ print OUT "#if _KLIBC_SYS_SOCKETCALL\n";
+ print OUT "# define DO_THIS_SOCKETCALL\n";
+ print OUT "#else\n";
+ print OUT "# if !defined(__NR_${name})";
+ if ($name eq 'accept') {
+ print OUT " && !defined(__NR_accept4)";
+ }
+ print OUT "\n# define DO_THIS_SOCKETCALL\n";
+ print OUT "# endif\n";
+ print OUT "#endif\n\n";
+
+ print OUT "#if defined(DO_THIS_SOCKETCALL) && defined(SYS_\U${name}\E)\n\n";
print OUT "extern long __socketcall(int, const unsigned long *);\n\n";
- print OUT "$type $name (", join(', ', @cargs), ")\n";
+ print OUT "$type ${name}(", join(', ', @cargs), ")\n";
print OUT "{\n";
print OUT " unsigned long args[$nargs];\n";
for ( $i = 0 ; $i < $nargs ; $i++ ) {