From: Samuel Jero Date: Wed, 24 Oct 2012 22:12:26 +0000 (-0400) Subject: "Sort of working" code. Only IPv6, just detects DCCP packets in response, terrible... X-Git-Url: http://sjero.net/git/?p=dccpping;a=commitdiff_plain;h=8739c9b4db1f612a3dd790c5aa62a19b907bc9c1 "Sort of working" code. Only IPv6, just detects DCCP packets in response, terrible design.... Lots of work needed --- 8739c9b4db1f612a3dd790c5aa62a19b907bc9c1 diff --git a/.cproject b/.cproject new file mode 100644 index 0000000..a4e9398 --- /dev/null +++ b/.cproject @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..57aa611 --- /dev/null +++ b/.project @@ -0,0 +1,26 @@ + + + dccpping + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6a76196 --- /dev/null +++ b/Makefile @@ -0,0 +1,39 @@ +############################################################################### +#Author: Samuel Jero +# +# Date: 11/2011 +# +# Makefile for program dccpping +############################################################################### + +CFLAGS= -O2 -Wall -Werror -g --std=gnu99 + +# for solaris, you probably want: +# LDLIBS = -lnsl -lsocket +# for HP, I'm told that you need: +# LDLIBS = -lstr +# everybody else (that I know of) just needs: +# LDLIBS = +LDLIBS = + +CC = gcc + +BINDIR = /usr/local/bin +MANDIR = /usr/local/man + +all: dccpping + +dccpping: dccpping.c + ${CC} ${CFLAGS} ${LDLIBS} dccpping.c -odccpping + + +install: dccpping + install -m 755 -o bin -g bin dccp2tcp ${BINDIR}/dccpping +# install -m 444 -o bin -g bin dccp2tcp.1 ${MANDIR}/man1/dccpping.1 + +uninstall: + rm -f ${BINDIR}/dccpping +# rm -r ${MANDIR}/man1/dccpping.1 + +clean: + rm -f *~ dccpping core *.o \ No newline at end of file diff --git a/dccpping.c b/dccpping.c new file mode 100644 index 0000000..8dc59c0 --- /dev/null +++ b/dccpping.c @@ -0,0 +1,433 @@ +/****************************************************************************** +Author: Samuel Jero + +Date: 10/2012 + +Description: Program to ping hosts using DCCP REQ packets to test for DCCP connectivity. +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int errno; + + +//Pseudo Header for checksums +#define IP4_ADDR_LEN 4 +struct ip4_pseudo_hdr{ + unsigned char src[IP4_ADDR_LEN]; + unsigned char dest[IP4_ADDR_LEN]; + unsigned int len; + unsigned char zero[3]; + unsigned char nxt; +}; +#define IP6_ADDR_LEN 16 +struct ip6_pseudo_hdr{ + unsigned char src[IP6_ADDR_LEN]; + unsigned char dest[IP6_ADDR_LEN]; + unsigned int len; + unsigned char zero[3]; + unsigned char nxt; +}; + + +int debug=0; /*set to 1 to turn on debugging information*/ +int count=-1; +int dest_port=33434; +int ttl=64; +long interval=1000; +int ip_type=AF_UNSPEC; +socklen_t addrlen; +struct sockaddr *dest_addr; +struct sockaddr *src_addr; + + +void doping(); +int ip6_chksum(unsigned char* buff, int len, unsigned char* dest, unsigned char* src, int type, unsigned short* chksum); +int ip4_chksum(unsigned char* buff, int len, unsigned char* dest, unsigned char* src, int type, unsigned short* chksum); +u_int32_t checksum(unsigned char *buf, unsigned nbytes, u_int32_t sum); +u_int32_t wrapsum(u_int32_t sum); +void dbgprintf(int level, const char *fmt, ...); +void sanitize_environment(); +void usage(); + + +/*Parse commandline options*/ +int main(int argc, char *argv[]) +{ + char c; + char *src=NULL; + char *dst=NULL; + int err; + struct addrinfo hint; + struct addrinfo *dtmp, *stmp; + struct ifaddrs *temp, *cur; + struct sockaddr_in6* iv6; + struct sockaddr_in6 lv6; + struct sockaddr_in lv4; + struct sockaddr_in* iv4; + + sanitize_environment(); + + while ((c = getopt(argc, argv, "64c:p:i:dt:S:")) != -1) { + switch (c) { + case '6': + ip_type=AF_INET6; + break; + case '4': + ip_type=AF_INET; + break; + case 'c': + count = atoi(optarg); + if(count<=0){ + dbgprintf(0, "Error: count must be positive"); + exit(1); + } + break; + case 'p': + dest_port = atoi(optarg); + break; + case 'i': + interval = (long)(atof(optarg) * 1000.0); + if (interval <= 0) { + fprintf(stderr, "Invalid interval\n"); + exit(1); + } + break; + case 'd': + debug++; + break; + case 't': + ttl = atoi(optarg); + if (ttl < 1 || ttl > 255) { + fprintf(stderr, "Invalid TTL\n"); + } + break; + case 'S': + src=optarg; + //r = inet_aton(optarg, &src_ip); + break; + default: + usage(); + break; + } + } + + argc -= optind; + argv += optind; + + if (argc != 1) { + usage(); + } + dst=argv[0]; + + /*Lookup destination Address*/ + memset(&hint,0,sizeof(struct addrinfo)); + hint.ai_family=ip_type; + hint.ai_flags=AI_V4MAPPED | AI_ADDRCONFIG; + + if((err=getaddrinfo(dst,NULL,&hint,&dtmp))!=0){ + dbgprintf(0,"Error: Couldn't lookup destination %s (%s)\n", dst, gai_strerror(err)); + exit(1); + } + if(dtmp==NULL){ + dbgprintf(0,"Error: Unknown Host %s\n", dst); + exit(1); + }else{ + hint.ai_family=ip_type=dtmp->ai_family; + addrlen=dtmp->ai_addrlen; + dest_addr=malloc(dtmp->ai_addrlen); + if(dest_addr==NULL){ + dbgprintf(0,"Error: Can't allocate Memory\n"); + exit(1); + } + memcpy(dest_addr,dtmp->ai_addr,dtmp->ai_addrlen); + } + freeaddrinfo(dtmp); + + /*Get a meaningful source address*/ + if(src!=NULL){ + /*Use Commandline arg*/ + if((err=getaddrinfo(src,NULL,&hint,&stmp))!=0){ + dbgprintf(0,"Error: Source Address %s is invalid (%s)\n", src, gai_strerror(err)); + exit(1); + } + if(stmp==NULL){ + dbgprintf(0,"Error: Unknown Host %s\n", dst); + exit(1); + }else{ + src_addr=malloc(stmp->ai_addrlen); + if(src_addr==NULL){ + dbgprintf(0,"Error: Can't allocate Memory\n"); + exit(1); + } + memcpy(src_addr,stmp->ai_addr,stmp->ai_addrlen); + } + freeaddrinfo(stmp); + }else{ + /*Guess a good source address*/ + inet_pton(AF_INET6,"::1",&lv6); + inet_pton(AF_INET,"127.0.0.1",&lv4); + getifaddrs(&temp); + cur=temp; + while(cur!=NULL){ + if((cur->ifa_flags & IFF_BROADCAST) == IFF_BROADCAST){ /*Not broad cast*/ + cur=cur->ifa_next; + continue; + } + if(cur->ifa_addr==NULL || cur->ifa_addr->sa_family!=ip_type){ /*Not matching ipv4/ipv6 of dest*/ + cur=cur->ifa_next; + continue; + } + if(cur->ifa_addr!=NULL && cur->ifa_addr->sa_family==AF_INET6){ + iv6=(struct sockaddr_in6*)cur->ifa_addr; + if(iv6->sin6_scope_id!=0){ /*Not globally valid address, if ipv6*/ + cur=cur->ifa_next; + continue; + } + if(memcmp(&lv6.sin6_addr,&iv6->sin6_addr,sizeof(iv6->sin6_addr))==0){/*IPv6 loopback*/ + cur=cur->ifa_next; + continue; + } + } + if(cur->ifa_addr!=NULL && cur->ifa_addr->sa_family==AF_INET){ + iv4=(struct sockaddr_in*)cur->ifa_addr; + if(memcmp(&lv4.sin_addr,&iv4->sin_addr,sizeof(iv4->sin_addr))==0){/*IPv4 loopback*/ + cur=cur->ifa_next; + continue; + } + } + + src_addr=malloc(sizeof(struct sockaddr_storage)); + if(src_addr==NULL){ + dbgprintf(0,"Error: Can't allocate Memory\n"); + exit(1); + } + src_addr->sa_family=ip_type; + memcpy(src_addr,cur->ifa_addr,addrlen); + break; + } + freeifaddrs(temp); + } + + doping(); + + + free(src_addr); + free(dest_addr); + return 0; +} + +/*Preform the ping functionality*/ +void doping(){ + int ds, is; + int done=0; + int seq=8; + int slen=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request); + unsigned char sbuffer[slen+1]; + unsigned char rbuffer[1000]; + char pbuf[1000]; + struct dccp_hdr *dhdr; + struct dccp_hdr_ext *dhdre; + struct dccp_hdr_request *dhdrr; + struct sockaddr_storage rcv_addr; + socklen_t rcv_addr_len=sizeof(struct sockaddr_storage); + struct sockaddr_in *iv41, *iv42; + struct sockaddr_in6 *tmp; + int opt; + int rlen; + + dbgprintf(0, "In doping()\n"); + + /*Open Sockets*/ + ds=socket(ip_type, SOCK_RAW | SOCK_NONBLOCK ,IPPROTO_DCCP); + if(ds<0){ + dbgprintf(0, "Error opening raw DCCP socket\n"); + exit(1); + } + /*opt=1; + if(setsockopt(ds,IPPROTO_IP, IP_HDRINCL, &opt, sizeof(opt))<0){ + dbgprintf(0, "Error setting socket options on raw DCCP socket (%s)\n", strerror(errno)); + exit(1); + }*/ + is=socket(ip_type,SOCK_RAW | SOCK_NONBLOCK ,IPPROTO_ICMP); + if(is<0){ + dbgprintf(0,"Error opening raw ICMP socket\n"); + exit(1); + } + + /*Build DCCP packet*/ + dhdr=(struct dccp_hdr*)sbuffer; + dhdre=(struct dccp_hdr_ext*)(sbuffer+sizeof(struct dccp_hdr)); + dhdrr=(struct dccp_hdr_request*)(sbuffer+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)); + dhdr->dccph_ccval=0; + dhdr->dccph_checksum=0; + dhdr->dccph_cscov=0; + dhdr->dccph_doff=slen/4; + dhdr->dccph_dport=htons(dest_port); + dhdr->dccph_reserved=0; + dhdr->dccph_sport=htons(dest_port+1); + dhdr->dccph_x=1; + dhdr->dccph_type=DCCP_PKT_REQUEST; + dhdr->dccph_seq2=htonl(0); //Reserved for 48 bit sequence numbers + dhdr->dccph_seq=htonl(0); //just always make the high end 0 + dhdre->dccph_seq_low=htonl(seq)>>8; + dhdrr->dccph_req_service= htonl(0x50455246); + + opt=((unsigned char*)&dhdr->dccph_checksum) - &sbuffer[0]; + if (setsockopt(ds, IPPROTO_IPV6, IPV6_CHECKSUM, &opt, sizeof(opt)) < 0){ + dbgprintf(0, "Error setting up checksums on raw DCCP socket (%s)\n", strerror(errno)); + exit(1); + } + if(ip_type==AF_INET){ + iv41=(struct sockaddr_in*)dest_addr; + iv42=(struct sockaddr_in*)src_addr; + ip4_chksum(sbuffer, slen, (unsigned char*) &iv41->sin_addr, (unsigned char*)&iv42->sin_addr, 33,&dhdr->dccph_checksum); + } + + while(!done){ + rcv_addr_len=sizeof(struct sockaddr_storage); + if(sendto(ds, &sbuffer, slen, MSG_DONTWAIT,(struct sockaddr*)dest_addr,addrlen)<0){ + dbgprintf(0,"Error: sendto failed\n"); + } + tmp=(struct sockaddr_in6*)dest_addr; + dbgprintf(0, "Sending DCCP Request to %s\n",inet_ntop(ip_type, (void*)&tmp->sin6_addr, pbuf, 1000)); + + if((rlen=recvfrom(ds, &rbuffer, 1000,MSG_DONTWAIT,(struct sockaddr*)&rcv_addr,&rcv_addr_len))<0){ + if(errno!=EAGAIN){ + dbgprintf(0, "Error on receive from DCCP socket (%s)\n",strerror(errno)); + } + } + if(rlen>0){ + if(rlen< sizeof(struct dccp_hdr)){ + dbgprintf(0,"Received Non-DCCP data!\n"); + } + dhdr=(struct dccp_hdr*)rbuffer; + tmp=(struct sockaddr_in6*)&rcv_addr; + dbgprintf(0,"Response from %s (%i)\n", inet_ntop(ip_type, (void*)&tmp->sin6_addr, pbuf, 1000),dhdr->dccph_type); + } + + if((rlen=recvfrom(is, &rbuffer, 1000,MSG_DONTWAIT,(struct sockaddr*)&rcv_addr,&rcv_addr_len))<0){ + if(errno!=EAGAIN){ + dbgprintf(0, "Error on receive from ICMP socket (%s)\n",strerror(errno)); + } + } + if(rlen>0){ + dbgprintf(0,"Received ICMP data!\n"); + } + + if(count>-1){ + count--; + } + if(count==0){ + done=1; + break; + } + sleep(interval/1000); + } + + close(ds); + close(is); +} + +int ip6_chksum(unsigned char* buff, int len, unsigned char* dest, unsigned char* src, int type, unsigned short* chksum){ + struct ip6_pseudo_hdr hdr; + + //create pseudo header + memset(&hdr, 0, sizeof(struct ip6_pseudo_hdr)); + memcpy(hdr.src, src, IP6_ADDR_LEN); + memcpy(hdr.dest, dest, IP6_ADDR_LEN); + hdr.nxt=type; + hdr.len=htonl(len); + + //calculate total checksum + *chksum=wrapsum(checksum((unsigned char*)&hdr,sizeof(struct ip6_pseudo_hdr),checksum(buff,len,0))); +return 0; +} + +int ip4_chksum(unsigned char* buff, int len, unsigned char* dest, unsigned char* src, int type, unsigned short* chksum){ + struct ip4_pseudo_hdr hdr; + + //create pseudo header + memset(&hdr, 0, sizeof(struct ip4_pseudo_hdr)); + memcpy(hdr.src, src, IP4_ADDR_LEN); + memcpy(hdr.dest, dest, IP4_ADDR_LEN); + hdr.nxt=type; + hdr.len=htonl(len); + + //calculate total checksum + *chksum=wrapsum(checksum((unsigned char*)&hdr,sizeof(struct ip4_pseudo_hdr),checksum(buff,len,0))); +return 0; +} + +u_int32_t checksum(unsigned char *buf, unsigned nbytes, u_int32_t sum) +{ + int i; + /* Checksum all the pairs of bytes first... */ + for (i = 0; i < (nbytes & ~1U); i += 2) { + sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i))); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + /* + * If there's a single byte left over, checksum it, too. + * Network byte order is big-endian, so the remaining byte is + * the high byte. + */ + if (i < nbytes) { + sum += buf[i] << 8; + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + return (sum); +} + +u_int32_t wrapsum(u_int32_t sum) +{ + sum = ~sum & 0xFFFF; + return (htons(sum)); +} + +/*Usage information for program*/ +void usage() +{ + dbgprintf(0, "dccpping: [-d] [-6|-4] [-c count] [-p port] [-i interval] [-t ttl] [-S srcaddress] remote_host\n"); + exit(0); +} + +/*Program will probably be run setuid, so be extra careful*/ +void sanitize_environment() +{ +#if defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE) + clearenv(); +#else + extern char **environ; + environ = NULL; +#endif +} + +/*Debug Printf*/ +void dbgprintf(int level, const char *fmt, ...) +{ + va_list args; + if(debug>=level){ + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + } +}