141edb306SCy Schubert /* $FreeBSD$ */ 241edb306SCy Schubert /* 341edb306SCy Schubert * ipsend.c (C) 1995-1998 Darren Reed 441edb306SCy Schubert * 541edb306SCy Schubert * See the IPFILTER.LICENCE file for details on licencing. 641edb306SCy Schubert */ 741edb306SCy Schubert #if !defined(lint) 841edb306SCy Schubert static const char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed"; 941edb306SCy Schubert static const char rcsid[] = "@(#)$Id$"; 1041edb306SCy Schubert #endif 1141edb306SCy Schubert #include <sys/param.h> 1241edb306SCy Schubert #include <sys/types.h> 1341edb306SCy Schubert #include <sys/time.h> 1441edb306SCy Schubert #include <sys/socket.h> 1541edb306SCy Schubert #include <netinet/in.h> 1641edb306SCy Schubert #include <arpa/inet.h> 1741edb306SCy Schubert #include <netinet/in_systm.h> 1841edb306SCy Schubert #include <stdio.h> 1941edb306SCy Schubert #include <stdlib.h> 2041edb306SCy Schubert #include <unistd.h> 2141edb306SCy Schubert #include <netdb.h> 2241edb306SCy Schubert #include <string.h> 2341edb306SCy Schubert #include <netinet/ip.h> 2441edb306SCy Schubert # include <netinet/ip_var.h> 2541edb306SCy Schubert #include "ipsend.h" 2641edb306SCy Schubert #include "ipf.h" 2741edb306SCy Schubert # include <netinet/udp_var.h> 2841edb306SCy Schubert 2941edb306SCy Schubert 3041edb306SCy Schubert extern char *optarg; 3141edb306SCy Schubert extern int optind; 3241edb306SCy Schubert extern void iplang(FILE *); 3341edb306SCy Schubert 3441edb306SCy Schubert char options[68]; 3541edb306SCy Schubert int opts; 3641edb306SCy Schubert char default_device[] = "le0"; 3741edb306SCy Schubert 3841edb306SCy Schubert 3941edb306SCy Schubert static void usage(char *); 4041edb306SCy Schubert static void do_icmp(ip_t *, char *); 4141edb306SCy Schubert void udpcksum(ip_t *, struct udphdr *, int); 4241edb306SCy Schubert int main(int, char **); 4341edb306SCy Schubert 4441edb306SCy Schubert 4541edb306SCy Schubert static void usage(prog) 4641edb306SCy Schubert char *prog; 4741edb306SCy Schubert { 4841edb306SCy Schubert fprintf(stderr, "Usage: %s [options] dest [flags]\n\ 4941edb306SCy Schubert \toptions:\n\ 5041edb306SCy Schubert \t\t-d\tdebug mode\n\ 5141edb306SCy Schubert \t\t-i device\tSend out on this device\n\ 5241edb306SCy Schubert \t\t-f fragflags\tcan set IP_MF or IP_DF\n\ 5341edb306SCy Schubert \t\t-g gateway\tIP gateway to use if non-local dest.\n\ 5441edb306SCy Schubert \t\t-I code,type[,gw[,dst[,src]]]\tSet ICMP protocol\n\ 5541edb306SCy Schubert \t\t-m mtu\t\tfake MTU to use when sending out\n\ 5641edb306SCy Schubert \t\t-P protocol\tSet protocol by name\n\ 5741edb306SCy Schubert \t\t-s src\t\tsource address for IP packet\n\ 5841edb306SCy Schubert \t\t-T\t\tSet TCP protocol\n\ 5941edb306SCy Schubert \t\t-t port\t\tdestination port\n\ 6041edb306SCy Schubert \t\t-U\t\tSet UDP protocol\n\ 6141edb306SCy Schubert \t\t-v\tverbose mode\n\ 6241edb306SCy Schubert \t\t-w <window>\tSet the TCP window size\n\ 6341edb306SCy Schubert ", prog); 6441edb306SCy Schubert fprintf(stderr, "Usage: %s [-dv] -L <filename>\n\ 6541edb306SCy Schubert \toptions:\n\ 6641edb306SCy Schubert \t\t-d\tdebug mode\n\ 6741edb306SCy Schubert \t\t-L filename\tUse IP language for sending packets\n\ 6841edb306SCy Schubert \t\t-v\tverbose mode\n\ 6941edb306SCy Schubert ", prog); 7041edb306SCy Schubert exit(1); 7141edb306SCy Schubert } 7241edb306SCy Schubert 7341edb306SCy Schubert 74efeb8bffSCy Schubert static 75efeb8bffSCy Schubert void do_icmp(ip_t *ip, char *args) 7641edb306SCy Schubert { 7741edb306SCy Schubert struct icmp *ic; 7841edb306SCy Schubert char *s; 7941edb306SCy Schubert 8041edb306SCy Schubert ip->ip_p = IPPROTO_ICMP; 8141edb306SCy Schubert ip->ip_len += sizeof(*ic); 8241edb306SCy Schubert ic = (struct icmp *)(ip + 1); 8341edb306SCy Schubert bzero((char *)ic, sizeof(*ic)); 8441edb306SCy Schubert if (!(s = strchr(args, ','))) 8541edb306SCy Schubert { 8641edb306SCy Schubert fprintf(stderr, "ICMP args missing: ,\n"); 8741edb306SCy Schubert return; 8841edb306SCy Schubert } 8941edb306SCy Schubert *s++ = '\0'; 9041edb306SCy Schubert ic->icmp_type = atoi(args); 9141edb306SCy Schubert ic->icmp_code = atoi(s); 9241edb306SCy Schubert if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ',')) 9341edb306SCy Schubert { 9441edb306SCy Schubert char *t; 9541edb306SCy Schubert 9641edb306SCy Schubert t = strtok(s, ","); 9741edb306SCy Schubert t = strtok(NULL, ","); 9841edb306SCy Schubert if (resolve(t, (char *)&ic->icmp_gwaddr) == -1) 9941edb306SCy Schubert { 10041edb306SCy Schubert fprintf(stderr,"Cant resolve %s\n", t); 10141edb306SCy Schubert exit(2); 10241edb306SCy Schubert } 10341edb306SCy Schubert if ((t = strtok(NULL, ","))) 10441edb306SCy Schubert { 10541edb306SCy Schubert if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1) 10641edb306SCy Schubert { 10741edb306SCy Schubert fprintf(stderr,"Cant resolve %s\n", t); 10841edb306SCy Schubert exit(2); 10941edb306SCy Schubert } 11041edb306SCy Schubert if ((t = strtok(NULL, ","))) 11141edb306SCy Schubert { 11241edb306SCy Schubert if (resolve(t, 11341edb306SCy Schubert (char *)&ic->icmp_ip.ip_src) == -1) 11441edb306SCy Schubert { 11541edb306SCy Schubert fprintf(stderr,"Cant resolve %s\n", t); 11641edb306SCy Schubert exit(2); 11741edb306SCy Schubert } 11841edb306SCy Schubert } 11941edb306SCy Schubert } 12041edb306SCy Schubert } 12141edb306SCy Schubert } 12241edb306SCy Schubert 12341edb306SCy Schubert 124efeb8bffSCy Schubert int 125efeb8bffSCy Schubert send_packets(char *dev, int mtu, ip_t *ip, struct in_addr gwip) 12641edb306SCy Schubert { 12741edb306SCy Schubert int wfd; 12841edb306SCy Schubert 12941edb306SCy Schubert wfd = initdevice(dev, 5); 13041edb306SCy Schubert if (wfd == -1) 13141edb306SCy Schubert return -1; 13241edb306SCy Schubert return send_packet(wfd, mtu, ip, gwip); 13341edb306SCy Schubert } 13441edb306SCy Schubert 13541edb306SCy Schubert void 13641edb306SCy Schubert udpcksum(ip_t *ip, struct udphdr *udp, int len) 13741edb306SCy Schubert { 13841edb306SCy Schubert union pseudoh { 13941edb306SCy Schubert struct hdr { 14041edb306SCy Schubert u_short len; 14141edb306SCy Schubert u_char ttl; 14241edb306SCy Schubert u_char proto; 14341edb306SCy Schubert u_32_t src; 14441edb306SCy Schubert u_32_t dst; 14541edb306SCy Schubert } h; 14641edb306SCy Schubert u_short w[6]; 14741edb306SCy Schubert } ph; 14841edb306SCy Schubert u_32_t temp32; 14941edb306SCy Schubert u_short *opts; 15041edb306SCy Schubert 15141edb306SCy Schubert ph.h.len = htons(len); 15241edb306SCy Schubert ph.h.ttl = 0; 15341edb306SCy Schubert ph.h.proto = IPPROTO_UDP; 15441edb306SCy Schubert ph.h.src = ip->ip_src.s_addr; 15541edb306SCy Schubert ph.h.dst = ip->ip_dst.s_addr; 15641edb306SCy Schubert temp32 = 0; 15741edb306SCy Schubert opts = &ph.w[0]; 15841edb306SCy Schubert temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5]; 15941edb306SCy Schubert temp32 = (temp32 >> 16) + (temp32 & 65535); 16041edb306SCy Schubert temp32 += (temp32 >> 16); 16141edb306SCy Schubert udp->uh_sum = temp32 & 65535; 16241edb306SCy Schubert udp->uh_sum = chksum((u_short *)udp, len); 16341edb306SCy Schubert if (udp->uh_sum == 0) 16441edb306SCy Schubert udp->uh_sum = 0xffff; 16541edb306SCy Schubert } 16641edb306SCy Schubert 167efeb8bffSCy Schubert int 168efeb8bffSCy Schubert main(int argc, char **argv) 16941edb306SCy Schubert { 17041edb306SCy Schubert FILE *langfile = NULL; 17141edb306SCy Schubert struct in_addr gwip; 17241edb306SCy Schubert tcphdr_t *tcp; 17341edb306SCy Schubert udphdr_t *udp; 17441edb306SCy Schubert ip_t *ip; 17541edb306SCy Schubert char *name = argv[0], host[MAXHOSTNAMELEN + 1]; 17641edb306SCy Schubert char *gateway = NULL, *dev = NULL; 17741edb306SCy Schubert char *src = NULL, *dst, *s; 17841edb306SCy Schubert int mtu = 1500, olen = 0, c, nonl = 0; 17941edb306SCy Schubert 18041edb306SCy Schubert /* 18141edb306SCy Schubert * 65535 is maximum packet size...you never know... 18241edb306SCy Schubert */ 18341edb306SCy Schubert ip = (ip_t *)calloc(1, 65536); 18441edb306SCy Schubert tcp = (tcphdr_t *)(ip + 1); 18541edb306SCy Schubert udp = (udphdr_t *)tcp; 18641edb306SCy Schubert ip->ip_len = sizeof(*ip); 18741edb306SCy Schubert IP_HL_A(ip, sizeof(*ip) >> 2); 18841edb306SCy Schubert 18941edb306SCy Schubert while ((c = getopt(argc, argv, "I:L:P:TUdf:i:g:m:o:s:t:vw:")) != -1) { 19041edb306SCy Schubert switch (c) 19141edb306SCy Schubert { 19241edb306SCy Schubert case 'I' : 19341edb306SCy Schubert nonl++; 19441edb306SCy Schubert if (ip->ip_p) 19541edb306SCy Schubert { 19641edb306SCy Schubert fprintf(stderr, "Protocol already set: %d\n", 19741edb306SCy Schubert ip->ip_p); 19841edb306SCy Schubert break; 19941edb306SCy Schubert } 20041edb306SCy Schubert do_icmp(ip, optarg); 20141edb306SCy Schubert break; 20241edb306SCy Schubert case 'L' : 20341edb306SCy Schubert if (nonl) { 20441edb306SCy Schubert fprintf(stderr, 20541edb306SCy Schubert "Incorrect usage of -L option.\n"); 20641edb306SCy Schubert usage(name); 20741edb306SCy Schubert } 20841edb306SCy Schubert if (!strcmp(optarg, "-")) 20941edb306SCy Schubert langfile = stdin; 21041edb306SCy Schubert else if (!(langfile = fopen(optarg, "r"))) { 21141edb306SCy Schubert fprintf(stderr, "can't open file %s\n", 21241edb306SCy Schubert optarg); 21341edb306SCy Schubert exit(1); 21441edb306SCy Schubert } 21541edb306SCy Schubert iplang(langfile); 21641edb306SCy Schubert return 0; 21741edb306SCy Schubert case 'P' : 21841edb306SCy Schubert { 21941edb306SCy Schubert struct protoent *p; 22041edb306SCy Schubert 22141edb306SCy Schubert nonl++; 22241edb306SCy Schubert if (ip->ip_p) 22341edb306SCy Schubert { 22441edb306SCy Schubert fprintf(stderr, "Protocol already set: %d\n", 22541edb306SCy Schubert ip->ip_p); 22641edb306SCy Schubert break; 22741edb306SCy Schubert } 22841edb306SCy Schubert if ((p = getprotobyname(optarg))) 22941edb306SCy Schubert ip->ip_p = p->p_proto; 23041edb306SCy Schubert else 23141edb306SCy Schubert fprintf(stderr, "Unknown protocol: %s\n", 23241edb306SCy Schubert optarg); 23341edb306SCy Schubert break; 23441edb306SCy Schubert } 23541edb306SCy Schubert case 'T' : 23641edb306SCy Schubert nonl++; 23741edb306SCy Schubert if (ip->ip_p) 23841edb306SCy Schubert { 23941edb306SCy Schubert fprintf(stderr, "Protocol already set: %d\n", 24041edb306SCy Schubert ip->ip_p); 24141edb306SCy Schubert break; 24241edb306SCy Schubert } 24341edb306SCy Schubert ip->ip_p = IPPROTO_TCP; 24441edb306SCy Schubert ip->ip_len += sizeof(tcphdr_t); 24541edb306SCy Schubert break; 24641edb306SCy Schubert case 'U' : 24741edb306SCy Schubert nonl++; 24841edb306SCy Schubert if (ip->ip_p) 24941edb306SCy Schubert { 25041edb306SCy Schubert fprintf(stderr, "Protocol already set: %d\n", 25141edb306SCy Schubert ip->ip_p); 25241edb306SCy Schubert break; 25341edb306SCy Schubert } 25441edb306SCy Schubert ip->ip_p = IPPROTO_UDP; 25541edb306SCy Schubert ip->ip_len += sizeof(udphdr_t); 25641edb306SCy Schubert break; 25741edb306SCy Schubert case 'd' : 25841edb306SCy Schubert opts |= OPT_DEBUG; 25941edb306SCy Schubert break; 26041edb306SCy Schubert case 'f' : 26141edb306SCy Schubert nonl++; 26241edb306SCy Schubert ip->ip_off = strtol(optarg, NULL, 0); 26341edb306SCy Schubert break; 26441edb306SCy Schubert case 'g' : 26541edb306SCy Schubert nonl++; 26641edb306SCy Schubert gateway = optarg; 26741edb306SCy Schubert break; 26841edb306SCy Schubert case 'i' : 26941edb306SCy Schubert nonl++; 27041edb306SCy Schubert dev = optarg; 27141edb306SCy Schubert break; 27241edb306SCy Schubert case 'm' : 27341edb306SCy Schubert nonl++; 27441edb306SCy Schubert mtu = atoi(optarg); 27541edb306SCy Schubert if (mtu < 28) 27641edb306SCy Schubert { 27741edb306SCy Schubert fprintf(stderr, "mtu must be > 28\n"); 27841edb306SCy Schubert exit(1); 27941edb306SCy Schubert } 28041edb306SCy Schubert break; 28141edb306SCy Schubert case 'o' : 28241edb306SCy Schubert nonl++; 28341edb306SCy Schubert olen = buildopts(optarg, options, (IP_HL(ip) - 5) << 2); 28441edb306SCy Schubert break; 28541edb306SCy Schubert case 's' : 28641edb306SCy Schubert nonl++; 28741edb306SCy Schubert src = optarg; 28841edb306SCy Schubert break; 28941edb306SCy Schubert case 't' : 29041edb306SCy Schubert nonl++; 29141edb306SCy Schubert if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) 29241edb306SCy Schubert tcp->th_dport = htons(atoi(optarg)); 29341edb306SCy Schubert break; 29441edb306SCy Schubert case 'v' : 29541edb306SCy Schubert opts |= OPT_VERBOSE; 29641edb306SCy Schubert break; 29741edb306SCy Schubert case 'w' : 29841edb306SCy Schubert nonl++; 29941edb306SCy Schubert if (ip->ip_p == IPPROTO_TCP) 30041edb306SCy Schubert tcp->th_win = atoi(optarg); 30141edb306SCy Schubert else 30241edb306SCy Schubert fprintf(stderr, "set protocol to TCP first\n"); 30341edb306SCy Schubert break; 30441edb306SCy Schubert default : 30541edb306SCy Schubert fprintf(stderr, "Unknown option \"%c\"\n", c); 30641edb306SCy Schubert usage(name); 30741edb306SCy Schubert } 30841edb306SCy Schubert } 30941edb306SCy Schubert 31041edb306SCy Schubert if (argc - optind < 1) 31141edb306SCy Schubert usage(name); 31241edb306SCy Schubert dst = argv[optind++]; 31341edb306SCy Schubert 31441edb306SCy Schubert if (!src) 31541edb306SCy Schubert { 31641edb306SCy Schubert gethostname(host, sizeof(host)); 31741edb306SCy Schubert src = host; 31841edb306SCy Schubert } 31941edb306SCy Schubert 32041edb306SCy Schubert if (resolve(src, (char *)&ip->ip_src) == -1) 32141edb306SCy Schubert { 32241edb306SCy Schubert fprintf(stderr,"Cant resolve %s\n", src); 32341edb306SCy Schubert exit(2); 32441edb306SCy Schubert } 32541edb306SCy Schubert 32641edb306SCy Schubert if (resolve(dst, (char *)&ip->ip_dst) == -1) 32741edb306SCy Schubert { 32841edb306SCy Schubert fprintf(stderr,"Cant resolve %s\n", dst); 32941edb306SCy Schubert exit(2); 33041edb306SCy Schubert } 33141edb306SCy Schubert 33241edb306SCy Schubert if (!gateway) 33341edb306SCy Schubert gwip = ip->ip_dst; 33441edb306SCy Schubert else if (resolve(gateway, (char *)&gwip) == -1) 33541edb306SCy Schubert { 33641edb306SCy Schubert fprintf(stderr,"Cant resolve %s\n", gateway); 33741edb306SCy Schubert exit(2); 33841edb306SCy Schubert } 33941edb306SCy Schubert 34041edb306SCy Schubert if (olen) 34141edb306SCy Schubert { 34241edb306SCy Schubert int hlen; 34341edb306SCy Schubert char *p; 34441edb306SCy Schubert 34541edb306SCy Schubert printf("Options: %d\n", olen); 34641edb306SCy Schubert hlen = sizeof(*ip) + olen; 34741edb306SCy Schubert IP_HL_A(ip, hlen >> 2); 34841edb306SCy Schubert ip->ip_len += olen; 34941edb306SCy Schubert p = (char *)malloc(65536); 35041edb306SCy Schubert if (p == NULL) 35141edb306SCy Schubert { 35241edb306SCy Schubert fprintf(stderr, "malloc failed\n"); 35341edb306SCy Schubert exit(2); 35441edb306SCy Schubert } 35541edb306SCy Schubert 35641edb306SCy Schubert bcopy(ip, p, sizeof(*ip)); 35741edb306SCy Schubert bcopy(options, p + sizeof(*ip), olen); 35841edb306SCy Schubert bcopy(ip + 1, p + hlen, ip->ip_len - hlen); 35941edb306SCy Schubert ip = (ip_t *)p; 36041edb306SCy Schubert 36141edb306SCy Schubert if (ip->ip_p == IPPROTO_TCP) { 36241edb306SCy Schubert tcp = (tcphdr_t *)(p + hlen); 36341edb306SCy Schubert } else if (ip->ip_p == IPPROTO_UDP) { 36441edb306SCy Schubert udp = (udphdr_t *)(p + hlen); 36541edb306SCy Schubert } 36641edb306SCy Schubert } 36741edb306SCy Schubert 36841edb306SCy Schubert if (ip->ip_p == IPPROTO_TCP) 36941edb306SCy Schubert for (s = argv[optind]; s && (c = *s); s++) 37041edb306SCy Schubert switch(c) 37141edb306SCy Schubert { 37241edb306SCy Schubert case 'S' : case 's' : 37341edb306SCy Schubert tcp->th_flags |= TH_SYN; 37441edb306SCy Schubert break; 37541edb306SCy Schubert case 'A' : case 'a' : 37641edb306SCy Schubert tcp->th_flags |= TH_ACK; 37741edb306SCy Schubert break; 37841edb306SCy Schubert case 'F' : case 'f' : 37941edb306SCy Schubert tcp->th_flags |= TH_FIN; 38041edb306SCy Schubert break; 38141edb306SCy Schubert case 'R' : case 'r' : 38241edb306SCy Schubert tcp->th_flags |= TH_RST; 38341edb306SCy Schubert break; 38441edb306SCy Schubert case 'P' : case 'p' : 38541edb306SCy Schubert tcp->th_flags |= TH_PUSH; 38641edb306SCy Schubert break; 38741edb306SCy Schubert case 'U' : case 'u' : 38841edb306SCy Schubert tcp->th_flags |= TH_URG; 38941edb306SCy Schubert break; 39041edb306SCy Schubert } 39141edb306SCy Schubert 39241edb306SCy Schubert if (!dev) 39341edb306SCy Schubert dev = default_device; 39441edb306SCy Schubert printf("Device: %s\n", dev); 39541edb306SCy Schubert printf("Source: %s\n", inet_ntoa(ip->ip_src)); 39641edb306SCy Schubert printf("Dest: %s\n", inet_ntoa(ip->ip_dst)); 39741edb306SCy Schubert printf("Gateway: %s\n", inet_ntoa(gwip)); 39841edb306SCy Schubert if (ip->ip_p == IPPROTO_TCP && tcp->th_flags) 39941edb306SCy Schubert printf("Flags: %#x\n", tcp->th_flags); 40041edb306SCy Schubert printf("mtu: %d\n", mtu); 40141edb306SCy Schubert 40241edb306SCy Schubert if (ip->ip_p == IPPROTO_UDP) { 40341edb306SCy Schubert udp->uh_sum = 0; 40441edb306SCy Schubert udpcksum(ip, udp, ip->ip_len - (IP_HL(ip) << 2)); 40541edb306SCy Schubert } 40641edb306SCy Schubert #ifdef DOSOCKET 40741edb306SCy Schubert if (ip->ip_p == IPPROTO_TCP && tcp->th_dport) 40841edb306SCy Schubert return do_socket(dev, mtu, ip, gwip); 40941edb306SCy Schubert #endif 41041edb306SCy Schubert return send_packets(dev, mtu, ip, gwip); 41141edb306SCy Schubert } 412