#define _BSD_SOURCE /* BSD compatibility */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CISCO_AUTH 1999 #define RESPOND_TIME 10 struct pseudo { u_long saddr; u_long daddr; u_char zero; u_char protocol; u_short length; }; /* diz piece is ripped off.. who carez */ unsigned short in_cksum (unsigned short *ptr, int nbytes) { register long sum; /* assumes long == 32 bits */ u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ *((u_char *) & oddbyte) = *(u_char *) ptr; /* one byte only */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ return (answer); } /* sendpack : ripped from another piece of mine. packet_body isn't used here. * (so length is not supposed to). */ int sendpack( int s, u_long srcaddr, u_short srcport, u_long dstaddr, u_short dstport,u_short th_flags, u_char *packet_body,u_long length) { u_char packet[sizeof(struct ip) + sizeof(struct pseudo) + sizeof(struct tcphdr)]; struct sockaddr_in foo; struct in_addr srcinaddr,dstinaddr; struct ip *ip = (struct ip *) packet; struct pseudo *pseudo = (struct pseudo *) (packet + sizeof(struct ip)); struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ip) + sizeof(struct pseudo)); bzero(packet, sizeof(packet)); bzero(&foo,sizeof(foo)); /* only BSD, linux has plain u_long declared */ srcinaddr.s_addr = srcaddr; dstinaddr.s_addr = dstaddr; /* building packets */ pseudo->saddr = srcaddr; pseudo->daddr = dstaddr; pseudo->zero = 0; pseudo->protocol=IPPROTO_TCP; pseudo->length = htons(sizeof (struct tcphdr)); ip->ip_v = 4; ip->ip_hl = 5; ip->ip_id = 1234; ip->ip_src = srcinaddr; ip->ip_dst = dstinaddr; ip->ip_p = IPPROTO_TCP; ip->ip_ttl = 40; ip->ip_off = 0; ip->ip_len = sizeof(struct ip) + sizeof(struct tcphdr) + length; tcp->th_sport = htons(srcport); tcp->th_dport = htons(dstport); tcp->th_seq = htonl(rand()); tcp->th_ack = htonl(rand()); tcp->th_off=5; tcp->th_flags = th_flags; tcp->th_urp = 0; tcp->th_sum = in_cksum((u_short *) pseudo, sizeof(struct pseudo) + sizeof(struct tcphdr)); bcopy(tcp,pseudo,sizeof(struct tcphdr)); foo.sin_family=AF_INET; foo.sin_addr.s_addr=dstaddr; sendto(s,packet,sizeof(struct ip) + sizeof(struct tcphdr) + length, 0, (struct sockaddr *) &foo,sizeof(foo)); return 0; } void usage(char *name) { fprintf(stderr,"Usage: %s local_IP remote_IP\n",name); exit(1); } u_long resolve_name(char *hostname) { struct hostent *host; u_long addr; if ((addr = inet_addr(hostname)) != -1) return addr; if ((host = gethostbyname(hostname)) == NULL) { fprintf(stderr,"Can not resolve name: %s\n",hostname); exit(1); } bcopy(host->h_addr,&addr,host->h_length); return addr; } int rawfd; void sig_alarm(int sig) { fprintf(stderr,"No responce received. Packets might be blocked\n"); close(rawfd); exit(1); } int main(argc,argv) int argc; char **argv; { int rd,rsize; int one=1; int i; u_char buf[1024]; struct sockaddr_in raddr; struct in_addr srcip,dstip; struct ip *ip; struct tcphdr *tcp; u_short srcport,dstport; if (argc!=3) usage(argv[0]); srcip.s_addr = resolve_name(argv[1]); srcport = rand(); dstip.s_addr = resolve_name(argv[2]); dstport = CISCO_AUTH; if ((rawfd=socket(PF_INET,SOCK_RAW,IPPROTO_TCP))<0) { perror("RawSocket:"); exit(1); } if (setsockopt(rawfd,IPPROTO_IP,IP_HDRINCL,&one,sizeof(one))<0) { perror("SetSockOpt:"); close(rawfd); exit(1); } fprintf(stderr,"Indent [%s]: ",inet_ntoa(dstip)); sendpack(rawfd,srcip.s_addr,srcport,dstip.s_addr,dstport,TH_SYN,NULL,0); signal(SIGALRM,sig_alarm); alarm(RESPOND_TIME); for(;;) { if ((rd=recvfrom(rawfd,buf,1024,0, (struct sockaddr *)&raddr,&rsize))<0) break; ip=(struct ip *)buf; tcp=(struct tcphdr *)&buf[ip->ip_hl<<2]; if(ip->ip_src.s_addr == dstip.s_addr || tcp->th_sport == dstport) { if ((ip->ip_hl<<2)+(tcp->th_off<<2)==rd) fprintf(stderr,"non-cisco device"); else for(i=(ip->ip_hl<<2)+(tcp->th_off<<2);i