tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sockopt.c (5216B)


      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 #include "nspr.h"
      7 #include "prio.h"
      8 #include "prinit.h"
      9 #include "prprf.h"
     10 #include "obsolete/probslet.h"
     11 
     12 #include "plerror.h"
     13 
     14 #ifdef XP_UNIX
     15 #  include <sys/socket.h> /* SO_REUSEPORT */
     16 #endif
     17 
     18 static PRFileDesc* err = NULL;
     19 static PRBool failed = PR_FALSE;
     20 
     21 static void Failed(const char* msg1, const char* msg2) {
     22  if (NULL != msg1) {
     23    PR_fprintf(err, "%s ", msg1);
     24  }
     25  PL_FPrintError(err, msg2);
     26  failed = PR_TRUE;
     27 } /* Failed */
     28 
     29 static PRSockOption Incr(PRSockOption* option) {
     30  PRIntn val = ((PRIntn)*option) + 1;
     31  *option = (PRSockOption)val;
     32  return (PRSockOption)val;
     33 } /* Incr */
     34 
     35 int main(int argc, char** argv) {
     36  PRStatus rv;
     37  PRFileDesc* udp = PR_NewUDPSocket();
     38  PRFileDesc* tcp = PR_NewTCPSocket();
     39  const char* tag[] = {
     40      "PR_SockOpt_Nonblocking",    /* nonblocking io */
     41      "PR_SockOpt_Linger",         /* linger on close if data present */
     42      "PR_SockOpt_Reuseaddr",      /* allow local address reuse */
     43      "PR_SockOpt_Keepalive",      /* keep connections alive */
     44      "PR_SockOpt_RecvBufferSize", /* receive buffer size */
     45      "PR_SockOpt_SendBufferSize", /* send buffer size */
     46 
     47      "PR_SockOpt_IpTimeToLive",    /* time to live */
     48      "PR_SockOpt_IpTypeOfService", /* type of service and precedence */
     49 
     50      "PR_SockOpt_AddMember",       /* add an IP group membership */
     51      "PR_SockOpt_DropMember",      /* drop an IP group membership */
     52      "PR_SockOpt_McastInterface",  /* multicast interface address */
     53      "PR_SockOpt_McastTimeToLive", /* multicast timetolive */
     54      "PR_SockOpt_McastLoopback",   /* multicast loopback */
     55 
     56      "PR_SockOpt_NoDelay",    /* don't delay send to coalesce packets */
     57      "PR_SockOpt_MaxSegment", /* maximum segment size */
     58      "PR_SockOpt_Broadcast",  /* Enable broadcast */
     59      "PR_SockOpt_Reuseport",  /* allow local address & port reuse */
     60      "PR_SockOpt_DontFrag",   /* do not fragment */
     61      "PR_SockOpt_Last"};
     62 
     63  err = PR_GetSpecialFD(PR_StandardError);
     64 
     65  if (NULL == udp) {
     66    Failed("PR_NewUDPSocket()", NULL);
     67  } else if (NULL == tcp) {
     68    Failed("PR_NewTCPSocket()", NULL);
     69  } else {
     70    PRSockOption option;
     71    PRUint32 segment = 1024;
     72    PRNetAddr addr;
     73 
     74    rv = PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr);
     75    if (PR_FAILURE == rv) {
     76      Failed("PR_InitializeNetAddr()", NULL);
     77    }
     78    rv = PR_Bind(udp, &addr);
     79    if (PR_FAILURE == rv) {
     80      Failed("PR_Bind()", NULL);
     81    }
     82    for (option = PR_SockOpt_Linger; option < PR_SockOpt_Last; Incr(&option)) {
     83      PRSocketOptionData data;
     84      PRFileDesc* fd = tcp;
     85      data.option = option;
     86      switch (option) {
     87        case PR_SockOpt_Nonblocking:
     88          data.value.non_blocking = PR_TRUE;
     89          break;
     90        case PR_SockOpt_Linger:
     91          data.value.linger.polarity = PR_TRUE;
     92          data.value.linger.linger = PR_SecondsToInterval(2);
     93          break;
     94        case PR_SockOpt_Reuseaddr:
     95          data.value.reuse_addr = PR_TRUE;
     96          break;
     97        case PR_SockOpt_Keepalive:
     98          data.value.keep_alive = PR_TRUE;
     99          break;
    100        case PR_SockOpt_RecvBufferSize:
    101          data.value.recv_buffer_size = segment;
    102          break;
    103        case PR_SockOpt_SendBufferSize:
    104          data.value.send_buffer_size = segment;
    105          break;
    106        case PR_SockOpt_IpTimeToLive:
    107          data.value.ip_ttl = 64;
    108          break;
    109        case PR_SockOpt_IpTypeOfService:
    110          data.value.tos = 0;
    111          break;
    112        case PR_SockOpt_McastTimeToLive:
    113          fd = udp;
    114          data.value.mcast_ttl = 4;
    115          break;
    116        case PR_SockOpt_McastLoopback:
    117          fd = udp;
    118          data.value.mcast_loopback = PR_TRUE;
    119          break;
    120        case PR_SockOpt_NoDelay:
    121          data.value.no_delay = PR_TRUE;
    122          break;
    123 #ifndef WIN32
    124        case PR_SockOpt_MaxSegment:
    125          data.value.max_segment = segment;
    126          break;
    127 #endif
    128        case PR_SockOpt_Broadcast:
    129          fd = udp;
    130          data.value.broadcast = PR_TRUE;
    131          break;
    132 #ifdef SO_REUSEPORT
    133        case PR_SockOpt_Reuseport:
    134          data.value.reuse_port = PR_TRUE;
    135          break;
    136 #endif
    137        case PR_SockOpt_DontFrag:
    138          data.value.dont_fragment = PR_TRUE;
    139          break;
    140 
    141        default:
    142          continue;
    143      }
    144 
    145      /*
    146       * TCP_MAXSEG can only be read, not set
    147       */
    148      if (option != PR_SockOpt_MaxSegment) {
    149 #ifdef WIN32
    150        if (option != PR_SockOpt_McastLoopback)
    151 #endif
    152        {
    153          rv = PR_SetSocketOption(fd, &data);
    154          if (PR_FAILURE == rv) {
    155            Failed("PR_SetSocketOption()", tag[option]);
    156          }
    157        }
    158      }
    159 
    160      rv = PR_GetSocketOption(fd, &data);
    161      if (PR_FAILURE == rv) {
    162        Failed("PR_GetSocketOption()", tag[option]);
    163      }
    164    }
    165    PR_Close(udp);
    166    PR_Close(tcp);
    167  }
    168  PR_fprintf(err, "%s\n", (failed) ? "FAILED" : "PASSED");
    169  return (failed) ? 1 : 0;
    170 } /* main */
    171 
    172 /* sockopt.c */