1 /* Copyright (C) 2010-2021 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <sys/socket.h>
19 #include <sysdep.h>
20 #include <socketcall.h>
21 
22 int
__recvmmsg64(int fd,struct mmsghdr * vmessages,unsigned int vlen,int flags,struct __timespec64 * timeout)23 __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
24 	      struct __timespec64 *timeout)
25 {
26 #ifndef __NR_recvmmsg_time64
27 # define __NR_recvmmsg_time64 __NR_recvmmsg
28 #endif
29   int r = SYSCALL_CANCEL (recvmmsg_time64, fd, vmessages, vlen, flags,
30 			  timeout);
31 #ifndef __ASSUME_TIME64_SYSCALLS
32   if (r >= 0 || errno != ENOSYS)
33     return r;
34 
35   struct timespec ts32, *pts32 = NULL;
36   if (timeout != NULL)
37     {
38       if (! in_time_t_range (timeout->tv_sec))
39 	{
40 	  __set_errno (EINVAL);
41 	  return -1;
42 	}
43       ts32 = valid_timespec64_to_timespec (*timeout);
44       pts32 = &ts32;
45     }
46 
47   socklen_t csize[IOV_MAX];
48   if (vlen > IOV_MAX)
49     vlen = IOV_MAX;
50   for (int i = 0; i < vlen; i++)
51     csize[i] = vmessages[i].msg_hdr.msg_controllen;
52 
53 # ifdef __ASSUME_RECVMMSG_SYSCALL
54   r = SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32);
55 # else
56   r = SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32);
57 # endif
58   if (r >= 0)
59     {
60       if (timeout != NULL)
61         *timeout = valid_timespec_to_timespec64 (ts32);
62 
63       for (int i=0; i < r; i++)
64         __convert_scm_timestamps (&vmessages[i].msg_hdr, csize[i]);
65     }
66 #endif /* __ASSUME_TIME64_SYSCALLS  */
67   return r;
68 }
69 #if __TIMESIZE != 64
libc_hidden_def(__recvmmsg64)70 libc_hidden_def (__recvmmsg64)
71 
72 int
73 __recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
74 	    struct timespec *timeout)
75 {
76   struct __timespec64 ts64, *pts64 = NULL;
77   if (timeout != NULL)
78     {
79       ts64 = valid_timespec_to_timespec64 (*timeout);
80       pts64 = &ts64;
81     }
82   int r = __recvmmsg64 (fd, vmessages, vlen, flags, pts64);
83   if (r >= 0 && timeout != NULL)
84     /* The remanining timeout will be always less the input TIMEOUT.  */
85     *timeout = valid_timespec64_to_timespec (ts64);
86   return r;
87 }
88 #endif
89 weak_alias (__recvmmsg, recvmmsg)
90