From 6ff0c75c838e73d2aeccc0102ab58a7b865172ca Mon Sep 17 00:00:00 2001 From: Guillaume Ranquet Date: Mon, 10 Feb 2014 13:11:29 +0100 Subject: [PATCH] Add recvmmsg and sendmmsg syscalls. Also add the corresponding constant, struct, and function declarations to , and perfunctory tests so we know that the symbols actually exist. Signed-off-by: Guillaume Ranquet Change-Id: Ib0d854239d3716be90ad70973c579aff4895a4f7 --- libc/SYSCALLS.TXT | 4 ++ libc/arch-arm/syscalls/recvmmsg.S | 22 ++++++ libc/arch-arm/syscalls/sendmmsg.S | 14 ++++ libc/arch-arm64/syscalls/recvmmsg.S | 21 ++++++ libc/arch-arm64/syscalls/sendmmsg.S | 21 ++++++ libc/arch-mips/syscalls/recvmmsg.S | 19 +++++ libc/arch-mips/syscalls/sendmmsg.S | 19 +++++ libc/arch-mips64/syscalls/recvmmsg.S | 25 +++++++ libc/arch-mips64/syscalls/sendmmsg.S | 25 +++++++ libc/arch-x86/syscalls/recvmmsg.S | 27 +++++++ libc/arch-x86/syscalls/sendmmsg.S | 27 +++++++ libc/arch-x86_64/syscalls/recvmmsg.S | 17 +++++ libc/arch-x86_64/syscalls/sendmmsg.S | 17 +++++ libc/include/sys/socket.h | 103 +++++++++++++++------------ tests/Android.mk | 1 + tests/sys_socket_test.cpp | 34 +++++++++ 16 files changed, 350 insertions(+), 46 deletions(-) create mode 100644 libc/arch-arm/syscalls/recvmmsg.S create mode 100644 libc/arch-arm/syscalls/sendmmsg.S create mode 100644 libc/arch-arm64/syscalls/recvmmsg.S create mode 100644 libc/arch-arm64/syscalls/sendmmsg.S create mode 100644 libc/arch-mips/syscalls/recvmmsg.S create mode 100644 libc/arch-mips/syscalls/sendmmsg.S create mode 100644 libc/arch-mips64/syscalls/recvmmsg.S create mode 100644 libc/arch-mips64/syscalls/sendmmsg.S create mode 100644 libc/arch-x86/syscalls/recvmmsg.S create mode 100644 libc/arch-x86/syscalls/sendmmsg.S create mode 100644 libc/arch-x86_64/syscalls/recvmmsg.S create mode 100644 libc/arch-x86_64/syscalls/sendmmsg.S create mode 100644 tests/sys_socket_test.cpp diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index ee3a05b19..192816816 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -247,6 +247,8 @@ int setsockopt(int, int, int, const void*, socklen_t) arm,arm64,mips, int getsockopt(int, int, int, void*, socklen_t*) arm,arm64,mips,mips64,x86_64 int sendmsg(int, const struct msghdr*, unsigned int) arm,arm64,mips,mips64,x86_64 int recvmsg(int, struct msghdr*, unsigned int) arm,arm64,mips,mips64,x86_64 +int recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*) arm,arm64,mips,mips64,x86_64 +int sendmmsg(int, struct mmsghdr*, unsigned int, int) arm,arm64,mips,mips64,x86_64 # sockets for x86. These are done as an "indexed" call to socketcall syscall. int socket:socketcall:1(int, int, int) x86 @@ -264,6 +266,8 @@ int setsockopt:socketcall:14(int, int, int, const void*, socklen_t) x int getsockopt:socketcall:15(int, int, int, void*, socklen_t*) x86 int sendmsg:socketcall:16(int, const struct msghdr*, unsigned int) x86 int recvmsg:socketcall:17(int, struct msghdr*, unsigned int) x86 +int recvmmsg:socketcall:19(int, struct mmsghdr*, unsigned int, int, const struct timespec*) x86 +int sendmmsg:socketcall:20(int, struct mmsghdr*, unsigned int, int) x86 # scheduler & real-time int sched_setscheduler(pid_t pid, int policy, const struct sched_param* param) all diff --git a/libc/arch-arm/syscalls/recvmmsg.S b/libc/arch-arm/syscalls/recvmmsg.S new file mode 100644 index 000000000..dd8cd8c65 --- /dev/null +++ b/libc/arch-arm/syscalls/recvmmsg.S @@ -0,0 +1,22 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(recvmmsg) + mov ip, sp + stmfd sp!, {r4, r5, r6, r7} + .cfi_def_cfa_offset 16 + .cfi_rel_offset r4, 0 + .cfi_rel_offset r5, 4 + .cfi_rel_offset r6, 8 + .cfi_rel_offset r7, 12 + ldmfd ip, {r4, r5, r6} + ldr r7, =__NR_recvmmsg + swi #0 + ldmfd sp!, {r4, r5, r6, r7} + .cfi_def_cfa_offset 0 + cmn r0, #(MAX_ERRNO + 1) + bxls lr + neg r0, r0 + b __set_errno +END(recvmmsg) diff --git a/libc/arch-arm/syscalls/sendmmsg.S b/libc/arch-arm/syscalls/sendmmsg.S new file mode 100644 index 000000000..04c3fe312 --- /dev/null +++ b/libc/arch-arm/syscalls/sendmmsg.S @@ -0,0 +1,14 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(sendmmsg) + mov ip, r7 + ldr r7, =__NR_sendmmsg + swi #0 + mov r7, ip + cmn r0, #(MAX_ERRNO + 1) + bxls lr + neg r0, r0 + b __set_errno +END(sendmmsg) diff --git a/libc/arch-arm64/syscalls/recvmmsg.S b/libc/arch-arm64/syscalls/recvmmsg.S new file mode 100644 index 000000000..44875cc47 --- /dev/null +++ b/libc/arch-arm64/syscalls/recvmmsg.S @@ -0,0 +1,21 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(recvmmsg) + stp x29, x30, [sp, #-16]! + mov x29, sp + str x8, [sp, #-16]! + + mov x8, __NR_recvmmsg + svc #0 + + ldr x8, [sp], #16 + ldp x29, x30, [sp], #16 + + cmn x0, #(MAX_ERRNO + 1) + cneg x0, x0, hi + b.hi __set_errno + + ret +END(recvmmsg) diff --git a/libc/arch-arm64/syscalls/sendmmsg.S b/libc/arch-arm64/syscalls/sendmmsg.S new file mode 100644 index 000000000..43b2fbfaf --- /dev/null +++ b/libc/arch-arm64/syscalls/sendmmsg.S @@ -0,0 +1,21 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(sendmmsg) + stp x29, x30, [sp, #-16]! + mov x29, sp + str x8, [sp, #-16]! + + mov x8, __NR_sendmmsg + svc #0 + + ldr x8, [sp], #16 + ldp x29, x30, [sp], #16 + + cmn x0, #(MAX_ERRNO + 1) + cneg x0, x0, hi + b.hi __set_errno + + ret +END(sendmmsg) diff --git a/libc/arch-mips/syscalls/recvmmsg.S b/libc/arch-mips/syscalls/recvmmsg.S new file mode 100644 index 000000000..23e511b0a --- /dev/null +++ b/libc/arch-mips/syscalls/recvmmsg.S @@ -0,0 +1,19 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(recvmmsg) + .set noreorder + .cpload t9 + li v0, __NR_recvmmsg + syscall + bnez a3, 1f + move a0, v0 + j ra + nop +1: + la t9,__set_errno + j t9 + nop + .set reorder +END(recvmmsg) diff --git a/libc/arch-mips/syscalls/sendmmsg.S b/libc/arch-mips/syscalls/sendmmsg.S new file mode 100644 index 000000000..d99ba9335 --- /dev/null +++ b/libc/arch-mips/syscalls/sendmmsg.S @@ -0,0 +1,19 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(sendmmsg) + .set noreorder + .cpload t9 + li v0, __NR_sendmmsg + syscall + bnez a3, 1f + move a0, v0 + j ra + nop +1: + la t9,__set_errno + j t9 + nop + .set reorder +END(sendmmsg) diff --git a/libc/arch-mips64/syscalls/recvmmsg.S b/libc/arch-mips64/syscalls/recvmmsg.S new file mode 100644 index 000000000..fa9fbb296 --- /dev/null +++ b/libc/arch-mips64/syscalls/recvmmsg.S @@ -0,0 +1,25 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(recvmmsg) + .set push + .set noreorder + li v0, __NR_recvmmsg + syscall + bnez a3, 1f + move a0, v0 + j ra + nop +1: + move t0, ra + bal 2f + nop +2: + .cpsetup ra, t1, 2b + LA t9,__set_errno + .cpreturn + j t9 + move ra, t0 + .set pop +END(recvmmsg) diff --git a/libc/arch-mips64/syscalls/sendmmsg.S b/libc/arch-mips64/syscalls/sendmmsg.S new file mode 100644 index 000000000..e4d80198f --- /dev/null +++ b/libc/arch-mips64/syscalls/sendmmsg.S @@ -0,0 +1,25 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(sendmmsg) + .set push + .set noreorder + li v0, __NR_sendmmsg + syscall + bnez a3, 1f + move a0, v0 + j ra + nop +1: + move t0, ra + bal 2f + nop +2: + .cpsetup ra, t1, 2b + LA t9,__set_errno + .cpreturn + j t9 + move ra, t0 + .set pop +END(sendmmsg) diff --git a/libc/arch-x86/syscalls/recvmmsg.S b/libc/arch-x86/syscalls/recvmmsg.S new file mode 100644 index 000000000..a7adac823 --- /dev/null +++ b/libc/arch-x86/syscalls/recvmmsg.S @@ -0,0 +1,27 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(recvmmsg) + pushl %ebx + pushl %ecx + .cfi_def_cfa_offset 8 + .cfi_rel_offset ebx, 0 + .cfi_rel_offset ecx, 4 + mov $19, %ebx + mov %esp, %ecx + addl $12, %ecx + movl $__NR_socketcall, %eax + int $0x80 + cmpl $-MAX_ERRNO, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno + addl $4, %esp + orl $-1, %eax +1: + popl %ecx + popl %ebx + ret +END(recvmmsg) diff --git a/libc/arch-x86/syscalls/sendmmsg.S b/libc/arch-x86/syscalls/sendmmsg.S new file mode 100644 index 000000000..46dd6cd4a --- /dev/null +++ b/libc/arch-x86/syscalls/sendmmsg.S @@ -0,0 +1,27 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(sendmmsg) + pushl %ebx + pushl %ecx + .cfi_def_cfa_offset 8 + .cfi_rel_offset ebx, 0 + .cfi_rel_offset ecx, 4 + mov $20, %ebx + mov %esp, %ecx + addl $12, %ecx + movl $__NR_socketcall, %eax + int $0x80 + cmpl $-MAX_ERRNO, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno + addl $4, %esp + orl $-1, %eax +1: + popl %ecx + popl %ebx + ret +END(sendmmsg) diff --git a/libc/arch-x86_64/syscalls/recvmmsg.S b/libc/arch-x86_64/syscalls/recvmmsg.S new file mode 100644 index 000000000..9da70e2c3 --- /dev/null +++ b/libc/arch-x86_64/syscalls/recvmmsg.S @@ -0,0 +1,17 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(recvmmsg) + movq %rcx, %r10 + movl $__NR_recvmmsg, %eax + syscall + cmpq $-MAX_ERRNO, %rax + jb 1f + negl %eax + movl %eax, %edi + call __set_errno + orq $-1, %rax +1: + ret +END(recvmmsg) diff --git a/libc/arch-x86_64/syscalls/sendmmsg.S b/libc/arch-x86_64/syscalls/sendmmsg.S new file mode 100644 index 000000000..7407c12f6 --- /dev/null +++ b/libc/arch-x86_64/syscalls/sendmmsg.S @@ -0,0 +1,17 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(sendmmsg) + movq %rcx, %r10 + movl $__NR_sendmmsg, %eax + syscall + cmpq $-MAX_ERRNO, %rax + jb 1f + negl %eax + movl %eax, %edi + call __set_errno + orq $-1, %rax +1: + ret +END(sendmmsg) diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h index 5eb7e3d90..b6107a576 100644 --- a/libc/include/sys/socket.h +++ b/libc/include/sys/socket.h @@ -75,40 +75,45 @@ enum { }; struct sockaddr { - sa_family_t sa_family; - char sa_data[14]; + sa_family_t sa_family; + char sa_data[14]; }; struct linger { - int l_onoff; - int l_linger; + int l_onoff; + int l_linger; }; struct msghdr { - void * msg_name; - int msg_namelen; - struct iovec * msg_iov; - __kernel_size_t msg_iovlen; - void * msg_control; - __kernel_size_t msg_controllen; - unsigned msg_flags; + void* msg_name; + socklen_t msg_namelen; + struct iovec* msg_iov; + size_t msg_iovlen; + void* msg_control; + size_t msg_controllen; + int msg_flags; +}; + +struct mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; }; struct cmsghdr { - __kernel_size_t cmsg_len; - int cmsg_level; - int cmsg_type; + size_t cmsg_len; + int cmsg_level; + int cmsg_type; }; #define __CMSG_NXTHDR(ctl, len, cmsg) __cmsg_nxthdr((ctl),(len),(cmsg)) #define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg)) #define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) ) -#define CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr)))) +#define CMSG_DATA(cmsg) ((void*)((char*)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr)))) #define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len)) #define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) -#define __CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr) ? (struct cmsghdr *)(ctl) : (struct cmsghdr *)NULL) +#define __CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr) ? (struct cmsghdr*)(ctl) : (struct cmsghdr*)NULL) #define CMSG_FIRSTHDR(msg) __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) -#define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && (cmsg)->cmsg_len <= (unsigned long) ((mhdr)->msg_controllen - ((char *)(cmsg) - (char *)(mhdr)->msg_control))) +#define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && (cmsg)->cmsg_len <= (unsigned long) ((mhdr)->msg_controllen - ((char*)(cmsg) - (char*)(mhdr)->msg_control))) #ifdef __GNUC__ #define __KINLINE static __inline__ @@ -118,16 +123,17 @@ struct cmsghdr { #define __KINLINE static #endif -__KINLINE struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size, struct cmsghdr *__cmsg) { - struct cmsghdr * __ptr; - __ptr = (struct cmsghdr*)(((unsigned char *) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return (struct cmsghdr *)0; - return __ptr; +__KINLINE struct cmsghdr* __cmsg_nxthdr(void* __ctl, size_t __size, struct cmsghdr* __cmsg) { + struct cmsghdr* __ptr; + __ptr = (struct cmsghdr*)(((unsigned char*) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len)); + if ((unsigned long)((char*)(__ptr+1) - (char*) __ctl) > __size) { + return NULL; + } + return __ptr; } -__KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__cmsg) { - return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg); +__KINLINE struct cmsghdr* cmsg_nxthdr (struct msghdr* __msg, struct cmsghdr* __cmsg) { + return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg); } #define SCM_RIGHTS 0x01 @@ -135,9 +141,9 @@ __KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__ #define SCM_SECURITY 0x03 struct ucred { - __u32 pid; - __u32 uid; - __u32 gid; + pid_t pid; + uid_t uid; + gid_t gid; }; #define AF_UNSPEC 0 @@ -241,6 +247,9 @@ struct ucred { #define MSG_ERRQUEUE 0x2000 #define MSG_NOSIGNAL 0x4000 #define MSG_MORE 0x8000 +#define MSG_WAITFORONE 0x10000 +#define MSG_FASTOPEN 0x20000000 +#define MSG_CMSG_CLOEXEC 0x40000000 #define MSG_EOF MSG_FIN #define MSG_CMSG_COMPAT 0 @@ -276,30 +285,32 @@ struct ucred { # define __socketcall extern #endif -__socketcall int socket(int, int, int); -__socketcall int bind(int, const struct sockaddr *, int); -__socketcall int connect(int, const struct sockaddr *, socklen_t); +__socketcall int accept(int, struct sockaddr*, socklen_t*); +__socketcall int bind(int, const struct sockaddr*, int); +__socketcall int connect(int, const struct sockaddr*, socklen_t); +__socketcall int getpeername(int, struct sockaddr*, socklen_t*); +__socketcall int getsockname(int, struct sockaddr*, socklen_t*); +__socketcall int getsockopt(int, int, int, void*, socklen_t*); __socketcall int listen(int, int); -__socketcall int accept(int, struct sockaddr *, socklen_t *); -__socketcall int getsockname(int, struct sockaddr *, socklen_t *); -__socketcall int getpeername(int, struct sockaddr *, socklen_t *); -__socketcall int socketpair(int, int, int, int *); +__socketcall int recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*); +__socketcall int recvmsg(int, struct msghdr*, unsigned int); +__socketcall int sendmmsg(int, const struct mmsghdr*, unsigned int, int); +__socketcall int sendmsg(int, const struct msghdr*, unsigned int); +__socketcall int setsockopt(int, int, int, const void*, socklen_t); __socketcall int shutdown(int, int); -__socketcall int setsockopt(int, int, int, const void *, socklen_t); -__socketcall int getsockopt(int, int, int, void *, socklen_t *); -__socketcall int sendmsg(int, const struct msghdr *, unsigned int); -__socketcall int recvmsg(int, struct msghdr *, unsigned int); +__socketcall int socket(int, int, int); +__socketcall int socketpair(int, int, int, int*); -extern ssize_t send(int, const void *, size_t, unsigned int); -extern ssize_t recv(int, void *, size_t, unsigned int); +extern ssize_t send(int, const void*, size_t, unsigned int); +extern ssize_t recv(int, void*, size_t, unsigned int); -__socketcall ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t); -__socketcall ssize_t recvfrom(int, void *, size_t, unsigned int, const struct sockaddr *, socklen_t *); +__socketcall ssize_t sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t); +__socketcall ssize_t recvfrom(int, void*, size_t, unsigned int, const struct sockaddr*, socklen_t*); #if defined(__BIONIC_FORTIFY) __errordecl(__recvfrom_error, "recvfrom called with size bigger than buffer"); -extern ssize_t __recvfrom_chk(int, void*, size_t, size_t, unsigned int, const struct sockaddr*, socklen_t *); -extern ssize_t __recvfrom_real(int, void *, size_t, unsigned int, const struct sockaddr*, socklen_t*) +extern ssize_t __recvfrom_chk(int, void*, size_t, size_t, unsigned int, const struct sockaddr*, socklen_t*); +extern ssize_t __recvfrom_real(int, void*, size_t, unsigned int, const struct sockaddr*, socklen_t*) __asm__(__USER_LABEL_PREFIX__ "recvfrom"); __BIONIC_FORTIFY_INLINE @@ -324,7 +335,7 @@ ssize_t recvfrom(int fd, void* buf, size_t len, unsigned int flags, const struct } __BIONIC_FORTIFY_INLINE -ssize_t recv(int socket, void *buf, size_t buflen, unsigned int flags) { +ssize_t recv(int socket, void* buf, size_t buflen, unsigned int flags) { return recvfrom(socket, buf, buflen, flags, NULL, 0); } diff --git a/tests/Android.mk b/tests/Android.mk index 5fafba6b0..451b3a99d 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -71,6 +71,7 @@ libBionicStandardTests_src_files := \ sys_resource_test.cpp \ sys_select_test.cpp \ sys_sendfile_test.cpp \ + sys_socket_test.cpp \ sys_stat_test.cpp \ sys_statvfs_test.cpp \ sys_syscall_test.cpp \ diff --git a/tests/sys_socket_test.cpp b/tests/sys_socket_test.cpp new file mode 100644 index 000000000..901ac177e --- /dev/null +++ b/tests/sys_socket_test.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +TEST(sys_socket, recvmmsg) { +#if !defined(__GLIBC__) // TODO: Android's prebuilt gcc is too old for recvmmsg/sendmmsg. + ASSERT_EQ(-1, recvmmsg(-1, NULL, 0, 0, NULL)); + ASSERT_EQ(EBADF, errno); +#endif +} + +TEST(sys_socket, sendmmsg) { +#if !defined(__GLIBC__) // TODO: Android's prebuilt gcc is too old for recvmmsg/sendmmsg. + ASSERT_EQ(-1, sendmmsg(-1, NULL, 0, 0)); + ASSERT_EQ(EBADF, errno); +#endif +}