/***************************************************************************
* DBS: Distributed Benchmark System
* Copyright (c) 1995, 1996, 1997 Yukio Murayama
* Copyright (c) 1995, 1996, 1997 Nara Institute of Science and Technology
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided only with the following
* conditions are satisfied:
*
* 1. Both the copyright notice and this permission notice appear in
* all copies of the software, derivative works or modified versions,
* and any portions thereof, and that both notices appear in
* supporting documentation.
* 2. All advertising materials mentioning features or use of this
* software must display the following acknowledgement:
* This product includes software developed by Nara Institute of
* Science and Technology and its contributors.
* 3. Neither the name of Nara Institute of Science and Technology nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND NARA
* INSTITUTE OF SCIENCE AND TECHNOLOGY DISCLAIMS ANY LIABILITY OF
* ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
* THIS SOFTWARE. ALSO, THERE IS NO WARRANTY IMPLIED OR OTHERWISE,
* NOR IS SUPPORT PROVIDED.
*
* Feedback of the results generated from any improvements or
* extensions made to this software would be much appreciated.
* Any such feedback should be sent to:
*
* Yukio Murayama
* E-mail: <yukio-m@is.aist-nara.ac.jp>
* URL: <http://shika.aist-nara.ac.jp/member/yukio-m/index.html>
* Address: Graduate School of Information Science,
* Nara Institute of Science and Technology,
* Takayama 8916-5, Ikoma, Nara, Japan
*
* Nara Institute of Science and Technology has the rights to
* redistribute these changes.
***************************************************************************/
/*****************************************************************
* Distributed Benchmark System
* DBS Client
* $Revision: 1.25 $
* $Date: 1997/07/11 00:54:00 $
* $Author: yukio-m $
*****************************************************************/
#define DBSC
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <setjmp.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#if (!defined(BSD) || (BSD < 199306))
#include <malloc.h>
#endif
#include "dbs.h"
#include "dbsc.h"
#include "dbs_net.h"
#define FREE(A) if ((A) != (NULL)) free(A)
int receive_status __P((int fd, char *msg));
void get_origin_time __P((struct timeval *origin_time));
int recv_result __P((struct scan_cmd *cmd));
int recv_tcp_trace __P((int fd, struct tcp_trace_net *rt));
void write_tcp_trace __P((char *name, struct tcp_trace_net *td));
void write_result __P((char *name, struct record_net *rd1, struct record_net *rd2));
int recv_sub __P((int fd, struct record_net *rd));
int is_send_recv __P((struct scan_cmd *cmd, int serverflg));
struct send_recv *set_send_recv __P((struct scan_cmd *cmd, int serverflg));
void send_cmd __P((int fd, struct scan_cmd *cmd, int sendflg));
void send_command __P((struct scan_cmd *cmd, int port, int sendflg));
void tcp_terminate __P((int fd));
void send_origin_time __P((int fd, struct timeval origin_time));
int tcp_init_client __P((char *remotehost, int port));
void init_scan_cmd __P((struct scan_cmd *scan_cmd));
void error __P((struct scan_cmd *scan, int sr, int e, char *msg));
int send_request __P((int fd, int i));
void safe_exit __P((void));
void safe_exit1 __P((int signo));
void safe_exit2 __P((int signo));
void tcp_init_client_timeout __P((int signo));
void help __P((char *prog));
struct scan_cmd *scan_cmd = (struct scan_cmd *)NULL;
static jmp_buf env_alrm;
/*****************************************************************
* MAIN
*****************************************************************/
void main(argc, argv)
int argc;
char *argv[];
{
struct servent *sp;
struct timeval origin_time;
struct scan_cmd *cmd;
FILE *fp;
int port;
int ch, i, e, n;
int end_time;
char *fname=NULL;
char msg[CHAR_ARRAY];
char buf[256];
extern char *optarg;
extern int optind, opterr;
extern struct scan_cmd *scan_cmd;
if ((sp = getservbyname("dbs", "tcp")) != NULL) {
port = (int)ntohs((u_short)sp->s_port);
} else {
port = DEFAULT_PORT;
}
if (argc <=1) {
help(argv[0]);
exit(1);
}
while ((ch = getopt(argc, argv, "dp:v")) != EOF) {
switch(ch) {
case 'p': /* -p: Port Number */
port = atoi(optarg);
break;
case 'd': /* -d: DEBUG MODE */
debug++;
break;
case 'v': /* -v: show version */
default:
help(argv[0]);
exit(1);
}
}
DEBUGMSG2(1, fprintf(stderr,"debug level = %d\n", debug));
if ((fname = argv[optind]) == 0) {
help(argv[0]);
exit(1);
}
DEBUGMSG2(2, fprintf(stderr, "sizeof(struct scan_cmd) = %dbyte\n", (int)sizeof(struct scan_cmd)));
/*
* Scan Command file.
*/
DEBUGMSG(0, "Command File: ");
if ((fp=fopen(fname, "r")) == NULL) {
char tmp[256];
sprintf(tmp, "fopen '%s'",fname);
perror(tmp);
exit(1);
}
n = scan(&scan_cmd, fp);
fclose(fp);
if (n <= 0) {
fprintf(stderr, "\nError: Command File is Empty.\n");
exit(1);
}
DEBUGMSG(0, "OK\n");
init_scan_cmd(scan_cmd);
signal(SIGINT, safe_exit1);
signal(SIGPIPE, safe_exit2);
signal(SIGALRM, tcp_init_client_timeout);
/*
* Send Command to Server
*/
DEBUGMSG(1, "Sending Command to SERVER\n");
send_command(cmd, port, SERVER);
sleep((int)RECV_DELAY_OFFSET);
/*
* Send Command to Client
*/
DEBUGMSG(1, "Sending Command to CLIENT\n");
send_command(cmd, port, CLIENT);
DEBUGMSG(1, "SEND COMMAND: Normal END.\n");
/****** Send Start Time or Exit. *****/
get_origin_time(&origin_time);
for (cmd = scan_cmd; cmd; cmd = cmd->next) {
send_origin_time(cmd->sender.fd, origin_time);
cmd->sender.status = S_GO;
send_origin_time(cmd->receiver.fd, origin_time);
cmd->receiver.status = S_GO;
}
DEBUGMSG(1, "SEND START TIME: Normal END.\n");
end_time = 0;
for (cmd = scan_cmd; cmd; cmd = cmd->next) {
if (end_time < cmd->end_time.tv_sec)
end_time = cmd->end_time.tv_sec;
}
i = (int)(end_time + START_TIME_OFFSET + END_TIME_OFFSET1 + END_TIME_OFFSET2);
DEBUGMSG2(0, fprintf(stderr, "Test Start. Test time=%ds\n", i));
sleep(i);
DEBUGMSG(0, "Test End.\n");
/***** Receive Status (Result). *****/
DEBUGMSG(1, "Wait for results from dbsd .....\n");
for (cmd = scan_cmd; cmd; cmd = cmd->next) {
int timeout_flg = OFF;
if (send_request(cmd->sender.fd, NORMAL) == -1) {
error(cmd, SEND, ABNORMAL, msg);
cmd->sender.status = S_ERROR;
safe_exit();
}
if ((e = receive_status(cmd->sender.fd, msg)) != NORMAL) {
error(cmd, SEND, e, msg);
cmd->sender.status = S_ERROR;
safe_exit();
}
if (strcmp(msg,"*Time Out*") == 0) {
timeout_flg = ON;
}
if (send_request(cmd->receiver.fd, NORMAL) == -1) {
error(cmd, RECEIVE, ABNORMAL, msg);
cmd->receiver.status = S_ERROR;
safe_exit();
}
if ((e = receive_status(cmd->receiver.fd, msg)) != NORMAL) {
error(cmd, RECEIVE, e, msg);
cmd->receiver.status = S_ERROR;
safe_exit();
}
if (strcmp(msg,"*Time Out*") == 0) {
timeout_flg = ON;
}
if (timeout_flg == ON) {
fprintf(stderr, "*Time Out*:(%s,%s,%d,%d,%s)\n",
cmd->sender.hostname,
cmd->receiver.hostname,
cmd->sender.port,
cmd->receiver.port,
(cmd->transport==TCP)?"TCP":"UDP");
fprintf(stderr, "'end_time=%.0f' is small.\n", timeval2double(&(cmd->end_time)));
}
}
DEBUGMSG(1, "RECEIVE STATUS: Normal END.\n");
/***** Receive Results and Write into File. *****/
for (cmd = scan_cmd; cmd; cmd = cmd->next) {
DEBUGMSG2(0,
fprintf(stderr, "Results:(%s,%s,%d,%d,%s)",
cmd->sender.hostname,
cmd->receiver.hostname,
cmd->sender.port,
cmd->receiver.port,
(cmd->transport==TCP)?"TCP":"UDP")
);
if (send_request(cmd->sender.fd, NORMAL) == -1) {
error(cmd, SEND, ABNORMAL, msg);
cmd->sender.status = S_ERROR;
safe_exit();
} else {
cmd->sender.status = S_NORMAL;
}
if (send_request(cmd->receiver.fd, NORMAL) == -1) {
error(cmd, RECEIVE, ABNORMAL, msg);
cmd->receiver.status = S_ERROR;
safe_exit();
} else {
cmd->receiver.status = S_NORMAL;
}
if (recv_result(cmd) != NORMAL) {
fprintf(stderr, "Receiving Error\n");
cmd->receiver.status = S_ERROR;
safe_exit();
}
close(cmd->sender.fd);
cmd->sender.status = S_CLOSE;
close(cmd->receiver.fd);
cmd->receiver.status = S_CLOSE;
DEBUGMSG(0, ":Received\n");
}
DEBUGMSG(1, "RECEIVE RESULT: Normal END\n");
DEBUGMSG(0, "DBSC: Normal END.\n");
exit(0);
}
/*****************************************************************
* Send Module
*****************************************************************/
/*
* Send origin time
*/
void send_origin_time(fd, origin_time)
int fd;
struct timeval origin_time;
{
struct timeval net_tv;
net_tv.tv_sec = htonl(origin_time.tv_sec);
net_tv.tv_usec = htonl(origin_time.tv_usec);
send(fd, (void *)&net_tv, sizeof(struct timeval), 0);
}
/*
* Send Request
*/
int send_request(fd, i)
int fd;
int i;
{
int net;
net = htonl(i);
if (send(fd, (void *)&net, sizeof(net), 0) != sizeof(i))
return -1;
else
return 1;
}
/*
* set send or recv
*/
struct send_recv *set_send_recv(cmd, serverflg)
struct scan_cmd *cmd;
int serverflg;
{
if (serverflg == SERVER ) {
if (cmd->serverflg == SEND)
return &(cmd->sender);
else
return &(cmd->receiver);
} else {
if (cmd->serverflg == SEND)
return &(cmd->receiver);
else
return &(cmd->sender);
}
}
/*
* Which is send or recv?
*/
int is_send_recv(cmd, serverflg)
struct scan_cmd *cmd;
int serverflg;
{
if (serverflg == SERVER) {
if (cmd->serverflg == SEND)
return SEND;
else
return RECEIVE;
} else {
if(cmd->serverflg == SEND)
return RECEIVE;
else
return SEND;
}
}
/*
* DBSC -> DBSD send_cmd()
*
* DBSD -> DBSC
*
* Send_Command
*
* send_cmd
* recv status
* check time synchronization
*/
void send_command(cmd, port, serverflg)
struct scan_cmd *cmd;
int port;
int serverflg;
{
struct send_recv *sr;
struct timeval current_time;
struct timezone tzp;
char msg[CHAR_ARRAY];
double d_time, t1, t2;
extern struct scan_cmd *scan_cmd;
int e;
SIGNAL_INIT;
gettimeofday(¤t_time, &tzp);
t1 = timeval2double(¤t_time);
/* Send Command to Server */
DEBUGMSG(2, "SEND_COMMAND\n");
for (cmd = scan_cmd; cmd; cmd = cmd->next) {
sr = set_send_recv(cmd, serverflg);
BEGIN_CRITICAL_REGION;
sr->fd = tcp_init_client(sr->hostname_cmd, port);
sr->status = S_CONNECT;
END_CRITICAL_REGION;
send_cmd(sr->fd, cmd, is_send_recv(cmd, serverflg));
}
/* Receive Status from Server */
DEBUGMSG(2, "RECEIVE_STATUS\n");
for (cmd = scan_cmd; cmd; cmd = cmd->next) {
sr = set_send_recv(cmd, serverflg);
if ((e = receive_status(sr->fd, msg)) != NORMAL) {
error(cmd, is_send_recv(cmd, serverflg), e, msg);
safe_exit();
}
gettimeofday(¤t_time, &tzp);
t2 = timeval2double(¤t_time);
d_time = atof(msg);
DEBUGMSG2(2, fprintf(stderr, "DBSD TIME=(%f) DBSC TIME=(%f, %f)\n", d_time, t1, t2));
DEBUGMSG2(1, fprintf(stderr, "TIME DIFF=(%f <= TIME <= %f)\n", t1 - d_time, t2 - d_time));
if (t1 - MAX_TIME_SYNC > d_time || t2 + MAX_TIME_SYNC < d_time) {
error(cmd, is_send_recv(cmd, serverflg), TIMESYNC, "No time sync\nYou should check NTP\n");
safe_exit();
}
if (t1 - WARN_TIME_SYNC > d_time || t2 + WARN_TIME_SYNC < d_time) {
DEBUGMSG2(0,
fprintf(stderr, "WARNING: Host '%s' may be out of time synchronization. You should check NTP.\n",
sr->hostname)
);
}
if (serverflg == CLIENT) {
DEBUGMSG2(0,
fprintf(stderr, "Setup:(%s.%d, %s.%d, %s):End\n",
cmd->sender.hostname,
cmd->sender.port,
cmd->receiver.hostname,
cmd->receiver.port,
(cmd->transport==TCP)?"TCP":"UDP")
);
}
}
}
/*
* Send_cmd
* Translate Network Byte Order and Transmission Command
*/
void send_cmd(fd, cmd, sendflg)
int fd;
struct scan_cmd *cmd;
int sendflg;
{
struct net_cmd net_cmd;
struct net_traffic net_traffic;
struct send_recv *p1, *p2;
struct scan_traffic *traffic;
int i;
if (sendflg == SEND) {
p1 = &(cmd->sender);
p2 = &(cmd->receiver);
} else if (sendflg == RECEIVE) {
p1 = &(cmd->receiver);
p2 = &(cmd->sender);
} else {
fprintf(stderr, "Internal Bug!! (send_cmd)\n");
safe_exit();
}
if (cmd->serverflg == sendflg) {
net_cmd.serverflg = htonl((u_int)SERVER);
} else {
net_cmd.serverflg = htonl((u_int)CLIENT);
}
/*
* Send Commands
*/
strcpy(net_cmd.dsthostname, p2->hostname);
strcpy(net_cmd.srchostname, p1->hostname);
net_cmd.transport = htonl((u_int)cmd->transport);
net_cmd.sendflg = htonl((u_int)sendflg);
net_cmd.source_port = htonl((u_int)p1->port);
net_cmd.dest_port = htonl((u_int)p2->port);
net_cmd.send_buff = htonl((u_int)p1->send_buff);
net_cmd.recv_buff = htonl((u_int)p1->recv_buff);
net_cmd.no_delay = htonl((u_int)p1->no_delay);
net_cmd.mss = htonl((u_int)p1->mss);
net_cmd.so_debug = htonl((u_int)p1->so_debug);
net_cmd.tcp_trace = htonl((u_int)p1->tcp_trace);
net_cmd.record_buff = htonl((u_int)p1->record_buff);
net_cmd.trace_buff = htonl((u_int)p1->trace_buff);
net_cmd.connection_mode = htonl((u_int)cmd->connection_mode);
net_cmd.traffic_n = htonl((u_int)p1->traffic_n);
net_cmd.mem_align = htonl((u_int)p1->mem_align);
net_cmd.align_offset = htonl((u_int)p1->align_offset);
net_cmd.align_pad = htonl((u_int)p1->align_pad);
net_cmd.send_times = htonl((u_int)cmd->send_times);
net_cmd.total_size = htonl((u_int)cmd->total_size);
net_cmd.total_message = htonl((u_int)cmd->total_message);
net_cmd.start_time.tv_sec = htonl((u_int)cmd->start_time.tv_sec);
net_cmd.start_time.tv_usec = htonl((u_int)cmd->start_time.tv_usec);
net_cmd.end_time.tv_sec = htonl((u_int)cmd->end_time.tv_sec);
net_cmd.end_time.tv_usec = htonl((u_int)cmd->end_time.tv_usec);
DEBUGMSG2(2, fprintf(stderr, "sizeof(struct net_cmd)=%dbyte\n", (int)sizeof(struct net_cmd)));
if (debug >= 2) {
fprintf(stderr, "Command Data --------------------------------------------------\n");
fprintf(stderr, "Send to %s\n", p1->hostname);
fprintf(stderr, "Destination = %-12s %-12s\n", p2->hostname, net_cmd.dsthostname);
fprintf(stderr, "Source = %-12s %-12s\n", p1->hostname, net_cmd.srchostname);
fprintf(stderr, "Protocol = %-12d %-12d\n", cmd->transport, net_cmd.transport);
fprintf(stderr, "Server flag = %-12d %-12d\n", ntohl(net_cmd.serverflg), net_cmd.serverflg);
fprintf(stderr, "Send flag = %-12d %-12d\n", sendflg, net_cmd.sendflg);
fprintf(stderr, "Source Port = %-12d %-12d\n", p1->port, net_cmd.source_port);
fprintf(stderr, "Receive Port = %-12d %-12d\n", p2->port, net_cmd.dest_port);
fprintf(stderr, "Send Times = %-12d %-12d\n", cmd->send_times,net_cmd.send_times);
fprintf(stderr, "Send Buffer = %-12d %-12d\n", p1->send_buff, net_cmd.send_buff);
fprintf(stderr, "Receive Buffer = %-12d %-12d\n", p1->recv_buff, net_cmd.recv_buff);
fprintf(stderr, "Total Size = %-12d %-12d\n", cmd->total_size,net_cmd.total_size);
fprintf(stderr, "Total Message = %-12d %-12d\n", cmd->total_message,net_cmd.total_message);
fprintf(stderr, "TCP No Delay = %-12d %-12d\n", p1->no_delay, net_cmd.no_delay);
fprintf(stderr, "MSS = %-12d %-12d\n", p1->mss, net_cmd.mss);
fprintf(stderr, "So Debug = %-12d %-12d\n", p1->so_debug, net_cmd.so_debug);
fprintf(stderr, "TCP Trace = %-12d %-12d\n", p1->tcp_trace, net_cmd.tcp_trace);
fprintf(stderr, "Traffic_N = %-12d %-12d\n", p1->traffic_n, net_cmd.traffic_n);
fprintf(stderr, "Record Buffer = %-12d %-12d\n", p1->record_buff,net_cmd.record_buff);
fprintf(stderr, "Trace Buffer = %-12d %-12d\n", p1->trace_buff, net_cmd.trace_buff);
fprintf(stderr, "Memory Align = %-12d %-12d\n", p1->mem_align, net_cmd.mem_align);
fprintf(stderr, "Align Offset = %-12d %-12d\n", p1->align_offset,net_cmd.align_offset);
fprintf(stderr, "Align Pad = %-12d %-12d\n", p1->align_pad, net_cmd.align_pad);
fprintf(stderr, "Connection Mode= %-12d %-12d\n", cmd->connection_mode, net_cmd.connection_mode);
fprintf(stderr, "Start Time = (%-12d, %-12d) (%-12d, %-12d)\n",
cmd->start_time.tv_sec, cmd->start_time.tv_usec,
net_cmd.start_time.tv_sec, net_cmd.start_time.tv_usec);
fprintf(stderr, "End time = (%-12d, %-12d) (%-12d, %-12d)\n",
cmd->end_time.tv_sec, cmd->end_time.tv_usec,
net_cmd.end_time.tv_sec, net_cmd.end_time.tv_usec);
fprintf(stderr, "---------------------------------------------------------------\n");
}
send(fd, (void *)&net_cmd, sizeof(struct net_cmd), 0);
/*
* Send Traffic Patterns
*/
traffic = p1->traffic;
for (i=0; i < p1->traffic_n; i++) {
net_traffic.size = htonl(traffic->size);
net_traffic.packet = htonl(traffic->packet);
net_traffic.esleep = htonl((int)(traffic->esleep*(1000.0*1000.0)));
net_traffic.isleep = htonl((int)(traffic->isleep*(1000.0*1000.0)));
if (debug >= 2) {
fprintf(stderr, "Traffic Pattern-----------------------------------------\n");
fprintf(stderr, "SIZE = %-12d %-12d\n", traffic->size, net_traffic.size);
fprintf(stderr, "PAKET = %-12d %-12d\n", traffic->packet, net_traffic.packet);
fprintf(stderr, "ESLEEP = %-12f %-12d\n", traffic->esleep, net_traffic.esleep);
fprintf(stderr, "ISLEEP = %-12f %-12d\n", traffic->isleep, net_traffic.isleep);
fprintf(stderr, "--------------------------------------------------------\n");
}
send(fd, (void *)&net_traffic, sizeof(struct net_traffic), 0);
traffic = traffic->next;
}
}
/*****************************************************************
* Receive Module
*****************************************************************/
/*
* Check Status
*/
int receive_status(fd, msg)
int fd;
char *msg;
{
int net, e, i;
net = e = i =0;
/* Error Number */
RECV(fd, &net, sizeof(net));
e = ntohl(net);
/* Message Length */
RECV(fd, &net, sizeof(net));
i = ntohl(net);
if (i >= CHAR_ARRAY) {
fprintf(stderr, "DBSD Version Mismatch or DBSD Internal Error(%d, %d)\n", e, i);
strcpy(msg, "<null>");
recv(fd, msg, CHAR_ARRAY-1, 0);
msg[CHAR_ARRAY-1]= '\0';
fprintf(stderr, "'%s'\n", msg);
safe_exit();
} else if (i > 0) {
RECV(fd, msg, i); /* Message Strings */
msg[i]= '\0';
} else {
strcpy(msg, "");
}
return e;
}
/*
* Receive Result
*/
int recv_result(cmd)
struct scan_cmd *cmd;
{
struct record_net rds, rdr;
struct tcp_trace_net rts, rtr;
char name[1024];
/*
* Receive RD2
*/
if (cmd->connection_mode == AFTER) {
recv_sub(cmd->sender.fd, &rds);
recv_sub(cmd->receiver.fd, &rdr);
sprintf(name, "%s%s", (char *)cmd->filename, ".c");
write_result(name, &rds, &rdr);
}
/*
* Receive RD
*/
recv_sub(cmd->sender.fd, &rds);
recv_sub(cmd->receiver.fd, &rdr);
sprintf(name, "%s%s", (char *)cmd->filename, ".t");
write_result(name, &rds, &rdr);
/*
* Receive TCP_Trace
*/
if (cmd->sender.tcp_trace == ON) {
recv_tcp_trace(cmd->sender.fd, &rts);
sprintf(name, "%s%s", (char *)cmd->filename, ".td_s");
write_tcp_trace(name, &rts);
}
if (cmd->receiver.tcp_trace == ON) {
recv_tcp_trace(cmd->receiver.fd, &rtr);
sprintf(name, "%s%s", (char *)cmd->filename, ".td_r");
write_tcp_trace(name, &rtr);
}
return NORMAL;
}
/*
* Receive sub
*/
int recv_sub(fd, rd)
int fd;
struct record_net *rd;
{
int net_r, r;
DEBUGMSG(1, "Receive Data:");
RECV(fd, &net_r, sizeof(net_r));
rd->n = ntohl(net_r);
r = rd->n * sizeof(struct record_d_net);
DEBUGMSG2(1,fprintf(stderr, "[%3d * %4d] = %6dbyte ", (int)sizeof(struct record_d_net), rd->n, r));
if (rd->n >= 1) {
if ((rd->d=(struct record_d_net *)malloc(r)) == NULL) {
perror("malloc");
return -1;
}
RECV(fd, rd->d, r);
} else {
rd->d = NULL;
}
DEBUGMSG(1, "Received.\n");
return r;
}
/*
* Write Result
*/
void write_result(name, rds, rdr)
char *name;
struct record_net *rds, *rdr;
{
FILE *fp;
int i, n;
if ((fp=fopen(name, "w")) == NULL) {
char tmp[256];
sprintf(tmp, "fopen '%s'",name);
perror(tmp);
return;
}
DEBUGMSG2(1, fprintf(stderr, "Writing File (%s)... ", name));
n = MAX(rds->n, rdr->n);
DEBUGMSG2(2, fprintf(stderr, "n1=%d, n2=%d, n=%d\n", rds->n, rdr->n, n));
/*
* Write Index which is used by dbs_view:Draw Graph Tool
*/
fprintf(fp, "%10s %10s %13s %10s %10s %13s\n",
"send_sequence",
"send_size",
"send_time",
"recv_sequence",
"recv_size",
"recv_time");
/*
* Write Results
*/
for (i=0; i < n; i++) {
if (i >= rds->n) {
fprintf(fp, "%10s %10s %13s %10d %10d %13.6f\n",
"NA",
"NA",
"NA",
(int)ntohl(rdr->d[i].packet_no),
(int)ntohl(rdr->d[i].packet_size),
(int)ntohl(rdr->d[i].tv_sec) + ntohl(rdr->d[i].tv_usec)/(1000.0*1000.0));
} else if (i >= rdr->n) {
fprintf(fp, "%10d %10d %13.6f %10s %10s %13s\n",
(int)ntohl(rds->d[i].packet_no),
(int)ntohl(rds->d[i].packet_size),
(int)ntohl(rds->d[i].tv_sec) + ntohl(rds->d[i].tv_usec)/(1000.0*1000.0),
"NA",
"NA",
"NA");
} else {
fprintf(fp, "%10d %10d %13.6f %10d %10d %13.6f\n",
(int)ntohl(rds->d[i].packet_no),
(int)ntohl(rds->d[i].packet_size),
(int)ntohl(rds->d[i].tv_sec) + ntohl(rds->d[i].tv_usec)/(1000.0*1000.0),
(int)ntohl(rdr->d[i].packet_no),
(int)ntohl(rdr->d[i].packet_size),
(int)ntohl(rdr->d[i].tv_sec) + ntohl(rdr->d[i].tv_usec)/(1000.0*1000.0));
}
}
fclose(fp);
DEBUGMSG(1, "END.\n");
FREE(rds->d);
FREE(rdr->d);
}
/*****************************************************************
* tcp_trace process
*****************************************************************/
int recv_tcp_trace(fd, rt)
int fd;
struct tcp_trace_net *rt;
{
int tcp_r, r = 0;
DEBUGMSG(1, "TCP Trace: ");
RECV(fd, &tcp_r, sizeof(tcp_r));
rt->n = ntohl(tcp_r);
r = sizeof(struct tcp_trace_d_net) * rt->n;
DEBUGMSG2(1, fprintf(stderr, "[%3d * %4d] = %6dbyte ",
(int)sizeof(struct tcp_trace_d_net), rt->n, r));
if (rt->n >= 1) {
if ((rt->d=(struct tcp_trace_d_net *)malloc(r)) == NULL) {
perror("malloc");
return -1;
}
RECV(fd, rt->d, r);
} else {
rt->d = NULL;
}
DEBUGMSG(1, "Received.\n");
return r;
}
void write_tcp_trace(name, rt)
char *name;
struct tcp_trace_net *rt;
{
FILE *fp[5];
char fname[1024];
int i, th_flags, t_flags, act;
int seq, ack;
for (i=0; i<5; i++) {
sprintf(fname, "%s_%d", name, i);
if ((fp[i]=fopen(fname, "w")) == NULL) {
char tmp[256];
sprintf(tmp, "fopen '%s'",fname);
perror(tmp);
return;
}
}
DEBUGMSG2(1, fprintf(stderr, "Writing File (%s0,1,2,3,4)... ", name));
for (i=0; i<5; i++) {
/*
* Write Index which used by dbs_view:Draw Graph Tool
*/
fprintf(fp[i],"%7s ", "td_time");
fprintf(fp[i],"%3s ", "act");
fprintf(fp[i],"%10s ", "seq");
fprintf(fp[i],"%10s ", "ack");
fprintf(fp[i],"%10s ", "len");
fprintf(fp[i],"%10s ", "th_seq");
fprintf(fp[i],"%10s ", "th_ack");
fprintf(fp[i],"%8s ", "th_flags");
fprintf(fp[i],"%10s ", "t_state");
fprintf(fp[i],"%10s ", "t_rxtshift");
fprintf(fp[i],"%10s ", "t_rxtcur");
fprintf(fp[i],"%10s ", "t_dupacks");
fprintf(fp[i],"%10s ", "t_maxseg");
/* fprintf(fp[i],"%10s ", "t_force");*/
fprintf(fp[i],"%16s ", "t_flags");
fprintf(fp[i],"%10s ", "snd_una");
fprintf(fp[i],"%10s ", "snd_nxt");
fprintf(fp[i],"%10s ", "snd_wl1");
fprintf(fp[i],"%10s ", "snd_wl2");
fprintf(fp[i],"%10s ", "iss");
fprintf(fp[i],"%10s ", "snd_wnd");
fprintf(fp[i],"%10s ", "rcv_wnd");
fprintf(fp[i],"%10s ", "rcv_nxt");
fprintf(fp[i],"%10s ", "irs");
fprintf(fp[i],"%10s ", "rcv_adv");
fprintf(fp[i],"%10s ", "snd_max");
fprintf(fp[i],"%10s ", "snd_cwnd");
fprintf(fp[i],"%10s ", "snd_ssthresh");
fprintf(fp[i],"%10s ", "t_idle");
fprintf(fp[i],"%10s ", "t_rtt");
fprintf(fp[i],"%10s ", "t_rtseq");
fprintf(fp[i],"%10s ", "t_srtt");
fprintf(fp[i],"%10s ", "t_rttvar");
/* fprintf(fp[i],"%10s ", "t_rttmin");*/
fprintf(fp[i],"%10s ", "max_sndwnd");
fprintf(fp[i],"\n");
}
#define TA_INPUT 0
#define TA_OUTPUT 1
#define TA_USER 2
#define TA_RESPOND 3
#define TA_DROP 4
for (i=0; i < rt->n; i++) {
th_flags = ntohl(rt->d[i].th_flags);
t_flags = ntohl(rt->d[i].t_flags),
act = ntohl(rt->d[i].td_act);
if (act >= 5) {
/*
* Internal Error
*/
fprintf(stderr, "ACT ERRROR td_act=%d\n", act);
act=TA_DROP;
}
/*
* Calculate Sequense Number and Acknowledge Number
*/
switch (act) {
case TA_INPUT:
seq = ntohl(rt->d[i].th_seq) - ntohl(rt->d[i].irs);
if ((0x02 & th_flags) != 0) /* SYN */
ack = 0;
else
ack = ntohl(rt->d[i].th_ack) - ntohl(rt->d[i].iss);
break;
case TA_OUTPUT:
seq = ntohl(rt->d[i].th_seq) - ntohl(rt->d[i].iss);
if ((0x02 & th_flags) != 0 ) /* SYN */
ack = 0;
else
ack = ntohl(rt->d[i].th_ack) - ntohl(rt->d[i].irs);
break;
case TA_USER:
case TA_RESPOND:
case TA_DROP:
seq = 0;
ack = 0;
break;
default:
if (act >= 5) {
fprintf(stderr, "ACT ERRROR td_act=%d\n", act);
act=TA_DROP;
}
break;
}
#undef TA_INPUT
#undef TA_OUTPUT
#undef TA_USER
#undef TA_RESPOND
#undef TA_DROP
/*
* Write Results
*/
fprintf(fp[act], "%7.3f ", (double)((int)ntohl((u_int)rt->d[i].td_time))/1000.0 /*-origin*/ );
fprintf(fp[act], "%3u ", act);
fprintf(fp[act], "%10u ", seq); /* XXX calculated by DBSC */
fprintf(fp[act], "%10u ", ack); /* XXX calculated by DBSC */
fprintf(fp[act], "%10u ", ntohl(rt->d[i].len));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].th_seq));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].th_ack));
fprintf(fp[act], " %1u%1u%1u%1u%1u%1u ",
(int)(0x01 & (th_flags >>5)), /* URG */
(int)(0x01 & (th_flags >>4)), /* ACK */
(int)(0x01 & (th_flags >>3)), /* PSH */
(int)(0x01 & (th_flags >>2)), /* RST */
(int)(0x01 & (th_flags >>1)), /* SYN */
(int)(0x01 & (th_flags >>0))); /* FIN */
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_state));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_rxtshift));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_rxtcur));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_dupacks));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_maxseg));
/* fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_force));*/
/* ntohl(rt->d[i].t_flags) */
fprintf(fp[act], "%1u%1u%1u%1u%1u%1u%1u%1u%1u%1u%1u%1u%1u%1u%1u%1u ",
(int)(0x01 & (t_flags >>15)), /* */
(int)(0x01 & (t_flags >>14)), /* */
(int)(0x01 & (t_flags >>13)), /* */
(int)(0x01 & (t_flags >>12)), /* */
(int)(0x01 & (t_flags >>11)), /* */
(int)(0x01 & (t_flags >>10)), /* */
(int)(0x01 & (t_flags >> 9)), /* TF_SACK_PERMIT */
(int)(0x01 & (t_flags >> 8)), /* TF_RCVD_TSTMP */
(int)(0x01 & (t_flags >> 7)), /* TF_REQ_TSTMP */
(int)(0x01 & (t_flags >> 6)), /* TF_RCVD_SCALE */
(int)(0x01 & (t_flags >> 5)), /* TF_REQ_SCALE */
(int)(0x01 & (t_flags >> 4)), /* TF_SENTFIN */
(int)(0x01 & (t_flags >> 3)), /* TF_NOOPT */
(int)(0x01 & (t_flags >> 2)), /* TF_NODELAY */
(int)(0x01 & (t_flags >> 1)), /* TF_DELACK */
(int)(0x01 & (t_flags >> 0))); /* TF_ACKNOW */
fprintf(fp[act], "%10u ", ntohl(rt->d[i].snd_una));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].snd_nxt));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].snd_wl1));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].snd_wl2));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].iss));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].snd_wnd));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].rcv_wnd));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].rcv_nxt));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].irs));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].rcv_adv));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].snd_max));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].snd_cwnd));
fprintf(fp[act], "%12u ", ntohl(rt->d[i].snd_ssthresh));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_idle));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_rtt));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_rtseq));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_srtt));
fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_rttvar));
/* fprintf(fp[act], "%10u ", ntohl(rt->d[i].t_rttmin));*/
fprintf(fp[act], "%10u ", ntohl(rt->d[i].max_sndwnd));
fprintf(fp[act], "\n");
}
for (i=0; i < 5; i++) {
fclose(fp[i]);
}
FREE(rt->d);
DEBUGMSG(1, "END.\n");
}
/*****************************************************************
* Mini Subroutines
*****************************************************************/
void init_scan_cmd(scan_cmd)
struct scan_cmd *scan_cmd;
{
struct scan_cmd *cmd;
for (cmd = scan_cmd; cmd; cmd = cmd->next) {
cmd->sender.fd = -1;
cmd->receiver.fd = -1;
}
}
/*
* Deside the time that is used for origin by DBSD.
*/
void get_origin_time(origin_time)
struct timeval *origin_time;
{
struct timeval current_time;
struct timezone tzp;
static struct timeval offset_time = {(int)START_TIME_OFFSET, (int)(START_TIME_OFFSET*1000000)%1000000};
gettimeofday(¤t_time, &tzp);
timeval_cp(origin_time, ¤t_time);
timeval_add(origin_time, &offset_time);
if (debug >= 2) {
fprintf(stderr, "Current Time = (%-12d, %-12d)\n", current_time.tv_sec, current_time.tv_usec);
fprintf(stderr, "Offset = (%-12d, %-12d)\n", offset_time.tv_sec, offset_time.tv_usec);
fprintf(stderr, "Origin Time = (%-12d, %-12d)\n", origin_time->tv_sec, origin_time->tv_usec);
}
}
/*
* TCP Connection establish for DBSC only.
* Return value: file discripter of the Connection.
*/
int tcp_init_client(remotehost, port)
char *remotehost;
int port;
{
struct sockaddr_in serv_addr;
int fd;
unsigned int tmp;
tmp = inet_addr(remotehost);
#ifndef INADDR_NONE
#define INADDR_NONE (-1)
#endif
if (tmp != (unsigned int) INADDR_NONE) {
serv_addr.sin_addr.s_addr = tmp;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
} else {
struct hostent *hp;
if ((hp = gethostbyname(remotehost)) == NULL) {
char tmp[256];
sprintf(tmp, "TCP gethostbyname '%s'",remotehost);
perror(tmp);
safe_exit();
}
bcopy((char *)hp->h_addr, (char *)&serv_addr.sin_addr, hp->h_length);
serv_addr.sin_family = hp->h_addrtype;
serv_addr.sin_port = htons(port);
}
if ((fd = socket(serv_addr.sin_family, SOCK_STREAM, 0)) < 0) {
perror("TCP socket");
safe_exit();
}
DEBUGMSG2(1, fprintf(stderr, "Connecting to (%s).(%d).....",remotehost, port));
alarm(30);
if (setjmp(env_alrm) == 0) {
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
char tmp[256];
sprintf(tmp, "TCP connect (%s).(%d)",remotehost, port);
perror(tmp);
safe_exit();
}
} else {
char tmp[256];
sprintf(tmp, "TCP connect (%s).(%d)",remotehost, port);
perror(tmp);
safe_exit();
}
alarm(0);
DEBUGMSG(1, "Connected.\n");
return fd;
}
void tcp_init_client_timeout(signo)
int signo;
{
longjmp(env_alrm, 1);
}
/*****************************************************************
* dbsc error routine
*****************************************************************/
void error(cmd, sr, e, msg)
struct scan_cmd *cmd;
int sr;
int e;
char *msg;
{
struct send_recv *p1, *p2;
if (sr == SEND) {
p1 = &(cmd->sender);
p2 = &(cmd->receiver);
} else if (sr == RECEIVE) {
p1 = &(cmd->receiver);
p2 = &(cmd->sender);
} else {
fprintf(stderr, "\nSorry! DBSC Internal Bug!!\n");
}
fprintf(stderr, "\n");
fprintf(stderr, "---- Error Messages ---------------------------------------------\n");
fprintf(stderr, "DBSC Version %d.%d%s",
DBS_MAJOR_VERSION, DBS_MINOR_VERSION, DBS_PATCH_VERSION);
fprintf(stderr, "Hostname = %-16s \n", p1->hostname);
if (NORMAL <= e && e <= INTERNALERROR)
fprintf(stderr, "\"%s\"\n", errmsg[e]);
else
fprintf(stderr, "error=%d\n", e);
fprintf(stderr, "%s\n", msg);
if (e == INTERNALERROR) {
fprintf(stderr, "*****************************************************************\n");
fprintf(stderr, "*** Could you send the command file, the error messages ***\n");
fprintf(stderr, "*** and the information about your environment ***\n");
fprintf(stderr, "*** to yukio-m@is.aist-nara.ac.jp? ***\n");
fprintf(stderr, "*****************************************************************\n");
}
fprintf(stderr, "-----------------------------------------------------------------\n");
fprintf(stderr, "Source = %-16s ", p1->hostname);
fprintf(stderr, "Destination = %-16s\n", p2->hostname);
fprintf(stderr, "Source Port = %-16d ", p1->port);
fprintf(stderr, "Dest Port = %-16d\n", p2->port);
fprintf(stderr, "Protocol = %-16s\n", (cmd->transport==TCP)?"TCP":"UDP");
switch (e) {
case TCPNODELAY:
fprintf(stderr, "TCP No Delay = %-16s\n", (p1->no_delay==ON)?"ON":"OFF");
break;
case TCPDEBUG:
case SODEBUG:
fprintf(stderr, "TCP Trace = %-16s", (p1->tcp_trace==ON)?"ON":"OFF");
fprintf(stderr, "So Debug = %-16s\n", (p1->so_debug==ON)?"ON":"OFF");
break;
case TCPMAXSEG:
fprintf(stderr, "MSS = %-16d ", p1->mss);
break;
case SOSNDBUF:
case SORCVBUF:
(p1->send_buff > 0)?fprintf(stderr, "Send Buffer = %-16d ", p1->send_buff):0;
(p1->recv_buff > 0)?fprintf(stderr, "Receive Buffer = %-16d\n", p1->recv_buff):0;
break;
case MALLOC:
fprintf(stderr, "Total Size = %-16d ", cmd->total_size);
fprintf(stderr, "Total Message = %-16d\n", cmd->total_message);
fprintf(stderr, "Record Buffer = %-16d ", p1->record_buff);
fprintf(stderr, "Trace Buffer = %-16d\n", p1->trace_buff);
fprintf(stderr, "Memory Align = %-16d ", p1->mem_align);
fprintf(stderr, "Align Offset = %-16d\n", p1->align_offset);
fprintf(stderr, "Align Pad = %-16d\n", p1->align_pad);
fprintf(stderr, "Traffic_N = %-16d\n", p1->traffic_n);
fprintf(stderr, "Send Times = %-16d ", cmd->send_times);
break;
case TIME:
case TIMESYNC:
case TIMEOUT:
fprintf(stderr, "Start Time = %-16f ", (double)cmd->start_time.tv_sec+(double)cmd->start_time.tv_usec/(1000.0*1000.0));
fprintf(stderr, "End time = %-16f\n", (double)cmd->end_time.tv_sec +(double)cmd->end_time.tv_usec/(1000.0*1000.0));
break;
case CONNECT:
case ACCESSDENY:
fprintf(stderr, "Server flag = %-16s ", (cmd->serverflg==SERVER)?"SERVER":"CLIENT");
fprintf(stderr, "Connection Mode= %-16s\n", (cmd->connection_mode==AFTER)?"AFTER":"BEFORE");
break;
}
fprintf(stderr, "-----------------------------------------------------------------\n");
}
/*****************************************************************
* Signal Handlers
*****************************************************************/
#define CLOSE(FD) if((FD)!=-1 && close(FD)!=-1){shutdown(FD, 1+1);}
void tcp_terminate(fd)
int fd;
{
if (fd != -1) {
char dummy[8];
DEBUGMSG(0, "*");
send(fd, dummy, 8, MSG_OOB);
CLOSE(fd);
} else {
DEBUGMSG(0, "-");
}
}
void safe_exit()
{
extern struct scan_cmd *scan_cmd;
struct scan_cmd *cmd;
struct timeval origin_time;
SIGNAL_INIT;
DEBUGMSG(0, "DBSC: Stopping process");
BEGIN_CRITICAL_REGION;
sleep(1);
DEBUGMSG(0, ".");
sleep(1);
DEBUGMSG(0, ".");
if (scan_cmd != (struct scan_cmd *)NULL) {
for (cmd = scan_cmd; cmd; cmd = cmd->next) {
tcp_terminate(cmd->sender.fd);
tcp_terminate(cmd->receiver.fd);
}
}
DEBUGMSG(0, "\n");
DEBUGMSG(1, "DBSC is stoped.\n");
END_CRITICAL_REGION;
exit(1);
}
#undef TCP_SHUTDOWN
/*
* Signal Handler for SIGINIT
*/
void safe_exit1(signo)
int signo;
{
DEBUGMSG(1, "Interrupting");
DEBUGMSG(0, "\n");
safe_exit();
}
/*
* Signal Handler for SIGPIP
*/
void safe_exit2(signo)
int signo;
{
DEBUGMSG(1, "Pipe is Broken");
DEBUGMSG(0, "\n");
safe_exit();
}
/*
* Help Message
*/
void help(prog)
char *prog;
{
fprintf(stderr, "DBS Version %d.%d%s by yukio-m@is.aist-nara.ac.jp\n", DBS_MAJOR_VERSION, DBS_MINOR_VERSION, DBS_PATCH_VERSION);
fprintf(stderr, "Usage: %s [-p port_number] [-v] [-d] command_file\n", prog);
}
syntax highlighted by Code2HTML, v. 0.9.1