LCOV - code coverage report
Current view: directory - nsprpub/pr/src/io - prmapopt.c (source / functions) Found Hit Coverage
Test: app.info Lines: 11 7 63.6 %
Date: 2012-06-02 Functions: 1 1 100.0 %

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

Generated by: LCOV version 1.7