diff options
author | abial <abial@FreeBSD.org> | 1998-08-27 17:38:45 +0000 |
---|---|---|
committer | abial <abial@FreeBSD.org> | 1998-08-27 17:38:45 +0000 |
commit | d38ad5332060d44f048e5b407d0b8e17da9a909c (patch) | |
tree | 3a1c3f90cb24f6c1da60d6fc980d38317610a4c8 /release/picobsd/tinyware/ns | |
download | FreeBSD-src-d38ad5332060d44f048e5b407d0b8e17da9a909c.zip FreeBSD-src-d38ad5332060d44f048e5b407d0b8e17da9a909c.tar.gz |
Initial import of PicoBSD v0.4 tree.
Diffstat (limited to 'release/picobsd/tinyware/ns')
-rw-r--r-- | release/picobsd/tinyware/ns/Makefile | 9 | ||||
-rw-r--r-- | release/picobsd/tinyware/ns/README | 41 | ||||
-rw-r--r-- | release/picobsd/tinyware/ns/ns.c | 628 |
3 files changed, 678 insertions, 0 deletions
diff --git a/release/picobsd/tinyware/ns/Makefile b/release/picobsd/tinyware/ns/Makefile new file mode 100644 index 0000000..b75d813 --- /dev/null +++ b/release/picobsd/tinyware/ns/Makefile @@ -0,0 +1,9 @@ +# $Id: Makefile,v 1.1 1998/08/01 18:26:02 abial Exp $ +# +PROG=ns +SRCS= ns.c +NOMAN=yes + +.include <bsd.prog.mk> + + diff --git a/release/picobsd/tinyware/ns/README b/release/picobsd/tinyware/ns/README new file mode 100644 index 0000000..d81bcd7 --- /dev/null +++ b/release/picobsd/tinyware/ns/README @@ -0,0 +1,41 @@ +Warsaw, 1998.07.20 + + Small replacement for netstat + ----------------------------- + +This program implements some basic functionality subset of normal netstat - +it can display the routing table and protocol statistics. + +Large part of the code dealing with retrieving the routing table via sysctl(3) +was taken from code examples written by Richard Stevens to accompany his +excellent book. + +Usage +----- + + ns [-r] [-s [-p ip|tcp|udp|icmp]] + +where + + -r print routing table (default) + -s print protocol statistics + Options: + -p proto display only statistics related to this + protocol, where 'proto' is one of: + - ip + - tcp + - udp + - icmp + +Bugs +---- + +* The link layer information is still missing. +* 'ns' doesn't resolve IP adresses to names +* well, real netstat provides _much_ more information... but this one needs + to be small, right? :-) + +Andrzej Bialecki +<abial@nask.pl> + +$Id: README,v 1.1 1998/08/19 17:21:50 abial Exp $ diff --git a/release/picobsd/tinyware/ns/ns.c b/release/picobsd/tinyware/ns/ns.c new file mode 100644 index 0000000..6ec15d3 --- /dev/null +++ b/release/picobsd/tinyware/ns/ns.c @@ -0,0 +1,628 @@ +/*- + * Copyright (c) 1998 Andrzej Bialecki + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ns.c,v 1.2 1998/08/09 18:52:07 abial Exp $ + */ + + +/* + * Small replacement for netstat. Uses only sysctl(3) to get the info. + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <err.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/sysctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#include <netinet/icmp_var.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/udp.h> +#include <netinet/udp_var.h> +#include <net/route.h> +#include <net/if_dl.h> +#include <sys/un.h> + +char *progname; +int rflag=1; /* print routing by default */ +int sflag=0; +int pflag=0; + +extern char *optarg; +extern int optind; + +void +usage() +{ + fprintf(stderr,"\n%s [-r | -s] [-p proto]\n",progname); + fprintf(stderr," proto: {ip|tcp|udp|icmp}\n\n"); +} + +int if_num; + +/* + * The following parts related to retrieving the routing table and + * interface information, were borrowed from R. Stevens' code examples + * accompanying his excellent book. Thanks! + */ + +char * +sock_ntop(const struct sockaddr *sa, size_t salen) +{ + char portstr[7]; + static char str[128]; /* Unix domain is largest */ + + switch (sa->sa_family) { + case 255: { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + int i; + + i=0; + while(sin->sin_addr.s_addr & (0x800000>>i)) i++; + sprintf(str,"/%d",i); + return(str); + } + case AF_UNSPEC: + case AF_INET: { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + + if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) + return(NULL); + if (ntohs(sin->sin_port)!=0) { + snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port)); + strcat(str, portstr); + } + if(strcmp(str,"0.0.0.0")==0) sprintf(str,"default"); + return(str); + } + case AF_UNIX: { + struct sockaddr_un *unp = (struct sockaddr_un *) sa; + + /* OK to have no pathname bound to the socket: happens on + every connect() unless client calls bind() first. */ + if (unp->sun_path[0] == 0) + strcpy(str, "(no pathname bound)"); + else + snprintf(str, sizeof(str), "%s", unp->sun_path); + return(str); + } + case AF_LINK: { + struct sockaddr_dl *sdl = (struct sockaddr_dl *) sa; + + if (sdl->sdl_nlen > 0) + snprintf(str, sizeof(str), "%*s", + sdl->sdl_nlen, &sdl->sdl_data[0]); + else + snprintf(str, sizeof(str), "link#%d", sdl->sdl_index); + return(str); + } + default: + snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", + sa->sa_family, salen); + return(str); + } + return (NULL); +} + +char * +Sock_ntop(const struct sockaddr *sa, size_t salen) +{ + char *ptr; + + if ( (ptr = sock_ntop(sa, salen)) == NULL) + err(1,"sock_ntop error"); /* inet_ntop() sets errno */ + return(ptr); +} + + +#define ROUNDUP(a,size) (((a) & ((size)-1))?(1+((a)|((size)-1))):(a)) + +#define NEXT_SA(ap) ap=(struct sockaddr *) \ + ((caddr_t)ap+(ap->sa_len?ROUNDUP(ap->sa_len,sizeof(u_long)):\ + sizeof(u_long))) + +void +get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) +{ + int i; + + for(i=0;i<RTAX_MAX;i++) { + if(addrs &(1<<i)) { + rti_info[i]=sa; + NEXT_SA(sa); + } else + rti_info[i]=NULL; + } +} + +void +get_flags(char *buf, int flags) +{ + if(flags & 0x1) { + strcat(buf,"U"); + } + if(flags & 0x2) { + strcat(buf,"G"); + } + if(flags & 0x4) { + strcat(buf,"H"); + } + if(flags & 0x8) { + strcat(buf,"r"); + } + if(flags & 0x10) { + strcat(buf,"d"); + } + /* + if(flags & 0x20) { + strcat(buf,"mod,"); + } + */ + if(flags & 0x100) { + strcat(buf,"C"); + } + if(flags & 0x400) { + strcat(buf,"L"); + } + if(flags & 0x800) { + strcat(buf,"S"); + } + if(flags & 0x10000) { + strcat(buf,"c"); + } + if(flags & 0x20000) { + strcat(buf,"W"); + } + /* + if(flags & 0x200000) { + strcat(buf,",LOC"); + } + */ + if(flags & 0x400000) { + strcat(buf,"b"); + } + /* + if(flags & 0x800000) { + strcat(buf,",MCA"); + } + */ +} + +int +routing(char *proto) +{ + int mib[6],i=0,rt_len,if_len; + char *rt_buf,*if_buf,*next,*lim; + struct rt_msghdr *rtm; + struct if_msghdr *ifm,**ifm_table; + struct ifa_msghdr *ifam; + struct sockaddr *sa,*sa1,*rti_info[RTAX_MAX],**if_table; + struct rt_metrics rm; + char fbuf[50]; + + /* Get the routing table */ + mib[0]=CTL_NET; + mib[1]=PF_ROUTE; + mib[2]=0; + mib[3]=0; + mib[4]=NET_RT_DUMP; + mib[5]=0; + /* Estimate the size of table */ + if(sysctl(mib,6,NULL,&rt_len,NULL,0)==-1) { + perror("sysctl size"); + exit(-1); + } + if((rt_buf=(char *)malloc(rt_len))==NULL) { + perror("malloc"); + exit(-1); + } + /* Now get it. */ + if(sysctl(mib,6,rt_buf,&rt_len,NULL,0)==-1) { + perror("sysctl get"); + exit(-1); + } + /* Get the interfaces table */ + mib[0]=CTL_NET; + mib[1]=PF_ROUTE; + mib[2]=0; + mib[3]=0; + mib[4]=NET_RT_IFLIST; + mib[5]=0; + /* Estimate the size of table */ + if(sysctl(mib,6,NULL,&if_len,NULL,0)==-1) { + perror("sysctl size"); + exit(-1); + } + if((if_buf=(char *)malloc(if_len))==NULL) { + perror("malloc"); + exit(-1); + } + /* Now get it. */ + if(sysctl(mib,6,if_buf,&if_len,NULL,0)==-1) { + perror("sysctl get"); + exit(-1); + } + lim=if_buf+if_len; + i=0; + for(next=if_buf,i=0;next<lim;next+=ifm->ifm_msglen) { + ifm=(struct if_msghdr *)next; + i++; + } + if_num=i; + if_table=(struct sockaddr **)malloc(i*sizeof(struct sockaddr)); + ifm_table=(struct if_msghdr **)malloc(i*sizeof(struct if_msghdr)); + memset(ifm_table,0,sizeof(ifm_table)); + i=0; + for(next=if_buf;next<lim;next+=ifm->ifm_msglen) { + ifm=(struct if_msghdr *)next; + if_table[i]=(struct sockaddr *)(ifm+1); + ifm_table[i]=ifm; + i++; + } + /* Now dump the routing table */ + printf("\nRouting table:\n"); + printf("--------------\n"); + printf("Destination Gateway Flags Netif Use\n"); + lim=rt_buf+rt_len; + for(next=rt_buf;next<lim;next+=rtm->rtm_msglen) { + rtm=(struct rt_msghdr *)next; + sa=(struct sockaddr *)(rtm+1); + get_rtaddrs(rtm->rtm_addrs,sa,rti_info); + if(rtm->rtm_flags & RTF_WASCLONED) { + if((rtm->rtm_flags & RTF_LLINFO)==0)continue; + } + if((sa=rti_info[RTAX_DST])!=NULL) { + sprintf(fbuf,"%s",sock_ntop(sa,sa->sa_len)); + if(((sa1=rti_info[RTAX_NETMASK])!=NULL) && sa1->sa_family==255) { + strcat(fbuf,sock_ntop(sa1,sa1->sa_len)); + } + printf("%-19s",fbuf); + } + if((sa=rti_info[RTAX_GATEWAY])!=NULL) { + printf("%-19s",sock_ntop(sa,sa->sa_len)); + } + memset(fbuf,0,sizeof(fbuf)); + get_flags(fbuf,rtm->rtm_flags); + printf("%-10s",fbuf); + for(i=0;i<if_num;i++) { + ifm=ifm_table[i]; + if((ifm->ifm_index==rtm->rtm_index) && + (ifm->ifm_data.ifi_type>0)) { + sa=if_table[i]; + break; + } + } + if(ifm->ifm_type==RTM_IFINFO) { + get_rtaddrs(ifm->ifm_addrs,sa,rti_info); + printf(" %s",Sock_ntop(sa,sa->sa_len)); + } else if(ifm->ifm_type==RTM_NEWADDR) { + ifam=(struct ifa_msghdr *)ifm_table[rtm->rtm_index-1]; + sa=(struct sockaddr *)(ifam+1); + get_rtaddrs(ifam->ifam_addrs,sa,rti_info); + printf(" %s",Sock_ntop(sa,sa->sa_len)); + } + printf(" %u",rtm->rtm_use); + printf("\n"); + } + return(0); + +} + +print_ip_stats() +{ + int mib[4],len; + struct ipstat s; + + mib[0]=CTL_NET; + mib[1]=PF_INET; + mib[2]=IPPROTO_IP; + mib[3]=IPCTL_STATS; + len=sizeof(struct ipstat); + if(sysctl(mib,4,&s,&len,NULL,0)<0) { + perror("sysctl"); + return(-1); + } + printf("\nIP statistics:\n"); + printf("--------------\n"); + printf(" %10lu total packets received\n",s.ips_total); + printf("* Packets ok:\n"); + printf(" %10lu fragments received\n",s.ips_fragments); + printf(" %10lu forwarded\n",s.ips_forward); + printf(" %10lu fast forwarded\n",s.ips_fastforward); + printf(" %10lu forwarded on same net (redirect)\n",s.ips_redirectsent); + printf(" %10lu delivered to upper level\n",s.ips_delivered); + printf(" %10lu total ip packets generated here\n",s.ips_localout); + printf(" %10lu total packets reassembled ok\n",s.ips_reassembled); + printf(" %10lu total datagrams successfully fragmented\n",s.ips_fragmented); + printf(" %10lu output fragments created\n",s.ips_ofragments); + printf(" %10lu total raw IP packets generated\n",s.ips_rawout); + printf("\n* Bad packets:\n"); + printf(" %10lu bad checksum\n",s.ips_badsum); + printf(" %10lu too short\n",s.ips_tooshort); + printf(" %10lu not enough data (too small)\n",s.ips_toosmall); + printf(" %10lu more data than declared in header\n",s.ips_badhlen); + printf(" %10lu less data than declared in header\n",s.ips_badlen); + printf(" %10lu fragments dropped (dups, no mbuf)\n",s.ips_fragdropped); + printf(" %10lu fragments timed out in reassembly\n",s.ips_fragtimeout); + printf(" %10lu received for unreachable dest.\n",s.ips_cantforward); + printf(" %10lu unknown or unsupported protocol\n",s.ips_noproto); + printf(" %10lu lost due to no bufs etc.\n",s.ips_odropped); + printf(" %10lu couldn't fragment (DF set, etc.)\n",s.ips_cantfrag); + printf(" %10lu error in IP options processing\n",s.ips_badoptions); + printf(" %10lu dropped due to no route\n",s.ips_noroute); + printf(" %10lu bad IP version\n",s.ips_badvers); + printf(" %10lu too long (more than max IP size)\n",s.ips_toolong); + printf(" %10lu multicast for unregistered groups\n",s.ips_notmember); +} + +print_tcp_stats() +{ + int mib[4],len; + struct tcpstat s; + + mib[0]=CTL_NET; + mib[1]=PF_INET; + mib[2]=IPPROTO_TCP; + mib[3]=TCPCTL_STATS; + len=sizeof(struct tcpstat); + if(sysctl(mib,4,&s,&len,NULL,0)<0) { + perror("sysctl"); + return(-1); + } + printf("\nTCP statistics:\n"); + printf("---------------\n"); + printf("* Connections:\n"); + printf(" %10lu initiated\n",s.tcps_connattempt); + printf(" %10lu accepted\n",s.tcps_accepts); + printf(" %10lu established\n",s.tcps_connects); + printf(" %10lu dropped\n",s.tcps_drops); + printf(" %10lu embryonic connections dropped\n",s.tcps_conndrops); + printf(" %10lu closed (includes dropped)\n",s.tcps_closed); + printf(" %10lu segments where we tried to get RTT\n",s.tcps_segstimed); + printf(" %10lu times RTT successfully updated\n",s.tcps_rttupdated); + printf(" %10lu delayed ACKs sent\n",s.tcps_delack); + printf(" %10lu dropped in rxmt timeout\n",s.tcps_timeoutdrop); + printf(" %10lu retrasmit timeouts\n",s.tcps_rexmttimeo); + printf(" %10lu persist timeouts\n",s.tcps_persisttimeo); + printf(" %10lu keepalive timeouts\n",s.tcps_keeptimeo); + printf(" %10lu keepalive probes sent\n",s.tcps_keepprobe); + printf(" %10lu dropped in keepalive\n",s.tcps_keepdrops); + + printf("* Packets sent:\n"); + printf(" %10lu total packets sent\n",s.tcps_sndtotal); + printf(" %10lu data packets sent\n",s.tcps_sndpack); + printf(" %10lu data bytes sent\n",s.tcps_sndbyte); + printf(" %10lu data packets retransmitted\n",s.tcps_sndrexmitpack); + printf(" %10lu data bytes retransmitted\n",s.tcps_sndrexmitbyte); + printf(" %10lu ACK-only packets sent\n",s.tcps_sndacks); + printf(" %10lu window probes sent\n",s.tcps_sndprobe); + printf(" %10lu URG-only packets sent\n",s.tcps_sndurg); + printf(" %10lu window update-only packets sent\n",s.tcps_sndwinup); + printf(" %10lu control (SYN,FIN,RST) packets sent\n",s.tcps_sndctrl); + printf("* Packets received:\n"); + printf(" %10lu total packets received\n",s.tcps_rcvtotal); + printf(" %10lu packets in sequence\n",s.tcps_rcvpack); + printf(" %10lu bytes in sequence\n",s.tcps_rcvbyte); + printf(" %10lu packets with bad checksum\n",s.tcps_rcvbadsum); + printf(" %10lu packets with bad offset\n",s.tcps_rcvbadoff); + printf(" %10lu packets too short\n",s.tcps_rcvshort); + printf(" %10lu duplicate-only packets\n",s.tcps_rcvduppack); + printf(" %10lu duplicate-only bytes\n",s.tcps_rcvdupbyte); + printf(" %10lu packets with some duplicate data\n",s.tcps_rcvpartduppack); + printf(" %10lu duplicate bytes in partially dup. packets\n",s.tcps_rcvpartdupbyte); + printf(" %10lu out-of-order packets\n",s.tcps_rcvoopack); + printf(" %10lu out-of-order bytes\n",s.tcps_rcvoobyte); + printf(" %10lu packets with data after window\n",s.tcps_rcvpackafterwin); + printf(" %10lu bytes received after window\n",s.tcps_rcvbyteafterwin); + printf(" %10lu packets received after 'close'\n",s.tcps_rcvafterclose); + printf(" %10lu window probe packets\n",s.tcps_rcvwinprobe); + printf(" %10lu duplicate ACKs\n",s.tcps_rcvdupack); + printf(" %10lu ACKs for unsent data\n",s.tcps_rcvacktoomuch); + printf(" %10lu ACK packets\n",s.tcps_rcvackpack); + printf(" %10lu bytes ACKed by received ACKs\n",s.tcps_rcvackbyte); + printf(" %10lu window update packets\n",s.tcps_rcvwinupd); + printf(" %10lu segments dropped due to PAWS\n",s.tcps_pawsdrop); + printf(" %10lu times header predict ok for ACKs\n",s.tcps_predack); + printf(" %10lu times header predict ok for data packets\n",s.tcps_preddat); + printf(" %10lu PCB cache misses\n",s.tcps_pcbcachemiss); + printf(" %10lu times cached RTT in route updated\n",s.tcps_cachedrtt); + printf(" %10lu times cached RTTVAR updated\n",s.tcps_cachedrttvar); + printf(" %10lu times ssthresh updated\n",s.tcps_cachedssthresh); + printf(" %10lu times RTT initialized from route\n",s.tcps_usedrtt); + printf(" %10lu times RTTVAR initialized from route\n",s.tcps_usedrttvar); + printf(" %10lu times ssthresh initialized from route\n",s.tcps_usedssthresh); + printf(" %10lu timeout in persist state\n",s.tcps_persistdrop); + printf(" %10lu bogus SYN, e.g. premature ACK\n",s.tcps_badsyn); + printf(" %10lu resends due to MTU discovery\n",s.tcps_mturesent); + printf(" %10lu listen queue overflows\n",s.tcps_listendrop); +} + +print_udp_stats() +{ + int mib[4],len; + struct udpstat s; + + mib[0]=CTL_NET; + mib[1]=PF_INET; + mib[2]=IPPROTO_UDP; + mib[3]=UDPCTL_STATS; + len=sizeof(struct udpstat); + if(sysctl(mib,4,&s,&len,NULL,0)<0) { + perror("sysctl"); + return(-1); + } + printf("\nUDP statistics:\n"); + printf("---------------\n"); + printf("* Packets received:\n"); + printf(" %10lu total input packets\n",s.udps_ipackets); + printf(" %10lu packets shorter than header (dropped)\n",s.udps_hdrops); + printf(" %10lu bad checksum\n",s.udps_badsum); + printf(" %10lu data length larger than packet\n",s.udps_badlen); + printf(" %10lu no socket on specified port\n",s.udps_noport); + printf(" %10lu of above, arrived as broadcast\n",s.udps_noportbcast); + printf(" %10lu not delivered, input socket full\n",s.udps_fullsock); + printf(" %10lu packets missing PCB cache\n",s.udpps_pcbcachemiss); + printf(" %10lu packets not for hashed PCBs\n",s.udpps_pcbhashmiss); + printf("* Packets sent:\n"); + printf(" %10lu total output packets\n",s.udps_opackets); + printf(" %10lu output packets on fast path\n",s.udps_fastout); +} + +char *icmp_names[]={ + "echo reply", + "#1", + "#2", + "destination unreachable", + "source quench", + "routing redirect", + "#6", + "#7", + "echo", + "router advertisement", + "router solicitation", + "time exceeded", + "parameter problem", + "time stamp", + "time stamp reply", + "information request", + "information request reply", + "address mask request", + "address mask reply", +}; + +print_icmp_stats() +{ + int mib[4],len,i; + struct icmpstat s; + + mib[0]=CTL_NET; + mib[1]=PF_INET; + mib[2]=IPPROTO_ICMP; + mib[3]=ICMPCTL_STATS; + len=sizeof(struct icmpstat); + if(sysctl(mib,4,&s,&len,NULL,0)<0) { + perror("sysctl"); + return(-1); + } + printf("\nICMP statistics:\n"); + printf("----------------\n"); + printf("* Output histogram:\n"); + for(i=0;i<(ICMP_MAXTYPE+1);i++) { + if(s.icps_outhist[i]>0) + printf("\t%10lu %s\n", + s.icps_outhist[i],icmp_names[i]); + } + printf("* Input histogram:\n"); + for(i=0;i<(ICMP_MAXTYPE+1);i++) { + if(s.icps_inhist[i]>0) + printf("\t%10lu %s\n", + s.icps_inhist[i],icmp_names[i]); + } + printf("* Other stats:\n"); + printf(" %10lu calls to icmp_error\n",s.icps_error); + printf(" %10lu no error 'cuz old ip too short\n",s.icps_oldshort); + printf(" %10lu no error 'cuz old was icmp\n",s.icps_oldicmp); + + printf(" %10lu icmp code out of range\n",s.icps_badcode); + printf(" %10lu packets shorter than min length\n",s.icps_tooshort); + printf(" %10lu bad checksum\n",s.icps_checksum); + printf(" %10lu calculated bound mismatch\n",s.icps_badlen); + printf(" %10lu number of responses\n",s.icps_reflect); + printf(" %10lu broad/multi-cast echo requests dropped\n",s.icps_bmcastecho); + printf(" %10lu broad/multi-cast timestamp requests dropped\n",s.icps_bmcasttstamp); +} + +int +stats(char *proto) +{ + if(pflag) { + if(proto==NULL) { + fprintf(stderr,"Option '-p' requires paramter.\n"); + usage(); + exit(-1); + } + if(strcmp(proto,"ip")==0) print_ip_stats(); + if(strcmp(proto,"icmp")==0) print_icmp_stats(); + if(strcmp(proto,"udp")==0) print_udp_stats(); + if(strcmp(proto,"tcp")==0) print_tcp_stats(); + return(0); + } + print_ip_stats(); + print_icmp_stats(); + print_udp_stats(); + print_tcp_stats(); + return(0); +} + +int +main(int argc, char *argv[]) +{ + char c; + char *proto=NULL; + + progname=argv[0]; + + while((c=getopt(argc,argv,"rsp:"))!=-1) { + switch(c) { + case 'r': + rflag++; + break; + case 's': + sflag++; + rflag=0; + break; + case 'p': + pflag++; + proto=optarg; + break; + case '?': + default: + usage(); + exit(0); + break; + } + } + argc-=optind; + if(argc>0) { + usage(); + exit(-1); + } + if(rflag) { + routing(proto); + } else { + stats(proto); + } + exit(0); +} |