From 9ef99177bc18fabae3f0ba42a3a88ea9565e63c7 Mon Sep 17 00:00:00 2001 From: Brett Gordon Date: Tue, 24 Jan 2017 10:59:19 -0500 Subject: [PATCH] netd: add ping client (to test raw socks) --- Applications/netd/Makefile.6809 | 3 +- Applications/netd/ping.c | 189 ++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 Applications/netd/ping.c diff --git a/Applications/netd/Makefile.6809 b/Applications/netd/Makefile.6809 index 0ab79718..af4d166a 100644 --- a/Applications/netd/Makefile.6809 +++ b/Applications/netd/Makefile.6809 @@ -16,7 +16,7 @@ CRT0 = ../../Library/libs/crt0_6809.o .SUFFIXES: .c .o SRCS = netd.c uip.c uiplib.c timer.c clock-arch.c uip_arp.c telnet.c lwwire.c -SRCS += echoping.c dig.c gethostbyname.c httpd.c coconic.c +SRCS += echoping.c dig.c gethostbyname.c httpd.c coconic.c ping.c OBJS = $(SRCS:.c=.o) @@ -32,6 +32,7 @@ netd: $(OBJS) $(LINKER) $(LINKER_OPT) -o echoping $(CRT0) echoping.o $(LINKER) $(LINKER_OPT) -o dig $(CRT0) dig.o $(LINKER) $(LINKER_OPT) -o httpd $(CRT0) httpd.o + $(LINKER) $(LINKER_OPT) -o ping $(CRT0) ping.o gethostbyname.o diff --git a/Applications/netd/ping.c b/Applications/netd/ping.c new file mode 100644 index 00000000..4e3e0b01 --- /dev/null +++ b/Applications/netd/ping.c @@ -0,0 +1,189 @@ +/* + A Cheesey ipv4 ping client + + todo: + * add timestamp to packets to measure delta-t + * add time max/min/avg/sdev stats like real ping + * check for endian problems +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "netdb.h" + +#define AF_INET 1 +#define SOCK_RAW 1 + +struct ip { + uint8_t ver; + uint8_t tos; + uint16_t len; + uint16_t id; + uint16_t off; + uint8_t ttl; + uint8_t proto; + uint16_t cksum; + uint32_t src; + uint32_t dest; +}; + +struct icmp { + uint8_t type; + uint8_t code; + uint16_t cksum; + uint16_t id; + uint16_t seq; +}; + +char *data = "FUZIX ping client"; + +#define MAXBUF 256 +int fd; +char buf[MAXBUF]; +struct sockaddr_in addr; +int id; +int seq=0; +int sent=0; +int recv=0; + +void alarm_handler( int signum ){ + return; +} + +void int_handler( int signum ){ + printf("sent %d, recv %d, %d%%\n", + sent, recv, recv*100/sent ); + exit(0); +} + +/* print a IP address */ +void ipprint( uint32_t *a ){ + char *b = (char *)a; + printf("%d.%d.%d.%d", b[0], b[1], b[2], b[3] ); +} + + +/* returns inet chksum */ +uint16_t cksum( char *b, int len ){ + uint16_t sum = 0; + uint16_t t; + char *e = b + len; + b[len] = 0; + while(b < e){ + t = (b[0] << 8) + b[1]; + sum += t; + if(sum < t) sum++; + b += 2; + } + return ~sum; +} + + +/* sends ping to remote */ +void send( void ){ + struct icmp *i = (struct icmp *)buf; + int l = strlen(data) + 8; + memset( buf, 0, MAXBUF); + i->type = 8; // echo request + i->id = id; + i->seq = seq; + strcpy( &buf[8], data ); + i->cksum = cksum(buf, l); + write(fd, buf, l); + sent++; + seq++; +} + +my_open( int argc, char *argv[]){ + struct hostent *h; + + h=gethostbyname( argv[1] ); + if( ! h ){ + fprintf( stderr, "cannot resolve hostname\n" ); + exit(1); + } + memcpy( &addr.sin_addr.s_addr, h->h_addr_list[0], 4 ); + + fd = socket(AF_INET, SOCK_RAW, 1); + if (fd < 0) { + perror("af_inet sock_stream 0"); + exit(1); + } + + /* fuzix raw sockets (for now) repurposes the connect() + address struct to pass it's protocol number + */ + addr.sin_port = 1; + addr.sin_family = AF_INET; + if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("connect"); + exit(1); + } +} + + +int main( int argc, char *argv[] ){ + uint16_t c = 0; + int x,i; + time_t t; + struct icmp *icmpbuf; + struct ip *ipbuf; + struct ip *ipbuf2; + + srand(time(&t)); + id = rand(); + + signal(SIGINT, int_handler); + + if( argc < 2 ){ + fprintf( stderr,"usage: ping hostname\n"); + exit(1); + } + + my_open( argc, argv ); + + + while(1){ + send(); + signal( SIGALRM, alarm_handler ); + alarm(2); + ragain: + x=read( fd, buf, MAXBUF); + if (x>0){ + ipbuf = (struct ip *)buf; + if (ipbuf->ver >> 4 != 4) + goto ragain; + icmpbuf = (struct icmp *)(buf + (ipbuf->ver & 15) * 4); + /* check for dest unreachable icmp messages */ + if ( icmpbuf->type == 3 ){ + /* point to original ip packet in icmp data field */ + ipbuf2 = (struct ip *)(icmpbuf + 1); + icmpbuf = (struct icmp *)((char *)ipbuf2 + (ipbuf2->ver & 15) * 4); + /* check the bombed-out ip packet to see if it's ours */ + if( icmpbuf->id == id ){ + printf("ICMP: from "); + ipprint( &ipbuf->src ); + printf(" dest unreachable\n"); + } + goto ragain; + } + /* filter for our id */ + if( icmpbuf->id != id ) + goto ragain; + /* passed filters, so this must be one of our pings */ + recv++; + printf("%d bytes from %s (", x, argv[1] ); + ipprint( &ipbuf->src ); + printf(") req=%d", icmpbuf->seq ); + printf("\n"); + } + sleep(1); + } +} -- 2.34.1