(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
setsockopt.c
       1  /* Copyright (C) 2015-2023 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 <time.h>
      20  #include <sysdep.h>
      21  #include <socketcall.h>
      22  #include <socket-constants-time64.h>
      23  
      24  static int
      25  setsockopt_syscall (int fd, int level, int optname, const void *optval,
      26  		    socklen_t len)
      27  {
      28  #ifdef __ASSUME_SETSOCKOPT_SYSCALL
      29    return INLINE_SYSCALL_CALL (setsockopt, fd, level, optname, optval, len);
      30  #else
      31    return SOCKETCALL (setsockopt, fd, level, optname, optval, len);
      32  #endif
      33  }
      34  
      35  #ifndef __ASSUME_TIME64_SYSCALLS
      36  static int
      37  setsockopt32 (int fd, int level, int optname, const void *optval,
      38  	      socklen_t len)
      39  {
      40    int r = -1;
      41  
      42    if (level != SOL_SOCKET)
      43      return r;
      44  
      45    switch (optname)
      46      {
      47      case COMPAT_SO_RCVTIMEO_NEW:
      48      case COMPAT_SO_SNDTIMEO_NEW:
      49        {
      50          if (len < sizeof (struct __timeval64))
      51  	  {
      52  	    __set_errno (EINVAL);
      53  	    break;
      54  	  }
      55  
      56  	struct __timeval64 *tv64 = (struct __timeval64 *) optval;
      57  	if (! in_int32_t_range (tv64->tv_sec))
      58  	  {
      59  	    __set_errno (EOVERFLOW);
      60  	    break;
      61  	  }
      62  
      63  	if (optname == COMPAT_SO_RCVTIMEO_NEW)
      64  	  optname = COMPAT_SO_RCVTIMEO_OLD;
      65  	if (optname == COMPAT_SO_SNDTIMEO_NEW)
      66  	  optname = COMPAT_SO_SNDTIMEO_OLD;
      67  
      68  	struct __timeval32 tv32 = valid_timeval64_to_timeval32 (*tv64);
      69  
      70  	r = setsockopt_syscall (fd, level, optname, &tv32, sizeof (tv32));
      71        }
      72        break;
      73  
      74      case COMPAT_SO_TIMESTAMP_NEW:
      75      case COMPAT_SO_TIMESTAMPNS_NEW:
      76        {
      77  	if (optname == COMPAT_SO_TIMESTAMP_NEW)
      78  	  optname = COMPAT_SO_TIMESTAMP_OLD;
      79  	if (optname == COMPAT_SO_TIMESTAMPNS_NEW)
      80  	  optname = COMPAT_SO_TIMESTAMPNS_OLD;
      81  	/* The expected type for the option is an 'int' for both types of
      82  	   timestamp formats, so there is no need to convert it.  */
      83  	r = setsockopt_syscall (fd, level, optname, optval, len);
      84        }
      85        break;
      86      }
      87  
      88    return r;
      89  }
      90  #endif
      91  
      92  int
      93  __setsockopt (int fd, int level, int optname, const void *optval, socklen_t len)
      94  {
      95    int r = setsockopt_syscall (fd, level, optname, optval, len);
      96  
      97  #ifndef __ASSUME_TIME64_SYSCALLS
      98    if (r == -1 && errno == ENOPROTOOPT)
      99      r = setsockopt32 (fd, level, optname, optval, len);
     100  #endif
     101  
     102    return r;
     103  }
     104  libc_hidden_def (__setsockopt)
     105  weak_alias (__setsockopt, setsockopt)
     106  #if __TIMESIZE != 64
     107  weak_alias (__setsockopt, __setsockopt64)
     108  #endif