157109Speter/* $FreeBSD$ */ 222514Sdarrenr/* 357109Speter * ipsend.c (C) 1995-1998 Darren Reed 422514Sdarrenr * 580490Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 622514Sdarrenr */ 7145519Sdarrenr#if !defined(lint) 8145519Sdarrenrstatic const char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed"; 9255332Scystatic const char rcsid[] = "@(#)$Id$"; 1092691Sdarrenr#endif 1157109Speter#include <sys/param.h> 1222514Sdarrenr#include <sys/types.h> 1322514Sdarrenr#include <sys/time.h> 1422514Sdarrenr#include <sys/socket.h> 1522514Sdarrenr#include <netinet/in.h> 1622514Sdarrenr#include <arpa/inet.h> 1722514Sdarrenr#include <netinet/in_systm.h> 18145519Sdarrenr#include <stdio.h> 19145519Sdarrenr#include <stdlib.h> 20145519Sdarrenr#include <unistd.h> 21145519Sdarrenr#include <netdb.h> 22145519Sdarrenr#include <string.h> 2322514Sdarrenr#include <netinet/ip.h> 2422514Sdarrenr#ifndef linux 25145519Sdarrenr# include <netinet/ip_var.h> 2622514Sdarrenr#endif 2724583Sdarrenr#include "ipsend.h" 28145519Sdarrenr#include "ipf.h" 29145519Sdarrenr#ifndef linux 30145519Sdarrenr# include <netinet/udp_var.h> 3180490Sdarrenr#endif 3222514Sdarrenr 3380490Sdarrenr 3422514Sdarrenrextern char *optarg; 3522514Sdarrenrextern int optind; 3631183Speterextern void iplang __P((FILE *)); 3722514Sdarrenr 3822514Sdarrenrchar options[68]; 3931183Speterint opts; 40145519Sdarrenr#ifdef linux 4122514Sdarrenrchar default_device[] = "eth0"; 4222514Sdarrenr#else 43145519Sdarrenr# ifdef ultrix 44145519Sdarrenrchar default_device[] = "ln0"; 4522514Sdarrenr# else 46145519Sdarrenr# ifdef __bsdi__ 47145519Sdarrenrchar default_device[] = "ef0"; 4822514Sdarrenr# else 49145519Sdarrenr# ifdef __sgi 50145519Sdarrenrchar default_device[] = "ec0"; 5122514Sdarrenr# else 52145519Sdarrenr# ifdef __hpux 53145519Sdarrenrchar default_device[] = "lan0"; 5431183Speter# else 55145519Sdarrenrchar default_device[] = "le0"; 56145519Sdarrenr# endif /* __hpux */ 57145519Sdarrenr# endif /* __sgi */ 58145519Sdarrenr# endif /* __bsdi__ */ 59145519Sdarrenr# endif /* ultrix */ 60145519Sdarrenr#endif /* linux */ 6122514Sdarrenr 6222514Sdarrenr 6324583Sdarrenrstatic void usage __P((char *)); 6424583Sdarrenrstatic void do_icmp __P((ip_t *, char *)); 65130890Sdarrenrvoid udpcksum(ip_t *, struct udphdr *, int); 6624583Sdarrenrint main __P((int, char **)); 6724583Sdarrenr 6824583Sdarrenr 6924583Sdarrenrstatic void usage(prog) 70255332Scy char *prog; 7122514Sdarrenr{ 7222514Sdarrenr fprintf(stderr, "Usage: %s [options] dest [flags]\n\ 7322514Sdarrenr\toptions:\n\ 7431183Speter\t\t-d\tdebug mode\n\ 7531183Speter\t\t-i device\tSend out on this device\n\ 7622514Sdarrenr\t\t-f fragflags\tcan set IP_MF or IP_DF\n\ 7722514Sdarrenr\t\t-g gateway\tIP gateway to use if non-local dest.\n\ 7822514Sdarrenr\t\t-I code,type[,gw[,dst[,src]]]\tSet ICMP protocol\n\ 7922514Sdarrenr\t\t-m mtu\t\tfake MTU to use when sending out\n\ 8022514Sdarrenr\t\t-P protocol\tSet protocol by name\n\ 8122514Sdarrenr\t\t-s src\t\tsource address for IP packet\n\ 8222514Sdarrenr\t\t-T\t\tSet TCP protocol\n\ 8322514Sdarrenr\t\t-t port\t\tdestination port\n\ 8422514Sdarrenr\t\t-U\t\tSet UDP protocol\n\ 8531183Speter\t\t-v\tverbose mode\n\ 8631183Speter\t\t-w <window>\tSet the TCP window size\n\ 8722514Sdarrenr", prog); 8831183Speter fprintf(stderr, "Usage: %s [-dv] -L <filename>\n\ 8931183Speter\toptions:\n\ 9031183Speter\t\t-d\tdebug mode\n\ 9131183Speter\t\t-L filename\tUse IP language for sending packets\n\ 9231183Speter\t\t-v\tverbose mode\n\ 9331183Speter", prog); 9422514Sdarrenr exit(1); 9522514Sdarrenr} 9622514Sdarrenr 9722514Sdarrenr 9831183Speterstatic void do_icmp(ip, args) 99255332Scy ip_t *ip; 100255332Scy char *args; 10122514Sdarrenr{ 10222514Sdarrenr struct icmp *ic; 10322514Sdarrenr char *s; 10422514Sdarrenr 10522514Sdarrenr ip->ip_p = IPPROTO_ICMP; 10622514Sdarrenr ip->ip_len += sizeof(*ic); 10722514Sdarrenr ic = (struct icmp *)(ip + 1); 10822514Sdarrenr bzero((char *)ic, sizeof(*ic)); 10922514Sdarrenr if (!(s = strchr(args, ','))) 11022514Sdarrenr { 11122514Sdarrenr fprintf(stderr, "ICMP args missing: ,\n"); 11222514Sdarrenr return; 11322514Sdarrenr } 11422514Sdarrenr *s++ = '\0'; 11522514Sdarrenr ic->icmp_type = atoi(args); 11622514Sdarrenr ic->icmp_code = atoi(s); 11722514Sdarrenr if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ',')) 11822514Sdarrenr { 11922514Sdarrenr char *t; 12022514Sdarrenr 12122514Sdarrenr t = strtok(s, ","); 12222514Sdarrenr t = strtok(NULL, ","); 12322514Sdarrenr if (resolve(t, (char *)&ic->icmp_gwaddr) == -1) 12422514Sdarrenr { 12522514Sdarrenr fprintf(stderr,"Cant resolve %s\n", t); 12622514Sdarrenr exit(2); 12722514Sdarrenr } 12822514Sdarrenr if ((t = strtok(NULL, ","))) 12922514Sdarrenr { 13022514Sdarrenr if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1) 13122514Sdarrenr { 13222514Sdarrenr fprintf(stderr,"Cant resolve %s\n", t); 13322514Sdarrenr exit(2); 13422514Sdarrenr } 13522514Sdarrenr if ((t = strtok(NULL, ","))) 13622514Sdarrenr { 13722514Sdarrenr if (resolve(t, 13822514Sdarrenr (char *)&ic->icmp_ip.ip_src) == -1) 13922514Sdarrenr { 14022514Sdarrenr fprintf(stderr,"Cant resolve %s\n", t); 14122514Sdarrenr exit(2); 14222514Sdarrenr } 14322514Sdarrenr } 14422514Sdarrenr } 14522514Sdarrenr } 14622514Sdarrenr} 14722514Sdarrenr 14822514Sdarrenr 14922514Sdarrenrint send_packets(dev, mtu, ip, gwip) 150255332Scy char *dev; 151255332Scy int mtu; 152255332Scy ip_t *ip; 153255332Scy struct in_addr gwip; 15422514Sdarrenr{ 155145519Sdarrenr int wfd; 15622514Sdarrenr 157145519Sdarrenr wfd = initdevice(dev, 5); 158161357Sguido if (wfd == -1) 159161357Sguido return -1; 16022514Sdarrenr return send_packet(wfd, mtu, ip, gwip); 16122514Sdarrenr} 16222514Sdarrenr 163130890Sdarrenrvoid 164130890Sdarrenrudpcksum(ip_t *ip, struct udphdr *udp, int len) 165130890Sdarrenr{ 166130890Sdarrenr union pseudoh { 167130890Sdarrenr struct hdr { 168130890Sdarrenr u_short len; 169130890Sdarrenr u_char ttl; 170130890Sdarrenr u_char proto; 171130890Sdarrenr u_32_t src; 172130890Sdarrenr u_32_t dst; 173130890Sdarrenr } h; 174130890Sdarrenr u_short w[6]; 175130890Sdarrenr } ph; 176130890Sdarrenr u_32_t temp32; 177145519Sdarrenr u_short *opts; 17822514Sdarrenr 179130890Sdarrenr ph.h.len = htons(len); 180130890Sdarrenr ph.h.ttl = 0; 181130890Sdarrenr ph.h.proto = IPPROTO_UDP; 182130890Sdarrenr ph.h.src = ip->ip_src.s_addr; 183130890Sdarrenr ph.h.dst = ip->ip_dst.s_addr; 184130890Sdarrenr temp32 = 0; 185130890Sdarrenr opts = &ph.w[0]; 186130890Sdarrenr temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5]; 187130890Sdarrenr temp32 = (temp32 >> 16) + (temp32 & 65535); 188130890Sdarrenr temp32 += (temp32 >> 16); 189130890Sdarrenr udp->uh_sum = temp32 & 65535; 190130890Sdarrenr udp->uh_sum = chksum((u_short *)udp, len); 191130890Sdarrenr if (udp->uh_sum == 0) 192130890Sdarrenr udp->uh_sum = 0xffff; 193130890Sdarrenr} 194130890Sdarrenr 19522514Sdarrenrint main(argc, argv) 196255332Scy int argc; 197255332Scy char **argv; 19822514Sdarrenr{ 19931183Speter FILE *langfile = NULL; 20022514Sdarrenr struct in_addr gwip; 20122514Sdarrenr tcphdr_t *tcp; 202130890Sdarrenr udphdr_t *udp; 20322514Sdarrenr ip_t *ip; 20457109Speter char *name = argv[0], host[MAXHOSTNAMELEN + 1]; 20557109Speter char *gateway = NULL, *dev = NULL; 20631183Speter char *src = NULL, *dst, *s; 20731183Speter int mtu = 1500, olen = 0, c, nonl = 0; 20822514Sdarrenr 20922514Sdarrenr /* 21022514Sdarrenr * 65535 is maximum packet size...you never know... 21122514Sdarrenr */ 21222514Sdarrenr ip = (ip_t *)calloc(1, 65536); 213145519Sdarrenr tcp = (tcphdr_t *)(ip + 1); 214145519Sdarrenr udp = (udphdr_t *)tcp; 21522514Sdarrenr ip->ip_len = sizeof(*ip); 216145519Sdarrenr IP_HL_A(ip, sizeof(*ip) >> 2); 21722514Sdarrenr 218145519Sdarrenr while ((c = getopt(argc, argv, "I:L:P:TUdf:i:g:m:o:s:t:vw:")) != -1) { 21922514Sdarrenr switch (c) 22022514Sdarrenr { 22122514Sdarrenr case 'I' : 22231183Speter nonl++; 22322514Sdarrenr if (ip->ip_p) 22422514Sdarrenr { 22522514Sdarrenr fprintf(stderr, "Protocol already set: %d\n", 22622514Sdarrenr ip->ip_p); 22722514Sdarrenr break; 22822514Sdarrenr } 22922514Sdarrenr do_icmp(ip, optarg); 23022514Sdarrenr break; 23131183Speter case 'L' : 23231183Speter if (nonl) { 23331183Speter fprintf(stderr, 23431183Speter "Incorrect usage of -L option.\n"); 23531183Speter usage(name); 23631183Speter } 23731183Speter if (!strcmp(optarg, "-")) 23831183Speter langfile = stdin; 23931183Speter else if (!(langfile = fopen(optarg, "r"))) { 24031183Speter fprintf(stderr, "can't open file %s\n", 24131183Speter optarg); 24231183Speter exit(1); 24331183Speter } 24431183Speter iplang(langfile); 24531183Speter return 0; 24622514Sdarrenr case 'P' : 24722514Sdarrenr { 24822514Sdarrenr struct protoent *p; 24922514Sdarrenr 25031183Speter nonl++; 25122514Sdarrenr if (ip->ip_p) 25222514Sdarrenr { 25322514Sdarrenr fprintf(stderr, "Protocol already set: %d\n", 25422514Sdarrenr ip->ip_p); 25522514Sdarrenr break; 25622514Sdarrenr } 25722514Sdarrenr if ((p = getprotobyname(optarg))) 25822514Sdarrenr ip->ip_p = p->p_proto; 25922514Sdarrenr else 26022514Sdarrenr fprintf(stderr, "Unknown protocol: %s\n", 26122514Sdarrenr optarg); 26222514Sdarrenr break; 26322514Sdarrenr } 26422514Sdarrenr case 'T' : 26531183Speter nonl++; 26622514Sdarrenr if (ip->ip_p) 26722514Sdarrenr { 26822514Sdarrenr fprintf(stderr, "Protocol already set: %d\n", 26922514Sdarrenr ip->ip_p); 27022514Sdarrenr break; 27122514Sdarrenr } 27222514Sdarrenr ip->ip_p = IPPROTO_TCP; 27322514Sdarrenr ip->ip_len += sizeof(tcphdr_t); 27422514Sdarrenr break; 27522514Sdarrenr case 'U' : 27631183Speter nonl++; 27722514Sdarrenr if (ip->ip_p) 27822514Sdarrenr { 27922514Sdarrenr fprintf(stderr, "Protocol already set: %d\n", 28022514Sdarrenr ip->ip_p); 28122514Sdarrenr break; 28222514Sdarrenr } 28322514Sdarrenr ip->ip_p = IPPROTO_UDP; 28422514Sdarrenr ip->ip_len += sizeof(udphdr_t); 28522514Sdarrenr break; 28622514Sdarrenr case 'd' : 28731183Speter opts |= OPT_DEBUG; 28822514Sdarrenr break; 28922514Sdarrenr case 'f' : 29031183Speter nonl++; 29122514Sdarrenr ip->ip_off = strtol(optarg, NULL, 0); 29222514Sdarrenr break; 29322514Sdarrenr case 'g' : 29431183Speter nonl++; 29522514Sdarrenr gateway = optarg; 29622514Sdarrenr break; 29731183Speter case 'i' : 29831183Speter nonl++; 29931183Speter dev = optarg; 30031183Speter break; 30122514Sdarrenr case 'm' : 30231183Speter nonl++; 30322514Sdarrenr mtu = atoi(optarg); 30422514Sdarrenr if (mtu < 28) 30522514Sdarrenr { 30622514Sdarrenr fprintf(stderr, "mtu must be > 28\n"); 30722514Sdarrenr exit(1); 30822514Sdarrenr } 30922514Sdarrenr break; 31022514Sdarrenr case 'o' : 31131183Speter nonl++; 312145519Sdarrenr olen = buildopts(optarg, options, (IP_HL(ip) - 5) << 2); 31322514Sdarrenr break; 31422514Sdarrenr case 's' : 31531183Speter nonl++; 31622514Sdarrenr src = optarg; 31722514Sdarrenr break; 31822514Sdarrenr case 't' : 31931183Speter nonl++; 32022514Sdarrenr if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) 32122514Sdarrenr tcp->th_dport = htons(atoi(optarg)); 32222514Sdarrenr break; 32331183Speter case 'v' : 32431183Speter opts |= OPT_VERBOSE; 32531183Speter break; 32622514Sdarrenr case 'w' : 32731183Speter nonl++; 32822514Sdarrenr if (ip->ip_p == IPPROTO_TCP) 32922514Sdarrenr tcp->th_win = atoi(optarg); 33022514Sdarrenr else 33122514Sdarrenr fprintf(stderr, "set protocol to TCP first\n"); 33222514Sdarrenr break; 33322514Sdarrenr default : 33422514Sdarrenr fprintf(stderr, "Unknown option \"%c\"\n", c); 33522514Sdarrenr usage(name); 33622514Sdarrenr } 337145519Sdarrenr } 33822514Sdarrenr 33931183Speter if (argc - optind < 1) 34022514Sdarrenr usage(name); 34122514Sdarrenr dst = argv[optind++]; 34222514Sdarrenr 34322514Sdarrenr if (!src) 34422514Sdarrenr { 34522514Sdarrenr gethostname(host, sizeof(host)); 34622514Sdarrenr src = host; 34722514Sdarrenr } 34822514Sdarrenr 34922514Sdarrenr if (resolve(src, (char *)&ip->ip_src) == -1) 35022514Sdarrenr { 35122514Sdarrenr fprintf(stderr,"Cant resolve %s\n", src); 35222514Sdarrenr exit(2); 35322514Sdarrenr } 35422514Sdarrenr 35522514Sdarrenr if (resolve(dst, (char *)&ip->ip_dst) == -1) 35622514Sdarrenr { 35722514Sdarrenr fprintf(stderr,"Cant resolve %s\n", dst); 35822514Sdarrenr exit(2); 35922514Sdarrenr } 36022514Sdarrenr 36122514Sdarrenr if (!gateway) 36222514Sdarrenr gwip = ip->ip_dst; 36322514Sdarrenr else if (resolve(gateway, (char *)&gwip) == -1) 36422514Sdarrenr { 36522514Sdarrenr fprintf(stderr,"Cant resolve %s\n", gateway); 36622514Sdarrenr exit(2); 36722514Sdarrenr } 36822514Sdarrenr 36931183Speter if (olen) 37031183Speter { 371130890Sdarrenr int hlen; 372130890Sdarrenr char *p; 37331183Speter 37431183Speter printf("Options: %d\n", olen); 375130890Sdarrenr hlen = sizeof(*ip) + olen; 376145519Sdarrenr IP_HL_A(ip, hlen >> 2); 377130890Sdarrenr ip->ip_len += olen; 378130890Sdarrenr p = (char *)malloc(65536); 379145519Sdarrenr if (p == NULL) 38072006Sdarrenr { 381145519Sdarrenr fprintf(stderr, "malloc failed\n"); 38272006Sdarrenr exit(2); 383145519Sdarrenr } 384145519Sdarrenr 385130890Sdarrenr bcopy(ip, p, sizeof(*ip)); 386130890Sdarrenr bcopy(options, p + sizeof(*ip), olen); 387130890Sdarrenr bcopy(ip + 1, p + hlen, ip->ip_len - hlen); 388130890Sdarrenr ip = (ip_t *)p; 389145519Sdarrenr 390130890Sdarrenr if (ip->ip_p == IPPROTO_TCP) { 391145519Sdarrenr tcp = (tcphdr_t *)(p + hlen); 392145519Sdarrenr } else if (ip->ip_p == IPPROTO_UDP) { 393145519Sdarrenr udp = (udphdr_t *)(p + hlen); 394130890Sdarrenr } 39531183Speter } 39631183Speter 39722514Sdarrenr if (ip->ip_p == IPPROTO_TCP) 39837078Speter for (s = argv[optind]; s && (c = *s); s++) 39922514Sdarrenr switch(c) 40022514Sdarrenr { 40122514Sdarrenr case 'S' : case 's' : 40222514Sdarrenr tcp->th_flags |= TH_SYN; 40322514Sdarrenr break; 40422514Sdarrenr case 'A' : case 'a' : 40522514Sdarrenr tcp->th_flags |= TH_ACK; 40622514Sdarrenr break; 40722514Sdarrenr case 'F' : case 'f' : 40822514Sdarrenr tcp->th_flags |= TH_FIN; 40922514Sdarrenr break; 41022514Sdarrenr case 'R' : case 'r' : 41122514Sdarrenr tcp->th_flags |= TH_RST; 41222514Sdarrenr break; 41322514Sdarrenr case 'P' : case 'p' : 41422514Sdarrenr tcp->th_flags |= TH_PUSH; 41522514Sdarrenr break; 41622514Sdarrenr case 'U' : case 'u' : 41722514Sdarrenr tcp->th_flags |= TH_URG; 41822514Sdarrenr break; 41922514Sdarrenr } 42022514Sdarrenr 42122514Sdarrenr if (!dev) 42222514Sdarrenr dev = default_device; 42322514Sdarrenr printf("Device: %s\n", dev); 42422514Sdarrenr printf("Source: %s\n", inet_ntoa(ip->ip_src)); 42522514Sdarrenr printf("Dest: %s\n", inet_ntoa(ip->ip_dst)); 42622514Sdarrenr printf("Gateway: %s\n", inet_ntoa(gwip)); 42722514Sdarrenr if (ip->ip_p == IPPROTO_TCP && tcp->th_flags) 42822514Sdarrenr printf("Flags: %#x\n", tcp->th_flags); 42922514Sdarrenr printf("mtu: %d\n", mtu); 43022514Sdarrenr 431130890Sdarrenr if (ip->ip_p == IPPROTO_UDP) { 432130890Sdarrenr udp->uh_sum = 0; 433145519Sdarrenr udpcksum(ip, udp, ip->ip_len - (IP_HL(ip) << 2)); 434130890Sdarrenr } 43522514Sdarrenr#ifdef DOSOCKET 436130890Sdarrenr if (ip->ip_p == IPPROTO_TCP && tcp->th_dport) 437145519Sdarrenr return do_socket(dev, mtu, ip, gwip); 43822514Sdarrenr#endif 439130890Sdarrenr return send_packets(dev, mtu, ip, gwip); 44022514Sdarrenr} 441