1 /* Copyright (C) 2015-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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/>. */
18 #include <sys/socket.h>
21 #include <socketcall.h>
22 #include <socket-constants-time64.h>
25 getsockopt_syscall (int fd
, int level
, int optname
, void *optval
,
28 #ifdef __ASSUME_GETSOCKOPT_SYSCALL
29 return INLINE_SYSCALL (getsockopt
, 5, fd
, level
, optname
, optval
, len
);
31 return SOCKETCALL (getsockopt
, fd
, level
, optname
, optval
, len
);
35 #ifndef __ASSUME_TIME64_SYSCALLS
37 getsockopt32 (int fd
, int level
, int optname
, void *optval
,
42 if (level
!= SOL_SOCKET
)
47 case COMPAT_SO_RCVTIMEO_NEW
:
48 case COMPAT_SO_SNDTIMEO_NEW
:
50 if (optname
== COMPAT_SO_RCVTIMEO_NEW
)
51 optname
= COMPAT_SO_RCVTIMEO_OLD
;
52 if (optname
== COMPAT_SO_SNDTIMEO_NEW
)
53 optname
= COMPAT_SO_SNDTIMEO_OLD
;
55 struct __timeval32 tv32
;
56 r
= getsockopt_syscall (fd
, level
, optname
, &tv32
,
57 (socklen_t
[]) { sizeof tv32
});
61 /* POSIX states that if the size of the option value is greater than
62 then option length, the option value argument shall be silently
64 if (*len
>= sizeof (struct __timeval64
))
66 struct __timeval64
*tv64
= (struct __timeval64
*) optval
;
67 *tv64
= valid_timeval32_to_timeval64 (tv32
);
68 *len
= sizeof (*tv64
);
71 memcpy (optval
, &tv32
, sizeof tv32
);
75 case COMPAT_SO_TIMESTAMP_NEW
:
76 case COMPAT_SO_TIMESTAMPNS_NEW
:
78 if (optname
== COMPAT_SO_TIMESTAMP_NEW
)
79 optname
= COMPAT_SO_TIMESTAMP_OLD
;
80 if (optname
== COMPAT_SO_TIMESTAMPNS_NEW
)
81 optname
= COMPAT_SO_TIMESTAMPNS_OLD
;
82 r
= getsockopt_syscall (fd
, level
, optname
, optval
, len
);
92 __getsockopt (int fd
, int level
, int optname
, void *optval
, socklen_t
*len
)
94 int r
= getsockopt_syscall (fd
, level
, optname
, optval
, len
);
96 #ifndef __ASSUME_TIME64_SYSCALLS
97 if (r
== -1 && errno
== ENOPROTOOPT
)
98 r
= getsockopt32 (fd
, level
, optname
, optval
, len
);
103 weak_alias (__getsockopt
, getsockopt
)
105 weak_alias (__getsockopt
, __getsockopt64
)