Esempio n. 1
0
static void
dump (void)
{
  #ifdef EXTENDED_STATS
    FILE *concurrent;
    FILE *reply;
  #endif
  Time conn_period = 0.0, call_period = 0.0;
  Time conn_time = 0.0, resp_time = 0.0, xfer_time = 0.0;
  Time call_size = 0.0, hdr_size = 0.0, reply_size = 0.0, footer_size = 0.0;
  Time lifetime_avg = 0.0, lifetime_stddev = 0.0, lifetime_median = 0.0;
  double reply_rate_avg = 0.0, reply_rate_stddev = 0.0;
  int i, total_replies = 0;
  Time delta, user, sys;
  u_wide total_size;
  Time time;
  u_int n;

  for (i = 1; i < NELEMS (basic.num_replies); ++i)
    total_replies += basic.num_replies[i];

  delta = test_time_stop - test_time_start;

  if (verbose > 1)
    {
      printf ("\nConnection lifetime histogram (time in ms):\n");
      for (i = 0; i < NUM_BINS; ++i)
	if (basic.conn_lifetime_hist[i])
	  {
	    if (i > 0 && basic.conn_lifetime_hist[i - 1] == 0)
	      printf ("%14c\n", ':');
	    time = (i + 0.5)*BIN_WIDTH;
	    printf ("%16.1f %u\n", 1e3*time, basic.conn_lifetime_hist[i]);
	  }
    }

  printf ("\nTotal: connections %u requests %u replies %u "
	  "test-duration %.3f s\n",
	  basic.num_conns_issued, basic.num_sent, total_replies,
	  delta);

  putchar ('\n');

  if (basic.num_conns_issued)
    conn_period = delta/basic.num_conns_issued;
  printf ("Connection rate: %.1f conn/s (%.1f ms/conn, "
	  "<=%u concurrent connections)\n",
	  basic.num_conns_issued / delta, 1e3*conn_period, basic.max_conns);

  if (basic.num_lifetimes > 0)
    {
      lifetime_avg = (basic.conn_lifetime_sum / basic.num_lifetimes);
      if (basic.num_lifetimes > 1)
	lifetime_stddev = STDDEV (basic.conn_lifetime_sum,
				  basic.conn_lifetime_sum2,
				  basic.num_lifetimes);
      n = 0;
      for (i = 0; i < NUM_BINS; i++)
	{
	  n += basic.conn_lifetime_hist[i];
	  if (n >= 0.5*basic.num_lifetimes)
	    {
	      lifetime_median = (i + 0.5)*BIN_WIDTH;
	      break;
	    }
	}
    }  
  printf ("Connection time [ms]: min %.1f avg %.1f max %.1f median %.1f "
	  "stddev %.1f\n",
	  basic.num_lifetimes > 0 ? 1e3 * basic.conn_lifetime_min : 0.0,
	  1e3 * lifetime_avg,
	  1e3 * basic.conn_lifetime_max, 1e3 * lifetime_median,
	  1e3 * lifetime_stddev);
  if (basic.num_connects > 0)
    conn_time = basic.conn_connect_sum / basic.num_connects;
  printf ("Connection time [ms]: connect %.1f\n", 1e3*conn_time);
  printf ("Connection length [replies/conn]: %.3f\n",
	  basic.num_lifetimes > 0
	  ? total_replies/ (double) basic.num_lifetimes : 0.0);
  putchar ('\n');

  if (basic.num_sent > 0)
    call_period = delta/basic.num_sent;
  printf ("Request rate: %.1f req/s (%.1f ms/req)\n",
	  basic.num_sent / delta, 1e3*call_period);

  if (basic.num_sent)
    call_size = basic.req_bytes_sent / basic.num_sent;
  printf ("Request size [B]: %.1f\n", call_size);

  putchar ('\n');

  if (basic.num_reply_rates > 0)
    {
      reply_rate_avg = (basic.reply_rate_sum / basic.num_reply_rates);
      if (basic.num_reply_rates > 1)
	reply_rate_stddev = STDDEV (basic.reply_rate_sum,
				    basic.reply_rate_sum2,
				    basic.num_reply_rates);
    }
  printf ("Reply rate [replies/s]: min %.1f avg %.1f max %.1f stddev %.1f "
	  "(%u samples)\n",
	  basic.num_reply_rates > 0 ? basic.reply_rate_min : 0.0,
	  reply_rate_avg, basic.reply_rate_max,
	  reply_rate_stddev, basic.num_reply_rates);

  if (basic.num_responses > 0)
    resp_time = basic.call_response_sum / basic.num_responses;
  if (total_replies > 0)
    xfer_time = basic.call_xfer_sum / total_replies;
  printf ("Reply time [ms]: response %.3f transfer %.3f\n",
	  1e3*resp_time, 1e3*xfer_time);

  if (total_replies)
    {
      hdr_size = basic.hdr_bytes_received / total_replies;
      reply_size = basic.reply_bytes_received / total_replies;
      footer_size = basic.footer_bytes_received / total_replies;
    }
  printf ("Reply size [B]: header %.1f content %.1f footer %.1f "
	  "(total %.1f)\n", hdr_size, reply_size, footer_size,
	  hdr_size + reply_size + footer_size);

  printf ("Reply status: 1xx=%u 2xx=%u 3xx=%u 4xx=%u 5xx=%u\n",
	  basic.num_replies[1], basic.num_replies[2], basic.num_replies[3],
	  basic.num_replies[4], basic.num_replies[5]);

  putchar ('\n');

  user = (TV_TO_SEC (test_rusage_stop.ru_utime)
	  - TV_TO_SEC (test_rusage_start.ru_utime));
  sys = (TV_TO_SEC (test_rusage_stop.ru_stime)
	  - TV_TO_SEC (test_rusage_start.ru_stime));
  printf ("CPU time [s]: user %.2f system %.2f (user %.1f%% system %.1f%% "
	  "total %.1f%%)\n", user, sys, 100.0*user/delta, 100.0*sys/delta,
	  100.0*(user + sys)/delta);

  total_size = (basic.req_bytes_sent
		+ basic.hdr_bytes_received + basic.reply_bytes_received);
  printf ("Net I/O: %.1f KB/s (%.1f*10^6 bps)\n",
	  total_size/delta / 1024.0, 8e-6*total_size/delta);

  putchar ('\n');

  printf ("Errors: total %u client-timo %u socket-timo %u "
	  "connrefused %u connreset %u\n"
	  "Errors: fd-unavail %u addrunavail %u ftab-full %u other %u\n",
	  (basic.num_client_timeouts + basic.num_sock_timeouts
	   + basic.num_sock_fdunavail + basic.num_sock_ftabfull
	   + basic.num_sock_refused + basic.num_sock_reset
	   + basic.num_sock_addrunavail + basic.num_other_errors),
	  basic.num_client_timeouts, basic.num_sock_timeouts,
	  basic.num_sock_refused, basic.num_sock_reset,
	  basic.num_sock_fdunavail, basic.num_sock_addrunavail,
	  basic.num_sock_ftabfull, basic.num_other_errors);
 /*diwa*/

#ifdef EXTENDED_STATS

  concurrent=fopen("concurrent.txt","w");
  if(!concurrent)
	   printf("\nError: Unable to Open the Concurrent File\nFailed to save Concurrent Connections Data\n");
  reply=fopen(param.rfile_name,"w");
   
   if(concurrent)
   {
     
     for (i = 0; i < CONC_NUM_BINS; i++)
     {
        fprintf(concurrent,"%d,%d\n",(i+1),basic.conc_conn_hist[i]);
     }
     fclose(concurrent);
   }

   if(reply)
   {
      for (i = 0; i < measure_index; i++)
      {
        if(basic.measurement[i].connect==-1)
			basic.measurement[i].connect=-1/1e3;
		/* RSH : Precisions increased to microsecond*/
        fprintf(reply,"%.3f,%.3f,%.3f,%.3f,%d,%d,%d\n",basic.measurement[i].start*1e3,basic.measurement[i].connect*1e3,basic.measurement[i].reply*1e3,basic.measurement[i].xfer*1e3,basic.measurement[i].num_active_conns,basic.measurement[i].response_size,basic.measurement[i].id);
      }
      fclose(reply);
   }

#endif

}
Esempio n. 2
0
void zz_dissect_packet(zz_handler *zz, const struct pcap_pkthdr *packet_header,
                       const uint8_t *packet) {
    struct ieee80211_radiotap_header *radiotap_header;
    struct ieee80211_mac_header *mac_header;
    struct ieee8022_llc_snap_header *llc_snap_header;
    struct ieee8021x_authentication_header *authentication_header;
    char bssid_str[ZZ_MAC_ADDR_STRING_SIZE];
    char source_str[ZZ_MAC_ADDR_STRING_SIZE];
    char destination_str[ZZ_MAC_ADDR_STRING_SIZE];
    char station_str[ZZ_MAC_ADDR_STRING_SIZE];
    zz_mac_addr bssid, source, destination, station;
    const uint8_t *cursor;
    uint32_t safe_size;
    int is_beacon;
    int is_eapol;
    zz_bss *bss;
    zz_packet_outcome outcome;
    const char *extra_info;

    /* save the timestamp of the first packet as a reference */
    if (!zz->epoch) {
        zz->epoch = TV_TO_SEC(packet_header->ts);
    }

    /* check size */
    safe_size = sizeof(struct ieee80211_radiotap_header);
    if (packet_header->caplen < safe_size) {
        log_ts("Skipping too short packet %u bytes", packet_header->caplen);
        return;
    }

    cursor = packet;

    /* get radiotap header */
    radiotap_header = (struct ieee80211_radiotap_header *)cursor;
    cursor += le16toh(radiotap_header->length); /* variable length */

    /* check size */
    safe_size = (cursor - packet) + sizeof(struct ieee80211_mac_header);
    if (packet_header->caplen < safe_size) {
        log_ts("Skipping too short packet %u bytes", packet_header->caplen);
        return;
    }

    /* get mac header */
    mac_header = (struct ieee80211_mac_header *)cursor;
    cursor += sizeof(struct ieee80211_mac_header) +
              (cursor[0] == ZZ_FCF_QOS_DATA ? 2 : 0); /* 2 bytes more for QoS */

    /* possible beacon frame */
    is_beacon = 0;
    if (!mac_header->from_ds && !mac_header->to_ds) {
        /* check if beacon */
        if (((uint8_t *)mac_header)[0] != ZZ_FCF_BEACON) {
            return;
        }

        is_beacon = 1;
        destination = zz_mac_addr_from_array(mac_header->address_1);
        source = zz_mac_addr_from_array(mac_header->address_2);
        bssid = zz_mac_addr_from_array(mac_header->address_3);
        station = 0; /* n.a. */
    }
    /* access point to station */
    else if (mac_header->from_ds && !mac_header->to_ds) {
        destination = zz_mac_addr_from_array(mac_header->address_1);
        bssid = zz_mac_addr_from_array(mac_header->address_2);
        source = zz_mac_addr_from_array(mac_header->address_3);
        station = destination;
    }
    /* station to access point */
    else if (mac_header->to_ds && !mac_header->from_ds){
        bssid = zz_mac_addr_from_array(mac_header->address_1);
        source = zz_mac_addr_from_array(mac_header->address_2);
        destination = zz_mac_addr_from_array(mac_header->address_3);
        station = source;
    } else {
        log_ts("Skipping packet due to frame direction");
        return;
    }

    /* prepare address representations */
    zz_mac_addr_sprint(bssid_str, bssid);
    zz_mac_addr_sprint(source_str, source);
    zz_mac_addr_sprint(destination_str, destination);
    zz_mac_addr_sprint(station_str, station);

    /* lookup or create a descriptor for this bss */
    if (zz_bsss_lookup(&zz->bsss, bssid, &bss)) {
        /* check if this bssid is filtered out just once */
        bss->is_allowed = (zz_members_is_empty(&zz->setup.allowed_bssids) ||
                           zz_members_get(&zz->setup.allowed_bssids, bssid));
    }

    /* skip unwanted access points */
    if (!bss->is_allowed) {
        if (!is_beacon) {
            log_ts("%s @ %s - Skipping unwanted BSSID", station_str, bssid_str);
        }
        return;
    }

    /* save a beacon (just once per bss) */
    if (is_beacon) {
        if (!bss->has_beacon) {
            int ssid_length;
            const char *ssid;

            /* dump the packet if requested */
            if (zz->dumper) {
                pcap_dump((u_char *)zz->dumper, packet_header, packet);
            }

            /* fetch and save the ssid */
            get_ssid(cursor + ZZ_BEACON_SSID_PARAMS_OFFSET,
                     packet_header->caplen - (cursor - packet),
                     &ssid, &ssid_length);
            memcpy(bss->ssid, ssid, ssid_length);
            bss->has_beacon = 1;
            zz_out("SSID discovered '%s' (%s)", bss->ssid, bssid_str);
        }

        /* anyway beacon processing stops here */
        return;
    }

    /* skip blacklisted stations */
    if (zz_members_get(&zz->setup.banned_stations, station)) {
        log_ts("%s @ %s - Skipping banned station", station_str, bssid_str);
        return;
    }

    /* detect broad/multicast traffic */
    if (destination == ZZ_MAC_ADDR_BCAST ||
        destination & ZZ_MAC_ADDR_MCAST_MASK) {

        /* for "handshaked" networks only, if explicitly requested */
        if (zz->setup.dump_group_traffic && bss->n_handshakes > 0) {
            bss->n_data_packets++;

            if (zz->dumper) {
                pcap_dump((u_char *)zz->dumper, packet_header, packet);
            }
        }

        return; /* anyway the processing stops here */
    }

    /* get llc+snap header (required by eapol) */
    llc_snap_header = (struct ieee8022_llc_snap_header *)cursor;
    cursor += sizeof(struct ieee8022_llc_snap_header);

    /* check actual snap and eapol presence */
    safe_size = (cursor - packet) + sizeof(struct ieee8021x_authentication_header);
    is_eapol = (packet_header->caplen >= safe_size &&
                llc_snap_header->dsap == ZZ_DSAP_SNAP &&
                llc_snap_header->ssap == ZZ_SSAP_SNAP &&
                llc_snap_header->control == ZZ_CONTROL_SNAP &&
                llc_snap_header->type == htobe16(ZZ_EAPOL_ETHERTYPE));

    /* get eapol header (if any) */
    if (is_eapol) {
        authentication_header = (struct ieee8021x_authentication_header *)cursor;
    } else {
        authentication_header = NULL;
    }

    /* advance the state machine and perform the needed actions */
    outcome = zz_process_packet(zz, station, bssid, packet_header,
                                authentication_header);

    if (outcome.ignore) {
        switch (outcome.ignore_reason) {
        case ZZ_IGNORE_REASON_RETRANSMISSION:
            log_ts("%s @ %s - Handshake message #%d (retransmission)",
                   station_str, bssid_str, outcome.handshake_info);
            break;
        case ZZ_IGNORE_REASON_INVALID_EAPOL:
            log_ts("%s @ %s - Ignoring invalid key flags",
                   station_str, bssid_str);
            break;
        case ZZ_IGNORE_REASON_INVALID_COUNTER:
            log_ts("%s @ %s - Ignoring invalid replay counter",
                   station_str, bssid_str);
            break;
        }

        return;
    }

    if (outcome.dump_packet) {
        if (!authentication_header) {
            bss->n_data_packets++;
        }
        if (zz->dumper) {
            pcap_dump((u_char *)zz->dumper, packet_header, packet);
        }
    }

    if (outcome.new_client || outcome.track_client) {
        if (zz->setup.is_live) {
            /* (re)start deauthenticating this client */
            zz_killer_post_message(&zz->killer, station, bssid, outcome);
        }
    }

    extra_info = "";
    if (outcome.track_client) {
        switch (outcome.track_reason) {
        case ZZ_TRACK_REASON_ALIVE:
            log_ts("%s @ %s - Activity detected again",
                   station_str, bssid_str);
            break;
        case ZZ_TRACK_REASON_FIRST_HANDSHAKE:
            extra_info = " (first attempt detected)";
            break;
        case ZZ_TRACK_REASON_EXPIRATION:
            extra_info = " (causes restart due to expiration)";
            break;
        case ZZ_TRACK_REASON_INVALIDATION:
            extra_info = " (caused restart due to invalidation)";
            break;
        }
    }

    if (outcome.handshake_info) {
        log_ts("%s @ %s - Handshake message #%d%s",
               station_str, bssid_str, outcome.handshake_info, extra_info);
    }

    if (outcome.new_client) {
        zz_out("New client %s @ %s", station_str, bssid_str);
    }

    if (outcome.got_handshake) {
        zz_out("^_^ Full handshake for %s @ %s", station_str, bssid_str);

        /* stop deauthenticating this client */
        if (zz->setup.is_live) {
            zz_killer_post_message(&zz->killer, station, bssid, outcome);
        }

        /* update stats */
        bss->n_handshakes++;
        zz_members_add(&bss->stations, station);
    }
}
Esempio n. 3
0
static void
dump(void) {
    Time conn_period = 0.0, call_period = 0.0;
    Time conn_time = 0.0, resp_time = 0.0, xfer_time = 0.0;
    Time call_size = 0.0, hdr_size = 0.0, reply_size =
            0.0, footer_size = 0.0;
    Time lifetime_avg = 0.0, lifetime_stddev =
            0.0, lifetime_median = 0.0;
    double reply_rate_avg = 0.0, reply_rate_stddev = 0.0;
    int i, total_replies = 0;
    Time delta, user, sys;
    u_wide total_size;
    Time time;
    u_int n;

    for (i = 1; i < NELEMS(basic.num_replies); ++i)
        total_replies += basic.num_replies[i];

    delta = test_time_stop - test_time_start;

    if (verbose > 1) {
        printf("\nConnection lifetime histogram (time in ms):\n");
        for (i = 0; i < NUM_BINS; ++i)
            if (basic.conn_lifetime_hist[i]) {
                if (i > 0 && basic.conn_lifetime_hist[i - 1] == 0)
                    printf("%14c\n", ':');
                time = (i + 0.5) * BIN_WIDTH;
                printf("%16.1f %u\n", 1e3 * time,
                       basic.conn_lifetime_hist[i]);
            }
    }

    printf("\nTotal: connections %u requests %u replies %u "
                   "test-duration %.3f s\n",
           basic.num_conns_issued, basic.num_sent, total_replies, delta);

    putchar('\n');

    if (basic.num_conns_issued)
        conn_period = delta / basic.num_conns_issued;
    printf("Connection rate: %.1f conn/s (%.1f ms/conn, "
                   "<=%u concurrent connections)\n",
           basic.num_conns_issued / delta, 1e3 * conn_period,
           basic.max_conns);

    if (basic.num_lifetimes > 0) {
        lifetime_avg = (basic.conn_lifetime_sum / basic.num_lifetimes);
        if (basic.num_lifetimes > 1)
            lifetime_stddev = STDDEV(basic.conn_lifetime_sum,
                                     basic.conn_lifetime_sum2,
                                     basic.num_lifetimes);
        n = 0;
        for (i = 0; i < NUM_BINS; ++i) {
            n += basic.conn_lifetime_hist[i];
            if (n >= 0.5 * basic.num_lifetimes) {
                lifetime_median = (i + 0.5) * BIN_WIDTH;
                break;
            }
        }
    }
    printf("Connection time [ms]: min %.1f avg %.1f max %.1f median %.1f "
                   "stddev %.1f\n",
           basic.num_lifetimes > 0 ? 1e3 * basic.conn_lifetime_min : 0.0,
           1e3 * lifetime_avg,
           1e3 * basic.conn_lifetime_max, 1e3 * lifetime_median,
           1e3 * lifetime_stddev);
    if (basic.num_connects > 0)
        conn_time = basic.conn_connect_sum / basic.num_connects;
    printf("Connection time [ms]: connect %.1f\n", 1e3 * conn_time);
    printf("Connection length [replies/conn]: %.3f\n",
           basic.num_lifetimes > 0
           ? total_replies / (double) basic.num_lifetimes : 0.0);
    putchar('\n');

    if (basic.num_sent > 0)
        call_period = delta / basic.num_sent;
    printf("Request rate: %.1f req/s (%.1f ms/req)\n",
           basic.num_sent / delta, 1e3 * call_period);

    if (basic.num_sent)
        call_size = basic.req_bytes_sent / basic.num_sent;
    printf("Request size [B]: %.1f\n", call_size);

    putchar('\n');

    if (basic.num_reply_rates > 0) {
        reply_rate_avg = (basic.reply_rate_sum / basic.num_reply_rates);
        if (basic.num_reply_rates > 1)
            reply_rate_stddev = STDDEV(basic.reply_rate_sum,
                                       basic.reply_rate_sum2,
                                       basic.num_reply_rates);
    }
    printf
            ("Reply rate [replies/s]: min %.1f avg %.1f max %.1f stddev %.1f "
                     "(%u samples)\n",
             basic.num_reply_rates > 0 ? basic.reply_rate_min : 0.0,
             reply_rate_avg, basic.reply_rate_max, reply_rate_stddev,
             basic.num_reply_rates);

    if (basic.num_responses > 0)
        resp_time = basic.call_response_sum / basic.num_responses;
    if (total_replies > 0)
        xfer_time = basic.call_xfer_sum / total_replies;
    printf("Reply time [ms]: response %.1f transfer %.1f\n",
           1e3 * resp_time, 1e3 * xfer_time);

    if (total_replies) {
        hdr_size = basic.hdr_bytes_received / total_replies;
        reply_size = basic.reply_bytes_received / total_replies;
        footer_size = basic.footer_bytes_received / total_replies;
    }
    printf("Reply size [B]: header %.1f content %.1f footer %.1f "
                   "(total %.1f)\n", hdr_size, reply_size, footer_size,
           hdr_size + reply_size + footer_size);

    printf("Reply status: 1xx=%u 2xx=%u 3xx=%u 4xx=%u 5xx=%u\n",
           basic.num_replies[1], basic.num_replies[2],
           basic.num_replies[3], basic.num_replies[4], basic.num_replies[5]);

    putchar('\n');

    user = (TV_TO_SEC(test_rusage_stop.ru_utime)
            - TV_TO_SEC(test_rusage_start.ru_utime));
    sys = (TV_TO_SEC(test_rusage_stop.ru_stime)
           - TV_TO_SEC(test_rusage_start.ru_stime));
    printf
            ("CPU time [s]: user %.2f system %.2f (user %.1f%% system %.1f%% "
                     "total %.1f%%)\n", user, sys, 100.0 * user / delta,
             100.0 * sys / delta, 100.0 * (user + sys) / delta);

    total_size = (basic.req_bytes_sent
                  + basic.hdr_bytes_received + basic.reply_bytes_received);
    printf("Net I/O: %.1f KB/s (%.1f*10^6 bps)\n",
           total_size / delta / 1024.0, 8e-6 * total_size / delta);

    putchar('\n');

    printf("Errors: total %u client-timo %u socket-timo %u "
                   "connrefused %u connreset %u\n"
                   "Errors: fd-unavail %u addrunavail %u ftab-full %u other %u\n",
           (basic.num_client_timeouts + basic.num_sock_timeouts
            + basic.num_sock_fdunavail + basic.num_sock_ftabfull
            + basic.num_sock_refused + basic.num_sock_reset
            + basic.num_sock_addrunavail + basic.num_other_errors),
           basic.num_client_timeouts, basic.num_sock_timeouts,
           basic.num_sock_refused, basic.num_sock_reset,
           basic.num_sock_fdunavail, basic.num_sock_addrunavail,
           basic.num_sock_ftabfull, basic.num_other_errors);
}
Esempio n. 4
0
static void
dump (void)
{
  Time conn_period = 0.0, call_period = 0.0;
  Time call_size = 0.0, hdr_size = 0.0, reply_size = 0.0, footer_size = 0.0;
  double reply_rate_avg = 0.0, reply_rate_stddev = 0.0;
  int i, total_replies = 0;
  Time delta, user, sys;
  u_wide total_size;

  calcstats(&es_lifetime);
  calcstats(&es_connect);
  calcstats(&es_response);
  calcstats(&es_transfer);

  for (i = 1; i < NELEMS (basic.num_replies); ++i)
    total_replies += basic.num_replies[i];

  delta = test_time_stop - test_time_start;


  if (percentiles) {
    printf("\nPercentiles [ms] - lifetime  connect  response  transfer:\n");
    for (i=1;i<=100;i++)
      printf("%6d%% %6.0f %6.0f %6.0f %6.0f\n",
             i,
	     1e3 * es_lifetime.perc[i],
             1e3 * es_connect.perc[i],
             1e3 * es_response.perc[i],
             1e3 * es_transfer.perc[i]);
  }
       
  /* One line summary output with --summary */
  if (summary) {
    printf ("%8.1f ", 1e3 * es_connect.avg);
    if (es_response.num != es_connect.num) 
      printf("******");
    else 
      printf ("%6.1f ", 1e3 * es_response.avg);
    if (total_replies != es_connect.num)
      printf("******");
    else 
      printf ("%6.1f ", 1e3 * es_transfer.avg);
    if (es_lifetime.num != es_connect.num)
      printf("******");
    else 
      printf ("%6.1f ", 1e3 * es_lifetime.avg);
    if (total_replies != es_connect.num)
      printf("   * * *   * * * * *"); 
    else {
      hdr_size = basic.hdr_bytes_received / total_replies;
      reply_size = basic.reply_bytes_received / total_replies;
      footer_size = basic.footer_bytes_received / total_replies;
      printf ("   %d %d %d",(int) hdr_size, (int) reply_size, (int) footer_size);
      printf ("   %d %d %d %d %d",
	      basic.num_replies[1], 
	      basic.num_replies[2], 
	      basic.num_replies[3],
	      basic.num_replies[4], 
	      basic.num_replies[5]);
    }
    printf("\n");
    return;
  }

  if (verbose > 1)
    {
      printf ("\nHistogram - connection lifetime (ms):\n");
      hist_print(es_lifetime.hist);
      printf ("\nHistogram - connect time (ms):\n");
      hist_print(es_connect.hist);
      printf ("\nHistogram - response time (ms):\n");
      hist_print(es_response.hist);
      printf ("\nHistogram - transfer time (ms):\n");
      hist_print(es_transfer.hist);
    }

  printf ("\nTotal: connections %u requests %u replies %u "
	  "test-duration %.3f s\n",
	  basic.num_conns_issued, basic.num_sent, total_replies,
	  delta);

  putchar ('\n');

  if (basic.num_conns_issued)
    conn_period = delta/basic.num_conns_issued;
  printf ("Connection rate: %.1f conn/s (%.1f ms/conn, "
	  "<=%u concurrent connections)\n",
	  basic.num_conns_issued / delta, 1e3*conn_period, basic.max_conns);

  printf ("Connection length [replies/conn]: %.3f\n",
	  es_lifetime.num > 0
	  ? total_replies/ (double) es_lifetime.num : 0.0);

  printf("\n                       num    avg stddev    min  10%%  25%%  50%%  75%%  90%%  95%%  99%% max");
  printf("\nConnection life [ms]");
  printstats(&es_lifetime);
  printf("\nHandshake time  [ms]");
  printstats(&es_connect);
  printf("\nResponse time   [ms]");
  printstats(&es_response);
  printf("\nTransfer time   [ms]");
  printstats(&es_transfer);
  printf("\n\n");

  if (basic.num_sent > 0)
    call_period = delta/basic.num_sent;
  printf ("Request rate: %.1f req/s (%.1f ms/req)\n",
	  basic.num_sent / delta, 1e3*call_period);

  if (basic.num_sent)
    call_size = basic.req_bytes_sent / basic.num_sent;
  printf ("Request size [B]: %.1f\n", call_size);

  putchar ('\n');

  if (basic.num_reply_rates > 0)
    {
      reply_rate_avg = (basic.reply_rate_sum / basic.num_reply_rates);
      if (basic.num_reply_rates > 1)
	reply_rate_stddev = STDDEV (basic.reply_rate_sum,
				    basic.reply_rate_sum2,
				    basic.num_reply_rates);
    }
  printf ("Reply rate [replies/s]: min %.1f avg %.1f max %.1f stddev %.1f "
	  "(%u samples)\n",
	  basic.num_reply_rates > 0 ? basic.reply_rate_min : 0.0,
	  reply_rate_avg, basic.reply_rate_max,
	  reply_rate_stddev, basic.num_reply_rates);

  if (total_replies)
    {
      hdr_size = basic.hdr_bytes_received / total_replies;
      reply_size = basic.reply_bytes_received / total_replies;
      footer_size = basic.footer_bytes_received / total_replies;
    }
  printf ("Reply size [B]: header %.1f content %.1f footer %.1f "
	  "(total %.1f)\n", hdr_size, reply_size, footer_size,
	  hdr_size + reply_size + footer_size);

  printf ("Reply status: 1xx=%u 2xx=%u 3xx=%u 4xx=%u 5xx=%u\n",
	  basic.num_replies[1], basic.num_replies[2], basic.num_replies[3],
	  basic.num_replies[4], basic.num_replies[5]);

  putchar ('\n');

  user = (TV_TO_SEC (test_rusage_stop.ru_utime)
	  - TV_TO_SEC (test_rusage_start.ru_utime));
  sys = (TV_TO_SEC (test_rusage_stop.ru_stime)
	  - TV_TO_SEC (test_rusage_start.ru_stime));
  printf ("CPU time [s]: user %.2f system %.2f (user %.1f%% system %.1f%% "
	  "total %.1f%%)\n", user, sys, 100.0*user/delta, 100.0*sys/delta,
	  100.0*(user + sys)/delta);

  total_size = (basic.req_bytes_sent
		+ basic.hdr_bytes_received + basic.reply_bytes_received);
  printf ("Net I/O: %.1f KB/s (%.1f*10^6 bps)\n",
	  total_size/delta / 1024.0, 8e-6*total_size/delta);

  putchar ('\n');

  printf ("Errors: total %u client-timo %u socket-timo %u "
	  "connrefused %u connreset %u\n"
	  "Errors: fd-unavail %u addrunavail %u ftab-full %u other %u\n",
	  (basic.num_client_timeouts + basic.num_sock_timeouts
	   + basic.num_sock_fdunavail + basic.num_sock_ftabfull
	   + basic.num_sock_refused + basic.num_sock_reset
	   + basic.num_sock_addrunavail + basic.num_other_errors),
	  basic.num_client_timeouts, basic.num_sock_timeouts,
	  basic.num_sock_refused, basic.num_sock_reset,
	  basic.num_sock_fdunavail, basic.num_sock_addrunavail,
	  basic.num_sock_ftabfull, basic.num_other_errors);
}