/*************************************************************************** * 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: * URL: * 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 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if (!defined(BSD) || (BSD < 199306)) #include #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, ""); 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); }