LCOV - code coverage report
Current view: top level - nsprpub/pr/src/io - prmapopt.c (source / functions) Hit Total Coverage
Test: output.info Lines: 7 11 63.6 %
Date: 2017-07-14 16:53:18 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /*
       7             :  * This file defines _PR_MapOptionName().  The purpose of putting
       8             :  * _PR_MapOptionName() in a separate file is to work around a Winsock
       9             :  * header file problem on Windows NT.
      10             :  *
      11             :  * On Windows NT, if we define _WIN32_WINNT to be 0x0400 (in order
      12             :  * to use Service Pack 3 extensions), windows.h includes winsock2.h
      13             :  * (instead of winsock.h), which doesn't define many socket options
      14             :  * defined in winsock.h.
      15             :  *
      16             :  * We need the socket options defined in winsock.h.  So this file
      17             :  * includes winsock.h, with _WIN32_WINNT undefined.
      18             :  */
      19             : 
      20             : #if defined(WINNT) || defined(__MINGW32__)
      21             : #include <winsock.h>
      22             : #endif
      23             : 
      24             : /* MinGW doesn't define these in its winsock.h. */
      25             : #ifdef __MINGW32__
      26             : #ifndef IP_TTL
      27             : #define IP_TTL 7
      28             : #endif
      29             : #ifndef IP_TOS
      30             : #define IP_TOS 8
      31             : #endif
      32             : #endif
      33             : 
      34             : #include "primpl.h"
      35             : 
      36             : #ifdef HAVE_NETINET_TCP_H
      37             : #include <netinet/tcp.h>  /* TCP_NODELAY, TCP_MAXSEG */
      38             : #endif
      39             : 
      40             : #ifndef _PR_PTHREADS
      41             : 
      42             : PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
      43             : {
      44             :     PRStatus rv;
      45             :     PRInt32 length;
      46             :     PRInt32 level, name;
      47             : 
      48             :     /*
      49             :      * PR_SockOpt_Nonblocking is a special case that does not
      50             :      * translate to a getsockopt() call
      51             :      */
      52             :     if (PR_SockOpt_Nonblocking == data->option)
      53             :     {
      54             :         data->value.non_blocking = fd->secret->nonblocking;
      55             :         return PR_SUCCESS;
      56             :     }
      57             : 
      58             :     rv = _PR_MapOptionName(data->option, &level, &name);
      59             :     if (PR_SUCCESS == rv)
      60             :     {
      61             :         switch (data->option)
      62             :         {
      63             :             case PR_SockOpt_Linger:
      64             :             {
      65             : #if !defined(XP_BEOS) || defined(BONE_VERSION)
      66             :                 struct linger linger;
      67             :                 length = sizeof(linger);
      68             :                 rv = _PR_MD_GETSOCKOPT(
      69             :                     fd, level, name, (char *) &linger, &length);
      70             :                 if (PR_SUCCESS == rv)
      71             :                 {
      72             :                     PR_ASSERT(sizeof(linger) == length);
      73             :                     data->value.linger.polarity =
      74             :                         (linger.l_onoff) ? PR_TRUE : PR_FALSE;
      75             :                     data->value.linger.linger =
      76             :                         PR_SecondsToInterval(linger.l_linger);
      77             :                 }
      78             :                 break;
      79             : #else
      80             :                 PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
      81             :                 return PR_FAILURE;
      82             : #endif
      83             :             }
      84             :             case PR_SockOpt_Reuseaddr:
      85             :             case PR_SockOpt_Keepalive:
      86             :             case PR_SockOpt_NoDelay:
      87             :             case PR_SockOpt_Broadcast:
      88             :             case PR_SockOpt_Reuseport:
      89             :             {
      90             : #ifdef WIN32 /* Winsock */
      91             :                 BOOL value;
      92             : #else
      93             :                 PRIntn value;
      94             : #endif
      95             :                 length = sizeof(value);
      96             :                 rv = _PR_MD_GETSOCKOPT(
      97             :                     fd, level, name, (char*)&value, &length);
      98             :                 if (PR_SUCCESS == rv)
      99             :                     data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE;
     100             :                 break;
     101             :             }
     102             :             case PR_SockOpt_McastLoopback:
     103             :             {
     104             : #ifdef WIN32 /* Winsock */
     105             :                 BOOL bool;
     106             : #else
     107             :                 PRUint8 bool;
     108             : #endif
     109             :                 length = sizeof(bool);
     110             :                 rv = _PR_MD_GETSOCKOPT(
     111             :                     fd, level, name, (char*)&bool, &length);
     112             :                 if (PR_SUCCESS == rv)
     113             :                     data->value.mcast_loopback = (0 == bool) ? PR_FALSE : PR_TRUE;
     114             :                 break;
     115             :             }
     116             :             case PR_SockOpt_RecvBufferSize:
     117             :             case PR_SockOpt_SendBufferSize:
     118             :             case PR_SockOpt_MaxSegment:
     119             :             {
     120             :                 PRIntn value;
     121             :                 length = sizeof(value);
     122             :                 rv = _PR_MD_GETSOCKOPT(
     123             :                     fd, level, name, (char*)&value, &length);
     124             :                 if (PR_SUCCESS == rv)
     125             :                     data->value.recv_buffer_size = value;
     126             :                 break;
     127             :             }
     128             :             case PR_SockOpt_IpTimeToLive:
     129             :             case PR_SockOpt_IpTypeOfService:
     130             :             {
     131             :                 /* These options should really be an int (or PRIntn). */
     132             :                 length = sizeof(PRUintn);
     133             :                 rv = _PR_MD_GETSOCKOPT(
     134             :                     fd, level, name, (char*)&data->value.ip_ttl, &length);
     135             :                 break;
     136             :             }
     137             :             case PR_SockOpt_McastTimeToLive:
     138             :             {
     139             : #ifdef WIN32 /* Winsock */
     140             :                 int ttl;
     141             : #else
     142             :                 PRUint8 ttl;
     143             : #endif
     144             :                 length = sizeof(ttl);
     145             :                 rv = _PR_MD_GETSOCKOPT(
     146             :                     fd, level, name, (char*)&ttl, &length);
     147             :                 if (PR_SUCCESS == rv)
     148             :                     data->value.mcast_ttl = ttl;
     149             :                 break;
     150             :             }
     151             : #ifdef IP_ADD_MEMBERSHIP
     152             :             case PR_SockOpt_AddMember:
     153             :             case PR_SockOpt_DropMember:
     154             :             {
     155             :                 struct ip_mreq mreq;
     156             :                 length = sizeof(mreq);
     157             :                 rv = _PR_MD_GETSOCKOPT(
     158             :                     fd, level, name, (char*)&mreq, &length);
     159             :                 if (PR_SUCCESS == rv)
     160             :                 {
     161             :                     data->value.add_member.mcaddr.inet.ip =
     162             :                         mreq.imr_multiaddr.s_addr;
     163             :                     data->value.add_member.ifaddr.inet.ip =
     164             :                         mreq.imr_interface.s_addr;
     165             :                 }
     166             :                 break;
     167             :             }
     168             : #endif /* IP_ADD_MEMBERSHIP */
     169             :             case PR_SockOpt_McastInterface:
     170             :             {
     171             :                 /* This option is a struct in_addr. */
     172             :                 length = sizeof(data->value.mcast_if.inet.ip);
     173             :                 rv = _PR_MD_GETSOCKOPT(
     174             :                     fd, level, name,
     175             :                     (char*)&data->value.mcast_if.inet.ip, &length);
     176             :                 break;
     177             :             }
     178             :             default:
     179             :                 PR_NOT_REACHED("Unknown socket option");
     180             :                 break;
     181             :         }  
     182             :     }
     183             :     return rv;
     184             : }  /* _PR_SocketGetSocketOption */
     185             : 
     186             : PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data)
     187             : {
     188             :     PRStatus rv;
     189             :     PRInt32 level, name;
     190             : 
     191             :     /*
     192             :      * PR_SockOpt_Nonblocking is a special case that does not
     193             :      * translate to a setsockopt call.
     194             :      */
     195             :     if (PR_SockOpt_Nonblocking == data->option)
     196             :     {
     197             : #ifdef WINNT
     198             :         PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE)
     199             :             || (fd->secret->nonblocking == data->value.non_blocking));
     200             :         if (fd->secret->md.io_model_committed
     201             :             && (fd->secret->nonblocking != data->value.non_blocking))
     202             :         {
     203             :             /*
     204             :              * On NT, once we have associated a socket with the io
     205             :              * completion port, we can't disassociate it.  So we
     206             :              * can't change the nonblocking option of the socket
     207             :              * afterwards.
     208             :              */
     209             :             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     210             :             return PR_FAILURE;
     211             :         }
     212             : #endif
     213             :         fd->secret->nonblocking = data->value.non_blocking;
     214             :         return PR_SUCCESS;
     215             :     }
     216             : 
     217             :     rv = _PR_MapOptionName(data->option, &level, &name);
     218             :     if (PR_SUCCESS == rv)
     219             :     {
     220             :         switch (data->option)
     221             :         {
     222             :             case PR_SockOpt_Linger:
     223             :             {
     224             : #if !defined(XP_BEOS) || defined(BONE_VERSION)
     225             :                 struct linger linger;
     226             :                 linger.l_onoff = data->value.linger.polarity;
     227             :                 linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger);
     228             :                 rv = _PR_MD_SETSOCKOPT(
     229             :                     fd, level, name, (char*)&linger, sizeof(linger));
     230             :                 break;
     231             : #else
     232             :                 PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
     233             :                 return PR_FAILURE;
     234             : #endif
     235             :             }
     236             :             case PR_SockOpt_Reuseaddr:
     237             :             case PR_SockOpt_Keepalive:
     238             :             case PR_SockOpt_NoDelay:
     239             :             case PR_SockOpt_Broadcast:
     240             :             case PR_SockOpt_Reuseport:
     241             :             {
     242             : #ifdef WIN32 /* Winsock */
     243             :                 BOOL value;
     244             : #else
     245             :                 PRIntn value;
     246             : #endif
     247             :                 value = (data->value.reuse_addr) ? 1 : 0;
     248             :                 rv = _PR_MD_SETSOCKOPT(
     249             :                     fd, level, name, (char*)&value, sizeof(value));
     250             :                 break;
     251             :             }
     252             :             case PR_SockOpt_McastLoopback:
     253             :             {
     254             : #ifdef WIN32 /* Winsock */
     255             :                 BOOL bool;
     256             : #else
     257             :                 PRUint8 bool;
     258             : #endif
     259             :                 bool = data->value.mcast_loopback ? 1 : 0;
     260             :                 rv = _PR_MD_SETSOCKOPT(
     261             :                     fd, level, name, (char*)&bool, sizeof(bool));
     262             :                 break;
     263             :             }
     264             :             case PR_SockOpt_RecvBufferSize:
     265             :             case PR_SockOpt_SendBufferSize:
     266             :             case PR_SockOpt_MaxSegment:
     267             :             {
     268             :                 PRIntn value = data->value.recv_buffer_size;
     269             :                 rv = _PR_MD_SETSOCKOPT(
     270             :                     fd, level, name, (char*)&value, sizeof(value));
     271             :                 break;
     272             :             }
     273             :             case PR_SockOpt_IpTimeToLive:
     274             :             case PR_SockOpt_IpTypeOfService:
     275             :             {
     276             :                 /* These options should really be an int (or PRIntn). */
     277             :                 rv = _PR_MD_SETSOCKOPT(
     278             :                     fd, level, name, (char*)&data->value.ip_ttl, sizeof(PRUintn));
     279             :                 break;
     280             :             }
     281             :             case PR_SockOpt_McastTimeToLive:
     282             :             {
     283             : #ifdef WIN32 /* Winsock */
     284             :                 int ttl;
     285             : #else
     286             :                 PRUint8 ttl;
     287             : #endif
     288             :                 ttl = data->value.mcast_ttl;
     289             :                 rv = _PR_MD_SETSOCKOPT(
     290             :                     fd, level, name, (char*)&ttl, sizeof(ttl));
     291             :                 break;
     292             :             }
     293             : #ifdef IP_ADD_MEMBERSHIP
     294             :             case PR_SockOpt_AddMember:
     295             :             case PR_SockOpt_DropMember:
     296             :             {
     297             :                 struct ip_mreq mreq;
     298             :                 mreq.imr_multiaddr.s_addr =
     299             :                     data->value.add_member.mcaddr.inet.ip;
     300             :                 mreq.imr_interface.s_addr =
     301             :                     data->value.add_member.ifaddr.inet.ip;
     302             :                 rv = _PR_MD_SETSOCKOPT(
     303             :                     fd, level, name, (char*)&mreq, sizeof(mreq));
     304             :                 break;
     305             :             }
     306             : #endif /* IP_ADD_MEMBERSHIP */
     307             :             case PR_SockOpt_McastInterface:
     308             :             {
     309             :                 /* This option is a struct in_addr. */
     310             :                 rv = _PR_MD_SETSOCKOPT(
     311             :                     fd, level, name, (char*)&data->value.mcast_if.inet.ip,
     312             :                     sizeof(data->value.mcast_if.inet.ip));
     313             :                 break;
     314             :             }
     315             :             default:
     316             :                 PR_NOT_REACHED("Unknown socket option");
     317             :                 break;
     318             :         }  
     319             :     }
     320             :     return rv;
     321             : }  /* _PR_SocketSetSocketOption */
     322             : 
     323             : #endif /* ! _PR_PTHREADS */
     324             : 
     325             : /*
     326             :  *********************************************************************
     327             :  *********************************************************************
     328             :  **
     329             :  ** Make sure that the following is at the end of this file,
     330             :  ** because we will be playing with macro redefines.
     331             :  **
     332             :  *********************************************************************
     333             :  *********************************************************************
     334             :  */
     335             : 
     336             : /*
     337             :  * Not every platform has all the socket options we want to
     338             :  * support.  Some older operating systems such as SunOS 4.1.3
     339             :  * don't have the IP multicast socket options.  Win32 doesn't
     340             :  * have TCP_MAXSEG.
     341             :  *
     342             :  * To deal with this problem, we define the missing socket
     343             :  * options as _PR_NO_SUCH_SOCKOPT.  _PR_MapOptionName() fails with
     344             :  * PR_OPERATION_NOT_SUPPORTED_ERROR if a socket option not
     345             :  * available on the platform is requested.
     346             :  */
     347             : 
     348             : /*
     349             :  * Sanity check.  SO_LINGER and TCP_NODELAY should be available
     350             :  * on all platforms.  Just to make sure we have included the
     351             :  * appropriate header files.  Then any undefined socket options
     352             :  * are really missing.
     353             :  */
     354             : 
     355             : #if !defined(SO_LINGER)
     356             : #error "SO_LINGER is not defined"
     357             : #endif
     358             : 
     359             : #if !defined(TCP_NODELAY)
     360             : #error "TCP_NODELAY is not defined"
     361             : #endif
     362             : 
     363             : /*
     364             :  * Make sure the value of _PR_NO_SUCH_SOCKOPT is not
     365             :  * a valid socket option.
     366             :  */
     367             : #define _PR_NO_SUCH_SOCKOPT -1
     368             : 
     369             : #ifndef SO_KEEPALIVE
     370             : #define SO_KEEPALIVE        _PR_NO_SUCH_SOCKOPT
     371             : #endif
     372             : 
     373             : #ifndef SO_SNDBUF
     374             : #define SO_SNDBUF           _PR_NO_SUCH_SOCKOPT
     375             : #endif
     376             : 
     377             : #ifndef SO_RCVBUF
     378             : #define SO_RCVBUF           _PR_NO_SUCH_SOCKOPT
     379             : #endif
     380             : 
     381             : #ifndef IP_MULTICAST_IF                 /* set/get IP multicast interface   */
     382             : #define IP_MULTICAST_IF     _PR_NO_SUCH_SOCKOPT
     383             : #endif
     384             : 
     385             : #ifndef IP_MULTICAST_TTL                /* set/get IP multicast timetolive  */
     386             : #define IP_MULTICAST_TTL    _PR_NO_SUCH_SOCKOPT
     387             : #endif
     388             : 
     389             : #ifndef IP_MULTICAST_LOOP               /* set/get IP multicast loopback    */
     390             : #define IP_MULTICAST_LOOP   _PR_NO_SUCH_SOCKOPT
     391             : #endif
     392             : 
     393             : #ifndef IP_ADD_MEMBERSHIP               /* add  an IP group membership      */
     394             : #define IP_ADD_MEMBERSHIP   _PR_NO_SUCH_SOCKOPT
     395             : #endif
     396             : 
     397             : #ifndef IP_DROP_MEMBERSHIP              /* drop an IP group membership      */
     398             : #define IP_DROP_MEMBERSHIP  _PR_NO_SUCH_SOCKOPT
     399             : #endif
     400             : 
     401             : #ifndef IP_TTL                          /* set/get IP Time To Live          */
     402             : #define IP_TTL              _PR_NO_SUCH_SOCKOPT
     403             : #endif
     404             : 
     405             : #ifndef IP_TOS                          /* set/get IP Type Of Service       */
     406             : #define IP_TOS              _PR_NO_SUCH_SOCKOPT
     407             : #endif
     408             : 
     409             : #ifndef TCP_NODELAY                     /* don't delay to coalesce data     */
     410             : #define TCP_NODELAY         _PR_NO_SUCH_SOCKOPT
     411             : #endif
     412             : 
     413             : #ifndef TCP_MAXSEG                      /* maxumum segment size for tcp     */
     414             : #define TCP_MAXSEG          _PR_NO_SUCH_SOCKOPT
     415             : #endif
     416             : 
     417             : #ifndef SO_BROADCAST                    /* enable broadcast on UDP sockets  */
     418             : #define SO_BROADCAST        _PR_NO_SUCH_SOCKOPT
     419             : #endif
     420             : 
     421             : #ifndef SO_REUSEPORT                    /* allow local address & port reuse */
     422             : #define SO_REUSEPORT        _PR_NO_SUCH_SOCKOPT
     423             : #endif
     424             : 
     425           8 : PRStatus _PR_MapOptionName(
     426             :     PRSockOption optname, PRInt32 *level, PRInt32 *name)
     427             : {
     428             :     static PRInt32 socketOptions[PR_SockOpt_Last] =
     429             :     {
     430             :         0, SO_LINGER, SO_REUSEADDR, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF,
     431             :         IP_TTL, IP_TOS, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP,
     432             :         IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP,
     433             :         TCP_NODELAY, TCP_MAXSEG, SO_BROADCAST, SO_REUSEPORT
     434             :     };
     435             :     static PRInt32 socketLevels[PR_SockOpt_Last] =
     436             :     {
     437             :         0, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET,
     438             :         IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP,
     439             :         IPPROTO_IP, IPPROTO_IP, IPPROTO_IP,
     440             :         IPPROTO_TCP, IPPROTO_TCP, SOL_SOCKET, SOL_SOCKET
     441             :     };
     442             : 
     443           8 :     if ((optname < PR_SockOpt_Linger)
     444           8 :     || (optname >= PR_SockOpt_Last))
     445             :     {
     446           0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     447           0 :         return PR_FAILURE;
     448             :     }
     449             : 
     450           8 :     if (socketOptions[optname] == _PR_NO_SUCH_SOCKOPT)
     451             :     {
     452           0 :         PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
     453           0 :         return PR_FAILURE;
     454             :     }
     455           8 :     *name = socketOptions[optname];
     456           8 :     *level = socketLevels[optname];
     457           8 :     return PR_SUCCESS;
     458             : }  /* _PR_MapOptionName */

Generated by: LCOV version 1.13