Advertisement
lspells

SSL Renegotiation Check - thc-ssl-dos.c modification

Oct 25th, 2011
4,085
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 20.22 KB | None | 0 0
  1. /* *****************************************
  2. This is a hack of thc-ssl-dos.c available at www.thc.org.  
  3. Instead of actually conducting an SSL DoS attack against your site,
  4. this hack will just report whether or not you are vulnerable to the attack. It exits with a 0 if your site is not vuln and a 1 if you are vuln.
  5.  
  6. Syntax is modified from the original only slightly and usage has NOT been updated.
  7. By default, this hack gives you one peer instead of 400.  
  8.  
  9. Use this at your own risk -- no warranty, implied or stated, is provided.  
  10.  
  11. Build this by downloading the original sources from http://www.thc.org/thc-ssl-dos/ and replacing the thc-ssl-dos.c file in the src directory with this one.  Then do a make clean ; make in the src directory.
  12.  
  13. Lamar Spells
  14. **************************************** */
  15. #include "common.h"
  16. #include <getopt.h>
  17. #include <openssl/ssl.h>
  18. #include <openssl/err.h>
  19.  
  20.  
  21. #define MAX_PEERS               (999)
  22. #define DEFAULT_PEERS           (1)
  23. #define PROGRAM_NAME            "thc-ssl-dos"
  24. #define TO_TCP_CONNECT          (10)    /* 10 second TCP connect() timeout */
  25.  
  26.  
  27. struct _statistics
  28. {
  29.         uint32_t total_tcp_connections;
  30.         uint32_t total_renegotiations;
  31.         uint32_t total_ssl_connect;
  32.         uint32_t error_count;
  33.         uint64_t epoch_start_usec;
  34.         uint32_t epoch_start_renegotiations;
  35. };
  36.  
  37. struct _opt
  38. {
  39.         uint32_t flags;
  40.         uint16_t n_peers;
  41.         uint16_t n_max_peers;
  42.         uint32_t ip;
  43.         uint16_t port;
  44.         fd_set rfds;
  45.         fd_set wfds;
  46.         int max_sox;
  47.         SSL_CTX *ctx;
  48.         struct _statistics stat;
  49.         int slowstart_last_peer_idx;
  50. };
  51. #define FL_SECURE_RENEGOTIATION         (0x01)
  52. #define FL_UNSECURE_RENEGOTIATION       (0x02)
  53. #define FL_OUTPUT_SR_ONCE               (0x04)
  54.  
  55. enum _states
  56. {
  57.         STATE_UNKNOWN = 0,
  58.         STATE_TCP_CONNECTING,
  59.         STATE_SSL_CONNECTING,
  60.         STATE_SSL_HANDSHAKING,
  61.         STATE_SSL_DUMMYWRITE
  62. };
  63.  
  64. struct _peer
  65. {
  66.         uint32_t flags;
  67.         SSL *ssl;
  68.         int sox;
  69.         enum _states state;
  70.         struct sockaddr_in addr;
  71.         uint32_t count_renegotiations;
  72.         uint32_t tv_connect_sec;
  73. };
  74. #define FL_PEER_WANT_NEXT_STATE         (0x04)
  75.  
  76. struct _peer peers[MAX_PEERS];
  77. #define PEER_GET_IDX(xpeer)     (int)(xpeer - &peers[0])
  78.  
  79. struct _opt g_opt;
  80.  
  81. #define ERREXIT(a...)   do { \
  82.         fprintf(stderr, "%s:%d ", __func__, __LINE__); \
  83.         fprintf(stderr, a); \
  84.         exit(-1); \
  85. } while (0)
  86.  
  87. #define DEBUGF(a...)    do { \
  88.         fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
  89.         fprintf(stderr, a); \
  90. } while (0)
  91.  
  92. #define SSLERR(a...)    do { \
  93.         fprintf(stderr, a); \
  94.         fprintf(stderr, ": %s\n", ERR_error_string(ERR_get_error(), NULL)); \
  95. } while (0)
  96.  
  97. #define SSLERREXIT(a...)        do { \
  98.         SSLERR(a); \
  99.         exit(-1); \
  100. } while (0)
  101.  
  102. static int tcp_connect_io(struct _peer *p);
  103. static int tcp_connect_try_finish(struct _peer *p, int ret);
  104. static void PEER_SSL_renegotiate(struct _peer *p);
  105. static void PEER_connect(struct _peer *p);
  106. static void PEER_disconnect(struct _peer *p);
  107.  
  108. static char *
  109. int_ntoa(uint32_t ip)
  110. {
  111.         struct in_addr x;
  112.  
  113.         //memset(&x, 0, sizeof x);
  114.         x.s_addr = ip;
  115.         return inet_ntoa(x);
  116. }
  117.  
  118. static uint64_t
  119. getusec(struct timeval *tv)
  120. {
  121.         struct timeval tv_l;
  122.  
  123.         if (tv == NULL)
  124.         {
  125.                 tv = &tv_l;
  126.                 gettimeofday(tv, NULL);
  127.         }
  128.  
  129.         return (uint64_t)tv->tv_sec * 1000000 + tv->tv_usec;
  130. }
  131.  
  132. static void
  133. init_default(void)
  134. {
  135.         g_opt.n_max_peers = DEFAULT_PEERS;
  136.         g_opt.port = htons(443);
  137.         g_opt.ip = -1; //inet_addr("127.0.0.1");
  138.         FD_ZERO(&g_opt.rfds);
  139.         FD_ZERO(&g_opt.wfds);
  140. }
  141.  
  142. static void
  143. init_vars(void)
  144. {
  145.         SSL_library_init();
  146.         SSL_load_error_strings();
  147.         g_opt.ctx = SSL_CTX_new(SSLv23_method());
  148.  
  149. #ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
  150.         SSL_CTX_set_options(g_opt.ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
  151.         /* Always guarantee we can connect to unpatched SSL Servers */
  152.         SSL_CTX_set_options(g_opt.ctx, SSL_OP_LEGACY_SERVER_CONNECT);
  153. #endif
  154.         /* AES256-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(256) */
  155.         /* RC4-MD5                 SSLv3 Kx=RSA      Au=RSA  Enc=RC4(128) */
  156.         /* RSA_decrypt() is 15x slower (used for Kx) than RSA_encrypt() */
  157.         SSL_CTX_set_cipher_list(g_opt.ctx, "AES256-SHA:RC4-MD5");
  158.         //SSL_CTX_set_cipher_list(g_opt.ctx, "AES256-SHA");
  159.         //SSL_CTX_set_cipher_list(g_opt.ctx, "RC4-MD5");
  160.         //SSL_CTX_set_options(g_opt.ctx, SSL_OP_NO_TLSv1);
  161.         //SSL_CTX_set_options(ctx, SSL_OP_LEGACY_SERVER_CONNECT);
  162.  
  163.         int i;
  164.         for (i = 0; i < MAX_PEERS; i++)
  165.                 peers[i].sox = -1;
  166. }
  167.  
  168. static void
  169. usage(void)
  170. {
  171.         fprintf(stderr, ""
  172. "./" PROGRAM_NAME " [options] <ip> <port>\n"
  173. "  -h      help\n"
  174. "  -l <n>  Limit parallel connections [default: %d]\n"
  175. "", DEFAULT_PEERS);
  176.         exit(0);
  177. }
  178.  
  179. static void
  180. do_getopt(int argc, char *argv[])
  181. {
  182.         int c;
  183.         int i;
  184.         static int accept_flag = 0;
  185.         static int skipdelay_flag = 0;
  186.  
  187.         static struct option long_options[] =
  188.         {
  189.                 {"accept", no_argument, &accept_flag, 1},
  190.                 {"skip-delay", no_argument, &skipdelay_flag, 1},
  191.                 {0, 0, 0, 0}
  192.         };
  193.         int option_index = 0;
  194.  
  195.  
  196.         while ((c = getopt_long(argc, argv, "hl:", long_options, &option_index)) != -1)
  197.         {
  198.                 switch (c)
  199.                 {
  200.                 case 0:
  201.                         break;
  202.                 case 'l':
  203.                         g_opt.n_max_peers = atoi(optarg);
  204.                         break;
  205.                 case 'h':
  206.                 default:
  207.                         usage();
  208.                 }
  209.         }
  210.  
  211.         if (optind >= argc)
  212.         {
  213.                 usage();
  214.         }
  215.  
  216.         if (accept_flag == 0)
  217.         {
  218.                 fprintf(stderr, ""
  219. "ERROR:\n"
  220. "Please agree by using '--accept' option that the IP is a legitimate target\n"
  221. "and that you are fully authorized to perform the test against this target.\n"
  222. "");
  223.                 exit(-1);
  224.         }
  225.  
  226.         i = optind;
  227.         if (i < argc)
  228.         {
  229.                 g_opt.ip = inet_addr(argv[i]);
  230.                 i++;
  231.         }
  232.         if (i < argc)
  233.         {
  234.                 g_opt.port = htons(atoi(argv[i]));
  235.                 i++;
  236.         }
  237.  
  238.         if (g_opt.ip == -1)
  239.                 ERREXIT("ERROR: Invalid target IP address\n");
  240. }
  241.  
  242. static void
  243. SSL_set_rw(struct _peer *p, int ret)
  244. {
  245.         int err;
  246.  
  247.         err = SSL_get_error(p->ssl, ret);
  248.         switch (err)
  249.         {
  250.         case SSL_ERROR_WANT_READ:
  251.                FD_SET(p->sox, &g_opt.rfds);
  252.                 FD_CLR(p->sox, &g_opt.wfds);
  253.                 break;
  254.         case SSL_ERROR_WANT_WRITE:
  255.                 FD_SET(p->sox, &g_opt.wfds);
  256.                 FD_CLR(p->sox, &g_opt.rfds);
  257.                 break;
  258.         default:
  259.                 SSLERR("SSL");
  260.                 if (g_opt.stat.total_ssl_connect <= 0)
  261.                 {
  262.                         fprintf(stderr, "#%d: This does not look like SSL!\n", PEER_GET_IDX(p));
  263.                         exit(-1);
  264.                 }
  265.                 g_opt.stat.error_count++;
  266.                 PEER_disconnect(p);
  267.                 return;
  268.         }
  269. }
  270.  
  271. static int
  272. ssl_handshake_io(struct _peer *p)
  273. {
  274.         int ret;
  275.  
  276.         /* Empty input buffer in case peer send data to us */
  277.         char buf[1024];
  278.         while (1)
  279.         {
  280.                 ret = SSL_read(p->ssl, buf, sizeof buf);
  281.                 if (ret <= 0)
  282.                         break;
  283.         }
  284.         ret = SSL_do_handshake(p->ssl);
  285.         if (ret == 1)
  286.         {
  287.                 p->flags |= FL_PEER_WANT_NEXT_STATE;
  288.  
  289.                 /* Stunnel watchdog bug, disconnect if no data is send */
  290.                 g_opt.stat.total_renegotiations++;
  291.                 p->count_renegotiations++;
  292.                 if (p->count_renegotiations % 50 == 0)
  293.                 {
  294.                         p->state = STATE_SSL_DUMMYWRITE;
  295.                 } else {
  296.                         p->state = STATE_SSL_HANDSHAKING;
  297.                 }
  298.  
  299.                 return 0;
  300.         }
  301.         int err;
  302.         err = SSL_get_error(p->ssl, ret);
  303.         if ((err != SSL_ERROR_WANT_READ) && (err != SSL_ERROR_WANT_WRITE))
  304.         {
  305.                 /* Renegotiation is not supported */
  306.                 if (g_opt.stat.total_renegotiations <= 0)
  307.                 {
  308.                         fprintf(stderr, ""
  309. "GOOD: Target has disabled renegotiations.\n");
  310.                         exit(0);
  311.                 }
  312.         }
  313.         else
  314.         {
  315.            if (g_opt.stat.total_renegotiations > 0)
  316.            {
  317.               fprintf(stderr, ""
  318. "BAD: Target is vuln - renegotiations allowed.\n");
  319.               exit(1);
  320.            }
  321.         }
  322.  
  323.         SSL_set_rw(p, ret);
  324.         return 0;
  325. }
  326.  
  327. static int
  328. ssl_connect_io(struct _peer *p)
  329. {
  330.         int ret;
  331.  
  332.         ret = SSL_connect(p->ssl);
  333.         if (ret == 1)
  334.         {
  335.                 g_opt.stat.total_ssl_connect++;
  336. #if 0
  337.                 if (!(g_opt.flags & FL_OUTPUT_SR_ONCE))
  338.                 {
  339.                         g_opt.flags |= FL_OUTPUT_SR_ONCE;
  340. #ifdef SSL_get_secure_renegotiation_support
  341.                         ret = SSL_get_secure_renegotiation_support(p->ssl);
  342.                         printf("Secure Renegotiation support: %s\n", SSL_get_secure_renegotiation_support(p->ssl)?"yes":"no");
  343. #else
  344.                         printf("Secure Renegotiation support: UNKNOWN. [Update your OpenSSL library!]\n");
  345. #endif
  346.                 }
  347. #endif
  348.  
  349.                 p->flags |= FL_PEER_WANT_NEXT_STATE;
  350.                 p->state = STATE_SSL_HANDSHAKING;
  351.                 return 0;
  352.         }
  353.  
  354.         SSL_set_rw(p, ret);
  355.  
  356.         return 0;
  357. }
  358.  
  359. static int
  360. ssl_dummywrite_io(struct _peer *p)
  361. {
  362.         char c = 0;
  363.         int ret;
  364.  
  365.         ret = SSL_write(p->ssl, &c, 1);
  366.         if (ret == 1)
  367.         {
  368.                 p->flags |= FL_PEER_WANT_NEXT_STATE;
  369.                 p->state = STATE_SSL_HANDSHAKING;
  370.                 return 0;
  371.         }
  372.  
  373.         SSL_set_rw(p, ret);
  374.  
  375.         return 0;
  376. }
  377.  
  378.  
  379. static void
  380. PEER_SSL_dummywrite(struct _peer *p)
  381. {
  382.         p->state = STATE_SSL_DUMMYWRITE;
  383.  
  384.         //DEBUGF("%d DummyWrite at %d\n", PEER_GET_IDX(p), p->count_renegotiations);
  385.         ssl_dummywrite_io(p);
  386. }
  387.  
  388. static void
  389. PEER_SSL_renegotiate(struct _peer *p)
  390. {
  391.         int ret;
  392.  
  393.         ret = SSL_renegotiate(p->ssl);
  394.         if (ret != 1)
  395.         {
  396.                 DEBUGF("SSL_renegotiate() failed\n");
  397.                 g_opt.stat.error_count++;
  398.                 PEER_disconnect(p);
  399.                 return;
  400.         }
  401.         p->state = STATE_SSL_HANDSHAKING;
  402.         ssl_handshake_io(p);
  403. }
  404.  
  405. static void
  406. PEER_SSL_connect(struct _peer *p)
  407. {
  408.         p->ssl = SSL_new(g_opt.ctx);
  409.         SSL_set_fd(p->ssl, p->sox);
  410.         p->state = STATE_SSL_CONNECTING;
  411.  
  412.         ssl_connect_io(p);
  413. }
  414.  
  415. static void
  416. NextState(struct _peer *p)
  417. {
  418.  
  419.         p->flags &= ~FL_PEER_WANT_NEXT_STATE;
  420.  
  421.         switch (p->state)
  422.         {
  423.         case STATE_TCP_CONNECTING:
  424.                 PEER_connect(p);
  425.                 break;
  426.         case STATE_SSL_DUMMYWRITE:
  427.                 PEER_SSL_dummywrite(p);
  428.                 break;
  429.         case STATE_SSL_HANDSHAKING:
  430.                 PEER_SSL_renegotiate(p);
  431.                 break;
  432.         default:
  433.                 DEBUGF("NextState(): unknown state: %d\n", p->state);
  434.         }
  435. }
  436.  
  437. static void
  438. CompleteState(struct _peer *p)
  439. {
  440.         int ret;
  441.  
  442.         switch (p->state)
  443.         {
  444.         case STATE_TCP_CONNECTING:
  445.                 ret = tcp_connect_io(p);
  446.                 if (ret != 0)
  447.                 {
  448.                         DEBUGF("%d tcp_connect_io(): %s\n", PEER_GET_IDX(p), strerror(errno));
  449.                         g_opt.stat.error_count++;
  450.                         PEER_disconnect(p);
  451.                 } else {
  452.                         /* TCP connect() successfully */
  453.                         if (g_opt.n_peers < g_opt.n_max_peers)
  454.                         {
  455.                                 //DEBUGF("#%d Activating..\n", g_opt.n_peers);
  456.                                 /* Slowly connect more TCP connections */
  457.                                 if (peers[g_opt.n_peers].state != STATE_UNKNOWN)
  458.                                         ERREXIT("internal error\n");
  459.                                 PEER_disconnect(&peers[g_opt.n_peers]);
  460.                                 g_opt.n_peers++;
  461.                         }
  462.                 }
  463.                 break;
  464.         case STATE_SSL_CONNECTING:
  465.                 ret = ssl_connect_io(p);
  466.                 if (ret != 0)
  467.                         ERREXIT("ssl_connect_io() failed\n");
  468.                 break;
  469.         case STATE_SSL_HANDSHAKING:
  470.                 ret = ssl_handshake_io(p);
  471.                 if (ret != 0)
  472.                 {
  473.                         DEBUGF("ssl_handshake_io() failed\n");
  474.                         g_opt.stat.error_count++;
  475.                         PEER_disconnect(p);
  476.                 }
  477.                 break;
  478.         case STATE_SSL_DUMMYWRITE:
  479.                 ret = ssl_dummywrite_io(p);
  480.                 if (ret != 0)
  481.                 {
  482.                         DEBUGF("ssl_dummywrite_io() failed\n");
  483.                         g_opt.stat.error_count++;
  484.                         PEER_disconnect(p);
  485.                 }
  486.                 break;
  487.         default:
  488.                 ERREXIT("Unknown state: %d\n", p->state);
  489.         }
  490.  
  491. }
  492.  
  493. /*
  494.  * Called if in state STATE_TCP_CONNECTING
  495.  */
  496. static int
  497. tcp_connect_io(struct _peer *p)
  498. {
  499.         int ret;
  500.         socklen_t len;
  501.  
  502.         /* Socket became writeable. Either the connection was successfull
  503.          * (errno == 0) or we have an error and we have to reconnect.
  504.          */
  505.         len = 4;
  506.         getsockopt(p->sox, SOL_SOCKET, SO_ERROR, &errno, &len);
  507.  
  508.         //DEBUGF("ret %d errno %d %s\n", ret, errno, strerror(errno));
  509.         ret = tcp_connect_try_finish(p, errno);
  510.  
  511.         return ret;
  512. }
  513.  
  514. static int
  515. tcp_connect_try_finish(struct _peer *p, int ret)
  516. {
  517.         if (ret != 0)
  518.         {
  519.                 if ((errno != EINPROGRESS) && (errno != EAGAIN))
  520.                 {
  521.                         if (g_opt.stat.total_tcp_connections <= 0)
  522.                         {
  523.                                 fprintf(stderr, "TCP connect(%s:%d): %s\n", int_ntoa(g_opt.ip), ntohs(g_opt.port), strerror(errno));
  524.                                 exit(-1);
  525.  
  526.                         }
  527.                         return -1;
  528.                 }
  529.                 p->state = STATE_TCP_CONNECTING;
  530.                 FD_SET(p->sox, &g_opt.wfds);
  531.                 FD_CLR(p->sox, &g_opt.rfds);
  532.  
  533.                 return 0;
  534.         } else {
  535.                 g_opt.stat.total_tcp_connections++;
  536.                 FD_CLR(p->sox, &g_opt.wfds);
  537.                 PEER_SSL_connect(p);
  538.         }
  539.  
  540.         return 0;
  541. }
  542.  
  543. int
  544. tcp_connect(struct _peer *p)
  545. {
  546.         int ret;
  547.  
  548.         p->sox = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  549.         if (p->sox < 0)
  550.                 return -1;
  551.       if (p->sox > g_opt.max_sox)
  552.                 g_opt.max_sox = p->sox;
  553.  
  554.         fcntl(p->sox, F_SETFL, fcntl(p->sox, F_GETFL, 0) | O_NONBLOCK);
  555.  
  556.         memset(&p->addr, 0, sizeof p->addr);
  557.         p->addr.sin_family = AF_INET;
  558.         p->addr.sin_port = g_opt.port;
  559.         p->addr.sin_addr.s_addr = g_opt.ip;
  560.  
  561.         ret = connect(p->sox, (struct sockaddr *)&p->addr, sizeof p->addr);
  562.         struct timeval tv;
  563.         gettimeofday(&tv, NULL);
  564.         p->tv_connect_sec = tv.tv_sec;
  565.         /* On some linux connect() on localhost can complete instantly even
  566.          * on non-blocking sockets.
  567.          */
  568.         ret = tcp_connect_try_finish(p, ret);
  569.  
  570.         return ret;
  571. }
  572.  
  573. static void
  574. PEER_read(struct _peer *p)
  575. {
  576.         CompleteState(p);
  577. }
  578.  
  579. static void
  580. PEER_write(struct _peer *p)
  581. {
  582.         CompleteState(p);
  583. }
  584.  
  585.  
  586. /*
  587.  * Connect the peer via TCP
  588.  */
  589. static void
  590. PEER_connect(struct _peer *p)
  591. {
  592.         if (tcp_connect(p) != 0)
  593.         {
  594.                 ERREXIT("tcp_connect(): %s\n", strerror(errno));
  595.         }
  596. }
  597.  
  598. static void
  599. PEER_disconnect(struct _peer *p)
  600. {
  601.         if (p->ssl != NULL)
  602.         {
  603.                 /* Make sure session is not kept in cache.
  604.                  * Calling SSL_free() without calling SSL_shutdown will
  605.                  * also remove the session from the session cache.
  606.                  */
  607.                 SSL_free(p->ssl);
  608.                 p->ssl = NULL;
  609.         }
  610.         if (p->sox >= 0)
  611.         {
  612.                 FD_CLR(p->sox, &g_opt.rfds);
  613.                 FD_CLR(p->sox, &g_opt.wfds);
  614.                 close(p->sox);
  615.                 p->sox = -1;
  616.         }
  617.  
  618.         p->state = STATE_TCP_CONNECTING;
  619.         p->flags = FL_PEER_WANT_NEXT_STATE;
  620. }
  621.  
  622. static void
  623. statistics_update(struct timeval *tv)
  624. {
  625.         int32_t reneg_delta;
  626.         uint32_t usec_delta;
  627.         uint64_t usec_now;
  628.         int32_t conn = 0;
  629.         int i;
  630.  
  631.         reneg_delta = g_opt.stat.total_renegotiations - g_opt.stat.epoch_start_renegotiations;
  632.         usec_now = getusec(tv);
  633.         usec_delta = usec_now - g_opt.stat.epoch_start_usec;
  634.  
  635.         for (i = 0; i < g_opt.n_peers; i++)
  636.         {
  637.                 if (peers[i].sox < 0)
  638.                         continue;
  639.                 if (peers[i].state > STATE_TCP_CONNECTING)
  640.                         conn++;
  641.         }
  642.         /* printf("Handshakes %" PRIu32" [%.2f h/s], %" PRId32 " Conn, %" PRIu32 " Err\n", g_opt.stat.total_renegotiations, (float)(1000000 * reneg_delta) / usec_delta, conn, g_opt.stat.error_count); */
  643.  
  644.         g_opt.stat.epoch_start_renegotiations = g_opt.stat.total_renegotiations;
  645.         g_opt.stat.epoch_start_usec = usec_now;
  646. }
  647.  
  648. int
  649. main(int argc, char *argv[])
  650. {
  651.         int n;
  652.        int i;
  653.         fd_set rfds;
  654.         fd_set wfds;
  655.  
  656.         fflush(stdout);
  657.  
  658.         init_default();
  659.         do_getopt(argc, argv);
  660.         init_vars();
  661.  
  662.         g_opt.n_peers = 1;
  663.         for (i = 0; i < g_opt.n_peers; i++)
  664.         {
  665.                 PEER_disconnect(&peers[i]);
  666.         }
  667.  
  668.         struct timeval tv;
  669.         while (1)
  670.         {
  671.                 for (i = 0; i < g_opt.n_peers; i++)
  672.                 {
  673.                         if (peers[i].flags & FL_PEER_WANT_NEXT_STATE)
  674.                                 NextState(&peers[i]);
  675.                 }
  676.                 tv.tv_sec = 0;
  677.                 tv.tv_usec = 100 * 1000;
  678.                 memcpy(&rfds, &g_opt.rfds, sizeof rfds);
  679.                 memcpy(&wfds, &g_opt.wfds, sizeof wfds);
  680.                 n = select(g_opt.max_sox + 1, &rfds, &wfds, NULL, &tv);
  681.                 gettimeofday(&tv, NULL);
  682.                 if (tv.tv_sec != g_opt.stat.epoch_start_usec / 1000000)
  683.                 {
  684.                         if (g_opt.stat.total_tcp_connections > 0) {
  685.                                 statistics_update(&tv);
  686.                         }
  687.                 }
  688.  
  689.                 if (n < 0)
  690.                         ERREXIT("select(): %s\n", strerror(errno));
  691.  
  692.                 /* g_opt.n_peers is dynamicly modified in this loop */
  693.                 int end = g_opt.n_peers;
  694.                 for (i = 0; i < end; i++)
  695.                 {
  696.                         if ((peers[i].state == STATE_TCP_CONNECTING) && (peers[i].tv_connect_sec + TO_TCP_CONNECT < tv.tv_sec))
  697.                         {
  698.                                 fprintf(stderr, "#%d Connection timed out\n", i);
  699.                                 PEER_disconnect(&peers[i]);
  700.                                 continue;
  701.                         }
  702.                   if (peers[i].sox < 0)
  703.                                 continue;
  704.                         if (FD_ISSET(peers[i].sox, &rfds))
  705.                         {
  706.                                 PEER_read(&peers[i]);
  707.                                 continue;
  708.                         }
  709.                         if (FD_ISSET(peers[i].sox, &wfds))
  710.                         {
  711.                                 PEER_write(&peers[i]);
  712.                                 continue;
  713.                         }
  714.                 }
  715.         }
  716.  
  717.         exit(0);
  718.         return 0;
  719. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement