LCOV - app.info - nsprpub/pr/src/io/prmapopt.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/io - prmapopt.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 11 | 0 | 0.0 %
| Date: | 2012-04-07 | Functions: | 1 | 0 | 0.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               0 : 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               0 :     if ((optname < PR_SockOpt_Linger)
         481               0 :     || (optname >= PR_SockOpt_Last))
         482                 :     {
         483               0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
         484               0 :         return PR_FAILURE;
         485                 :     }
         486                 :
         487               0 :     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               0 :     *name = socketOptions[optname];
         493               0 :     *level = socketLevels[optname];
         494               0 :     return PR_SUCCESS;
         495                 : }  /* _PR_MapOptionName */

Generated by: LCOV version 1.7