bdgutil/ 40775 423 0 0 6106122302 11004 5ustar luigiwheelbdgutil/pcbridged.c100664 423 0 44222 5714411523 13226 0ustar luigiwheel/* * PCbridge managing daemon. * taken from bootpd sources * Options are: * * -b print data in format suitable for machine interpretation * eth_port time ctr# count * -c command send a command * 0 = dump data segment (256 bytes) * 1 = dump filtering table (256 bytes) * 2 = flush filtering table * -d increase debugging verbosity * -e ethaddr send the offset corresponding to ethaddr (for cmd 1) * -l filename log data to file * -o offset send offset (for cmd 0 and 1) * -p i print entry i (i=0..7) * -s use as standalone, otherwise use with inetd * -s is useless at the moment * -t get traffic data * -v field show only deltas for one field */ #define MYNET 0xffffffff /* insert here you net. broadcast address */ #include #include #include #include #include #include #include #include #ifdef SUNOS40 # include # include #endif #include #include #include #include #include #include #include #if 1 /* #ifdef SYSLOG */ # include #endif /* * Externals, forward declarations, and global variables */ #define byte char #define TRUE 1 #define FALSE 0 #define MAXHADDRLEN 6 #define MAXPORTS 5 #define NUMCOUNTERS 8 struct bdg_if_addr { unsigned char a[8]; }; struct counter { unsigned char ct[8]; }; struct filters { char mask[6]; }; /*** all data here are in little-endian format ***/ struct pcbridge_data { char magic[16]; char if_found[8]; struct bdg_if_addr if_addr[8]; struct counter stat[3+MAXPORTS*NUMCOUNTERS]; short video_seg; char loop_counters[8]; unsigned char filt[16*6+2]; short table_data_off; struct bdg_if_addr table[64]; }; #define MIN_SIZE (sizeof(struct pcbridge_data)-8-16*6-2-2-512) struct bridges { unsigned char hwaddr[6]; char *bdg_name; char *port_name; long last_rx; long last_time; } known_bridges[1024]; int n_known_bridges=0; void usage(); void report(); void readtable(); void cleanup(); /* * IP port numbers for client and server obtained from /etc/services */ #define PCBRIDGE_SPORT 2299 #define PCBRIDGE_CPORT 2298 u_short pcbridge_port; struct servent *servp; /* * Internet socket and interface config structures */ unsigned thecommand=0xff; unsigned short theoffset=0; struct sockaddr_in s_sin; struct sockaddr_in cmdsock; struct sockaddr_in from; /* Packet source */ struct ifreq ifreq[10]; /* Holds interface configuration */ struct ifconf ifconf; /* Int. config ioctl block (pnts to ifreq) */ /* * General */ char *logfilename=NULL; FILE *logfile=NULL; int print_filters=TRUE; int print_table=FALSE; int machine_data=FALSE; /* -b option */ int traffic=FALSE; int standalone = TRUE; /* set to FALSE to use with inetd */; int debug = 3; /* Debugging flag */ int s; /* Socket file descriptor */ byte buf[2048]; /* Receive packet buffer */ int pr_flags[8]={TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE}; #define print_rxp print_flags[0] #define print_fwd print_flags[1] #define print_txp print_flags[2] #define print_drop print_flags[3] #define print_ldrop print_flags[4] #define print_rxbdg print_flags[5] #define print_rxbytes print_flags[6] #define print_badrx print_flags[7] unsigned long thecounter(struct counter i) { return ( ( ( ( (i.ct[5]<<8)+i.ct[4])<<8) + i.ct[3])<<8) + i.ct[2]; } unsigned long thetime(struct counter i) { return ( (i.ct[2] & 0xf) + 10*( (i.ct[2] & 0xf0)>>4) + 60* ( (i.ct[3] & 0xf) + 10*( (i.ct[3] & 0xf0)>>4) + 60* ( (i.ct[4] & 0xf) + 10*( (i.ct[4] & 0xf0)>>4) ) ) ); } char *stat_string[]= { "Rx packets", "Fwd all ", "Tx packets", "Dropped ", "Local drop", "Rx bridge ", "Rx bytes ", "Bad rx pkt", NULL}; int addrcmp(char *a, unsigned char *ha) { int i; char *b= (char *)ha; for (i=0;i<6;i++) if (*a++ != *b++) return 0 ; return 1; } int dump_packet(struct pcbridge_data *p, int n) { int i,j,stat; char string[80]; struct bdg_if_addr h, k; char *name=NULL, *port=NULL; char *port_names[MAXPORTS]; unsigned char *q; if (traffic) { /* must dump traffic data */ for (i=1;i<=MAXPORTS;i++) { /* scan all the ports */ if (p->if_found[i]) { /* only use the active ones */ unsigned long new_rx=thecounter(p->stat[2+5*6+i]); unsigned long new_time=thetime(p->stat[2]); k= (p->if_addr[1]); h= (p->if_addr[i]); for (j=0;jstat[2]), i, h.a[0],h.a[1],h.a[2],h.a[3],h.a[4],h.a[5], k.a[0],k.a[1],k.a[2],k.a[3],k.a[4],k.a[5], new_rx, (new_rx - known_bridges[j].last_rx) %0x1000000L, new_time - known_bridges[j].last_time ); fflush(logfile? logfile:stdout); known_bridges[j].last_rx= new_rx; known_bridges[j].last_time=new_time; } } return; } /* printf("Packet size %d\n",n); */ j=p->if_found[0]; h= (p->if_addr[j]); for (i=0;imagic,name, thecounter(p->stat[0]), thecounter(p->stat[1]),thecounter(p->stat[2])); fflush(stdout); for (i=1;i<=MAXPORTS;i++) { port_names[i-1]="???"; if (p->if_found[i]) { h= (p->if_addr[i]); for (j=0;jif_found[0] ? '*':' ', port_names[i-1], i, h.a[0],h.a[1],h.a[2],h.a[3],h.a[4],h.a[5], string); fflush(stdout); } } if (print_filters) { for (q= &(p->filt[0]); *q; q += 6) { printf("[%04x..%04x[: %s outside, %s inside\n", q[2]+q[3]*256, q[4]+q[5]*256, (q[0]==1 ? "keep" : (q[0]==2 ? "discard" : "--")), (q[1]==1 ? "keep" : (q[1]==2 ? "discard" : "--")) ); } fflush(stdout); } printf("\n%10s",""); for (j=0;j<5; j++) { printf("%14s",p->if_found[j+1]?port_names[j]:""); } printf("\n%10s",""); for (j=0;j<5; j++) { printf(p->if_found[j+1]?" == Port %d ==":"",j+1); } printf("\n"); for (i=0;i<8;i++) { if (pr_flags[i]) { printf(stat_string[i]); for (j=0;j<5; j++) { if (p->if_found[j+1]) printf("%14u",thecounter(p->stat[3+5*i+j])); else printf("%14s",""); } printf("\n"); } } if (print_table) { unsigned short off=p->table_data_off; printf("Table offset %4x\n",off); for (i=0; i<64;i++) { struct bdg_if_addr bdg; bdg= p->if_addr[p->if_found[0]]; h= (p->table[i]); if ( h.a[6] != 255 ) { printf("[Entry %4d] %02x:%02x:%02x:%02x:%02x:%02x port %d - %d\n", i, h.a[0],h.a[1],h.a[2],h.a[3],h.a[4],h.a[5], h.a[6],h.a[7]); if (logfile) { fprintf(logfile, "IF %02x:%02x:%02x:%02x:%02x:%02x %4x PORT %d %2x SRC %02x:%02x:%02x:%02x:%02x:%02x TIME %6lx\n", h.a[0],h.a[1],h.a[2],h.a[3],h.a[4],h.a[5], off + i*8 - 0x200 /* patch for bad EPROM 2.64 */, h.a[6],h.a[7], bdg.a[0],bdg.a[1],bdg.a[2],bdg.a[3],bdg.a[4],bdg.a[5], thecounter(p->stat[2]) ); fflush(logfile); } } } } printf("\n"); fflush(stdout); } /* * Initialization such as command-line processing is done and then the main * server loop is started. */ main(argc, argv) int argc; char **argv; { struct timeval actualtimeout, *timeout; int n, tolen, fromlen; int nfound, readfds; timeout = &actualtimeout; /* * Read switches. */ for (argc--, argv++; argc > 0; argc--, argv++) { if (argv[0][0] == '-') { switch (argv[0][1]) { case 'b': /* machine data */ machine_data=TRUE; print_table=FALSE; traffic=FALSE; break; case 't': /* traffic */ print_table=FALSE; traffic=TRUE; break; case 'c': /* command */ argc--; argv++; thecommand=atoi(argv[0]); if (thecommand>3) thecommand=0; break; case 'o': /* offset */ argc--; argv++; sscanf(argv[0],"%i",&theoffset); break; case 'e': /* offset */ {int b2,b3,b4,b5; argc--; argv++; sscanf(argv[0],"%*x:%*x:%x:%x:%x:%x", &b2, &b3, &b4, &b5); theoffset= (((b2 ^ b4) + ((b3 ^ b5)<<8) )<<3) & 0xffff; thecommand=1; print_table=TRUE; } break; case 'l': /* logging */ argc--; argv++; logfilename=argv[0]; logfile=fopen(logfilename,"w+"); if (logfile==NULL) { fprintf(stderr,"Can't open logfile %s\n",logfilename); } break; case 'd': { int i; for (i=0;i<8;i++) pr_flags[i]=TRUE;} debug++; break; case 's': standalone = TRUE; break; default: fprintf(stderr, "pcbridged: unknown switch: -%c\n", argv[0][1]); usage(); break; } } else { usage(); } } if (standalone) { /* * Go into background and disassociate from controlling terminal. */ if (debug < 3) { if (fork()) exit(0); for (n = 0; n < 10; n++) (void) close(n); (void) open("/", O_RDONLY); (void) dup2(0, 1); (void) dup2(0, 2); n = open("/dev/tty", O_RDWR); if (n >= 0) { ioctl(n, TIOCNOTTY, (char *) 0); (void) close(n); } } /* * Nuke any timeout value */ timeout = NULL; } #ifdef SYSLOG /* * Initialize logging. */ #ifndef LOG_CONS #define LOG_CONS 0 /* Don't bother if not defined... */ #endif #ifndef LOG_DAEMON #define LOG_DAEMON 0 #endif openlog("pcbridged", LOG_PID | LOG_CONS, LOG_DAEMON); syslog(LOG_INFO, "%s", Version); #endif readtable(); if (standalone) { /* * Get us a socket. */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { report(LOG_ERR, "socket: %s\n", "can't get socket" ); exit(1); } /* * Get server's listening port number */ servp = getservbyname("pcbridge", "udp"); if (servp) { pcbridge_port = ntohs((u_short) servp->s_port); } else { report(LOG_ERR, "udp/pcbridge: unknown service -- assuming port %d\n", PCBRIDGE_SPORT); pcbridge_port = (u_short) PCBRIDGE_SPORT; } /* * Bind socket to pcbridge port. */ s_sin.sin_family = AF_INET; s_sin.sin_addr.s_addr = INADDR_ANY; s_sin.sin_port = htons(pcbridge_port); if (bind(s, &s_sin, sizeof(s_sin)) < 0) { report(LOG_ERR, "bind: %s\n", "can't bind to pcbridge_port"); exit(1); } } else { /* * Assume socket was passed to us from inetd */ s = 0; tolen = sizeof(s_sin); bzero((char *) &s_sin, tolen); if (getsockname(s, &s_sin, &tolen) < 0) { report(LOG_ERR, "getsockname: %s\n","failed" ); exit(1); } pcbridge_port = ntohs(s_sin.sin_port); } { int c=1; setsockopt(s, SOL_SOCKET, SO_BROADCAST, &c, sizeof(c) ); } /* * Determine network configuration. */ ifconf.ifc_len = sizeof(ifreq); ifconf.ifc_req = ifreq; if ((ioctl(s, SIOCGIFCONF, (caddr_t) &ifconf) < 0) || (ifconf.ifc_len <= 0)) { report(LOG_ERR, "ioctl: %s\n", "failed"); exit(1); } /* * Set up signals to clean up on exit. -mah */ signal(SIGSEGV, cleanup); signal(SIGBUS , cleanup); signal(SIGINT, cleanup); signal(SIGILL, cleanup); signal(SIGQUIT, cleanup); signal(SIGFPE, cleanup); signal(SIGIOT, cleanup); /* * Set up signals to read or dump the table. */ if ((int) signal(SIGHUP, cleanup) < 0) { report(LOG_ERR, "signal: %s\n", "cleanup..."); exit(1); } /*** if necessary, send out command ***/ if (thecommand != 0xff) { sendcmd(thecommand,theoffset); thecommand = 0xff; } /* * Process incoming requests. */ for (;;) { struct pcbridge_data *pcd=(struct pcbridge_data *)buf; readfds = 1 << s; nfound = select(s + 1, &readfds, NULL, NULL, timeout); if (nfound < 0) { if (errno != EINTR) { report(LOG_ERR, "select: %s\n", "not eintr"); } continue; } if (!(readfds & (1 << s))) { report(LOG_INFO, "exiting after %ld minutes of inactivity\n", actualtimeout.tv_sec / 60); exit(0); } fromlen = sizeof(from); n = recvfrom(s, buf, sizeof(buf), 0, &from, &fromlen); if (n <= 0) { continue; } if (n < MIN_SIZE) { if (debug) { report(LOG_INFO, "received short packet\n"); } continue; } dump_packet(pcd,n); /* process data */ } } /* * Print "usage" message and exit */ void usage() { fprintf(stderr, "usage: pcbridged [-d] [-s]\n"); fprintf(stderr, "\t -d\tincrease debug verbosity\n"); fprintf(stderr, "\t -c cmd\tsends cmd to bridges\n"); fprintf(stderr, "\t -o addr\tsends offset to bridges (with -c)\n"); fprintf(stderr, "\t -e ethaddr\tfinds out an ethernet card\n"); fprintf(stderr, "\t -l logfile\tlogs to file\n"); fprintf(stderr, "\t -s\trun standalone (without inetd)\n"); exit(1); } /* * Send a command to the bridge. */ struct bdgcmd { unsigned char magic[4]; /* 'L' 'R' .... */ unsigned short cmd[2]; } thecmd; sendcmd(unsigned char cmd, unsigned short off) { struct bdgcmd *bp = &thecmd; struct in_addr dst; struct sockaddr_in to; thecmd.magic[0]='L'; /* magic string */ thecmd.magic[1]='R'; thecmd.cmd[0]=htons(cmd); thecmd.cmd[1]=htons(off); to = s_sin; to.sin_port = htons(PCBRIDGE_CPORT); dst.s_addr=htonl(MYNET); to.sin_addr = dst; if (sendto(s, bp, sizeof(struct bdgcmd), 0, &to, sizeof(to)) < 0) { fprintf(stderr, "sendto: %s\n", "failed <0"); } } /* * Compare function to determine whether two hardware addresses are * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE * otherwise. * * This function is used when retrieving elements from the hardware address * hash table. */ /* * Convert a hardware address to an ASCII string. */ char *haddrtoa(haddr, htype) register byte *haddr; byte htype; { static char haddrbuf[2 * MAXHADDRLEN + 1]; register char *bufptr; register unsigned count; bufptr = haddrbuf; for (count = MAXHADDRLEN; count > 0; count--) { sprintf(bufptr, "%02X", (unsigned) (*haddr++ & 0xFF)); bufptr += 2; } return (haddrbuf); } /* * This routine reports errors and such via stderr and syslog() if * appopriate. It just helps avoid a lot of "#ifdef SYSLOG" constructs * from being scattered throughout the code. * * The syntax is identical to syslog(3), but %m is not considered special * for output to stderr (i.e. you'll see "%m" in the output. . .). Also, * control strings should normally end with \n since newlines aren't * automatically generated for stderr output (whereas syslog strips out all * newlines and adds its own at the end). */ /*VARARGS2*/ void report(priority, fmt, p0, p1, p2, p3, p4) int priority; char *fmt; { /* * Print the message */ if (debug > 2) { fprintf(stderr, "*** pcbridged: "); fprintf(stderr, fmt, p0, p1, p2, p3, p4); fprintf(stderr, "\n\n"); } #ifdef SYSLOG syslog(priority, fmt, p0, p1, p2, p3, p4); #endif } /* * shutdown the socket on weird signals * otherwise it wont go away on pmaxes * and we get an 'address already in use' on next try * -mah */ void cleanup(sig) int sig; { shutdown(s,2); report(LOG_ERR, "cleanup: got signal %d\n", sig); exit(sig); } int ishex(char c) { if (c>='0' && c<='9') return (c-'0'); else if (c>='a' && c<='f') return (c-'a'+10); else if (c>='A' && c<='F') return (c-'A'+10); else return(-1); } void readtable() { char linebuf[256]; char *p; FILE *f; int i; unsigned char ha[6]; char *bdg_name, *bdg_port; f=fopen("pcbridgetab","r"); if (f==NULL) f=fopen("/etc/pcbridgetab","r"); if (f==NULL) return; while (p=fgets(linebuf,sizeof(linebuf),f)) { while (*p && *p!='#' && *p!='\n') p++; *p='\0'; /* skip comments */ for (p=linebuf;*p && (*p==' ' || *p=='\t'); p++); /* skip blanks */ if (*p) { /* printf("Found %s\n",p); */ for (i=0;i<6;i++) { int c1,c2; c1=ishex(*p++); if (c1<0) { fprintf(stderr, "Invalid first digit (%d) %d\n",i,c1); break; } c2=ishex(*p); if (c2== -1 ) { if (*p!=':' && *p!=' ' && *p!='\t') { fprintf(stderr, "Invalid second digit\n"); break; } else { c2=c1; c1=0; } } else p++; known_bridges[n_known_bridges].hwaddr[i]=c1*16+c2; if (i<5) while (*p && ishex(*p)<0) p++; } if (i==6) { /* successful end */ char *p1; char *p2; while (*p && (*p ==' ' || *p=='\t')) p++; p1=p; while (*p && *p !=' ' && *p!='\t') p++; if (*p) { *p++='\0'; while (*p && (*p ==' ' || *p=='\t')) p++; p2= p; while (*p && *p !=' ' && *p!='\t') p++; *p='\0'; } else p2=NULL; known_bridges[n_known_bridges].bdg_name= (char *)malloc(1+strlen(p1)); strcpy(known_bridges[n_known_bridges].bdg_name,p1); if (p2) { known_bridges[n_known_bridges].port_name= (char *)malloc(1+strlen(p2)); strcpy(known_bridges[n_known_bridges].port_name,p2); } else known_bridges[n_known_bridges].port_name=NULL; /* fprintf(stderr," bdg: %s port: %s\n", known_bridges[n_known_bridges].bdg_name, known_bridges[n_known_bridges].port_name); */ known_bridges[n_known_bridges].last_rx= -1; known_bridges[n_known_bridges].last_time= 0; n_known_bridges++; } } } fclose(f); } bdgutil/pcbridgetab100664 423 0 3034 5551036266 13312 0ustar luigiwheel# Similarly to bootptab and others, this file has the following format # A dash # marks the start of comment # each line is one entry, with three fields # eth_address bridge_name bridge_port # An address can have multiple entries to assign multiple names # # A bridge can respond to the following commands: # # LOCATE -- query to tell which interface # a specific address is on. It requires some work to find out a map, # but in the end it shouldn't be difficult as we have already a tree. # Also serves as a PING # # FLUSH -- request to flush the bridging tables. May help, sometimes. # requires some rights to work on the bridge. # # DUMP -- dump internal tables to the host. As the table is large, # and we don't want to mantain protocols etc. in the bridge, we # may want to dump the table in small pieces, e.g. 512bytes or so, # with the page number specified by the host. # # 00:00:c0:01:ea:65 labinfo interdip 00:00:c0:fe:f2:2f labinfo bartoli # pisolo 00:00:c0:ff:e9:65 labinfo labinfo # r6000 00:00:c0:a1:b0:67 labinfo dec 00:00:c0:96:b0:67 labinfo old_deit 00:00:c0:94:b0:67 chimica deit 00:00:c0:cc:af:67 chimica interdip 00:00:c0:c4:f1:2f pc-uprog port1 00:00:c0:d9:f1:2f pc-uprog port2 00:00:c0:9d:b0:67 cisid risc6000 00:00:c0:a9:b0:67 cisid mac 00:00:c0:90:b0:67 cisid interdip 00:00:c0:c0:a0:63 scale dorsale 00:00:c0:9f:9f:63 scale fastpath 00:00:c0:8e:c4:63 scale rizzo 00:00:c0:c6:a0:63 luise port1 00:00:c0:40:a0:63 luise dorsale 00:00:c0:a5:9f:63 luise port3 00:00:c0:7b:58:69 dsea deit 00:00:c0:da:6e:66 dsea dsea bdgutil/bdgshow100775 423 0 5160 5714431503 12500 0ustar luigiwheel#!/usr/local/bin/wish -f # # get data from pcbridged -t and shows them # set i 0 set w(width) 400 set w(height) 180 set w(min_bw) 1000 ; # less than 1KB/s is not worth resolution. set w(max_bw) 1000000 ; # less than 1KB/s is not worth resolution. set w(yscale) [expr $w(height)*1.0/log($w(max_bw)/$w(min_bw))] set w(bw_10k) [expr $w(yscale)*log(10000.0/$w(min_bw))] set w(bw_100k) [expr $w(yscale)*log(100000.0/$w(min_bw))] set w(color,1) white set w(color,2) red set w(color,3) yellow set w(color,4) green set w(color,5) orange set w(color,bg) black set w(color,font) fixed . configure -background $w(color,bg) proc ini {} { global i set i 0 } proc nuovo {nm} { global i w incr i set w($nm) $i set w(x,$nm) 0 # set w(bw,$nm) 0 frame .f$i -background $w(color,bg) pack .f$i -fill x frame .f$i.l -background $w(color,bg) pack .f$i.l -side left -fill x -expand 1 canvas .f$i.c -width $w(width) -height $w(height) -background black pack .f$i.c -side right -anchor se .f$i.c create line 0 0 [expr $w(width) -1] 0 -fill white .f$i.c create line 0 $w(bw_10k) [expr $w(width) - 1] $w(bw_10k) -fill green .f$i.c create line 0 $w(bw_100k) [expr $w(width) - 1] $w(bw_100k) -fill blue label .f$i.l.l -text "***** Bridge $nm *****" \ -relief raised \ -font $w(color,font) pack .f$i.l.l -side top -anchor nw -fill x for {set idx 1} {$idx < 6} {incr idx} { set w(prevy,$idx,$nm) $w(height) label .f$i.l.l$idx -textvariable w(bw,$idx,$nm) \ -background $w(color,bg) -foreground $w(color,$idx) \ -font $w(color,font) pack .f$i.l.l$idx -side top -anchor nw } } proc processa {a} { global w set idx [lindex $a 3] ; # port index set nm [lindex $a 4] ; # port name -- index is 3 set main_nm [lindex $a 5] ; # main port name -- index is 3 set bw [lindex $a 8] ; # aggregate bandwidth set deltat [lindex $a 9] ; # delta t if [expr $deltat < 1 ] { set deltat 1 } set w(bw,$idx,$main_nm) [format "$nm BW: %6d B/s" [expr $bw / $deltat] ] if [catch {set w($main_nm)}] { nuovo $main_nm } set c .f$w($main_nm).c ; # canvas id. set x $w(x,$main_nm) if [expr $idx == 1 ] { set w(x,$main_nm) [expr ($w(x,$main_nm) + 1) % $w(width)] set x $w(x,$main_nm) $c create line $x 0 $x [expr $w(height)-1] -fill black } set bw [expr $bw / $deltat] if [expr $bw < $w(min_bw) ] { set bw $w(min_bw) } set y [expr $w(height)- $w(yscale)*log(1.0*$bw/$w(min_bw))] $c create line $x [expr $y + 1] $x $y -fill $w(color,$idx) set w(prevy,$idx,$nm) $y } while {[gets stdin a] != -1 } { update processa "$a" } bdgutil/bdgshow1100775 423 0 2305 5714405713 12563 0ustar luigiwheel#!/usr/local/bin/wish -f set i 0 proc ini {} { global i set i 0 } proc nuovo {nm} { global i w set i [expr $i + 1] set w($nm) $i set w(p,$nm) 0 set w(bw,$nm) 0 frame .f$i pack .f$i -fill x frame .f$i.l pack .f$i.l -side left -fill x -expand 1 canvas .f$i.c -width 600 -height 50 -background red pack .f$i.c -side right -anchor se .f$i.c create line 0 0 599 0 -fill white .f$i.c create line 0 25 599 25 -fill green .f$i.c create line 0 49 599 49 -fill blue label .f$i.l.l -text $nm -background black -foreground white pack .f$i.l.l -side top -anchor ne label .f$i.l.l1 -textvariable w(bw,$nm) -background black -foreground white pack .f$i.l.l1 -side top -anchor ne } proc processa {a} { global w set bw [lindex $a 6] set deltat [lindex $a 7] set nm [lindex $a 3] if [expr $deltat < 1 ] { set deltat 1 } set w(bw,$nm) "bw [expr $bw / $deltat] B/s" if [catch {set w($nm)}] { nuovo $nm } set c .f$w($nm).c set x $w(p,$nm) set y [expr 49 - (log ($bw + 1))] $c create line $x 49 $x $y set w(p,$nm) [expr ($x + 1) % 600] } while {[gets stdin a] != -1 } { update processa "$a" } bdgutil/bdgshow.950203100775 423 0 2736 5714407203 13247 0ustar luigiwheel#!/usr/local/bin/wish -f set i 0 set w(width) 400 set w(height) 100 set w(height2) [expr $w(height) / 2] proc ini {} { global i set i 0 } proc nuovo {nm} { global i w set i [expr $i + 1] set w($nm) $i set w(p,$nm) 0 set w(bw,$nm) 0 frame .f$i pack .f$i -fill x frame .f$i.l pack .f$i.l -side left -fill x -expand 1 canvas .f$i.c -width $w(width) -height $w(height) -background red pack .f$i.c -side right -anchor se .f$i.c create line 0 0 [expr $w(width) -1] 0 -fill white .f$i.c create line 0 [expr $w(height2) - 1] \ [expr $w(width) - 1] [expr $w(height2) - 1] -fill green .f$i.c create line 0 [expr $w(height) - 1] \ [expr $w(width) - 1] [expr $w(height) - 1] -fill blue label .f$i.l.l -text $nm -background black -foreground white pack .f$i.l.l -side top -anchor ne label .f$i.l.l1 -textvariable w(bw,$nm) -background black -foreground white pack .f$i.l.l1 -side top -anchor ne } proc processa {a} { global w set bw [lindex $a 6] set nm [lindex $a 3] set deltat [lindex $a 7] if [expr $deltat < 1 ] { set deltat 1 } set w(bw,$nm) "bw [expr $bw / $deltat] B/s" if [catch {set w($nm)}] { nuovo $nm } set c .f$w($nm).c set x $w(p,$nm) set y [expr $w(height)*(1.0- (log ($bw/$deltat + 1))/log(1000000))] $c create line $x [expr $w(height) - 1] $x $y set w(p,$nm) [expr ($x + 1) % $w(width)] } while {[gets stdin a] != -1 } { update processa "$a" }