Home | History | Annotate | Line # | Download | only in ipsend
      1  1.3       mrg /*	$NetBSD: ipsend.c,v 1.3 2018/02/04 08:19:42 mrg Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * ipsend.c (C) 1995-1998 Darren Reed
      5  1.1  christos  *
      6  1.1  christos  * See the IPFILTER.LICENCE file for details on licencing.
      7  1.1  christos  */
      8  1.1  christos #if !defined(lint)
      9  1.3       mrg static __attribute__((__used__)) const char sccsid[] = "@(#)ipsend.c	1.5 12/10/95 (C)1995 Darren Reed";
     10  1.3       mrg static __attribute__((__used__)) const char rcsid[] = "@(#)Id: ipsend.c,v 1.1.1.2 2012/07/22 13:44:36 darrenr Exp $";
     11  1.1  christos #endif
     12  1.1  christos #include <sys/param.h>
     13  1.1  christos #include <sys/types.h>
     14  1.1  christos #include <sys/time.h>
     15  1.1  christos #include <sys/socket.h>
     16  1.1  christos #include <netinet/in.h>
     17  1.1  christos #include <arpa/inet.h>
     18  1.1  christos #include <netinet/in_systm.h>
     19  1.1  christos #include <stdio.h>
     20  1.1  christos #include <stdlib.h>
     21  1.1  christos #include <unistd.h>
     22  1.1  christos #include <netdb.h>
     23  1.1  christos #include <string.h>
     24  1.1  christos #include <netinet/ip.h>
     25  1.1  christos #ifndef	linux
     26  1.1  christos # include <netinet/ip_var.h>
     27  1.1  christos #endif
     28  1.1  christos #include "ipsend.h"
     29  1.1  christos #include "ipf.h"
     30  1.1  christos #ifndef	linux
     31  1.1  christos # include <netinet/udp_var.h>
     32  1.1  christos #endif
     33  1.1  christos 
     34  1.1  christos 
     35  1.1  christos extern	char	*optarg;
     36  1.1  christos extern	int	optind;
     37  1.1  christos extern	void	iplang __P((FILE *));
     38  1.1  christos 
     39  1.1  christos char	options[68];
     40  1.1  christos int	opts;
     41  1.1  christos #ifdef linux
     42  1.1  christos char	default_device[] = "eth0";
     43  1.1  christos #else
     44  1.1  christos # ifdef ultrix
     45  1.1  christos char	default_device[] = "ln0";
     46  1.1  christos # else
     47  1.1  christos #  ifdef __bsdi__
     48  1.1  christos char	default_device[] = "ef0";
     49  1.1  christos #  else
     50  1.1  christos #   ifdef __sgi
     51  1.1  christos char	default_device[] = "ec0";
     52  1.1  christos #   else
     53  1.1  christos #    ifdef __hpux
     54  1.1  christos char	default_device[] = "lan0";
     55  1.1  christos #    else
     56  1.1  christos char	default_device[] = "le0";
     57  1.1  christos #    endif /* __hpux */
     58  1.1  christos #   endif /* __sgi */
     59  1.1  christos #  endif /* __bsdi__ */
     60  1.1  christos # endif /* ultrix */
     61  1.1  christos #endif /* linux */
     62  1.1  christos 
     63  1.1  christos 
     64  1.1  christos static	void	usage __P((char *));
     65  1.1  christos static	void	do_icmp __P((ip_t *, char *));
     66  1.1  christos void udpcksum(ip_t *, struct udphdr *, int);
     67  1.1  christos int	main __P((int, char **));
     68  1.1  christos 
     69  1.1  christos 
     70  1.1  christos static	void	usage(prog)
     71  1.1  christos 	char	*prog;
     72  1.1  christos {
     73  1.1  christos 	fprintf(stderr, "Usage: %s [options] dest [flags]\n\
     74  1.1  christos \toptions:\n\
     75  1.1  christos \t\t-d\tdebug mode\n\
     76  1.1  christos \t\t-i device\tSend out on this device\n\
     77  1.1  christos \t\t-f fragflags\tcan set IP_MF or IP_DF\n\
     78  1.1  christos \t\t-g gateway\tIP gateway to use if non-local dest.\n\
     79  1.1  christos \t\t-I code,type[,gw[,dst[,src]]]\tSet ICMP protocol\n\
     80  1.1  christos \t\t-m mtu\t\tfake MTU to use when sending out\n\
     81  1.1  christos \t\t-P protocol\tSet protocol by name\n\
     82  1.1  christos \t\t-s src\t\tsource address for IP packet\n\
     83  1.1  christos \t\t-T\t\tSet TCP protocol\n\
     84  1.1  christos \t\t-t port\t\tdestination port\n\
     85  1.1  christos \t\t-U\t\tSet UDP protocol\n\
     86  1.1  christos \t\t-v\tverbose mode\n\
     87  1.1  christos \t\t-w <window>\tSet the TCP window size\n\
     88  1.1  christos ", prog);
     89  1.1  christos 	fprintf(stderr, "Usage: %s [-dv] -L <filename>\n\
     90  1.1  christos \toptions:\n\
     91  1.1  christos \t\t-d\tdebug mode\n\
     92  1.1  christos \t\t-L filename\tUse IP language for sending packets\n\
     93  1.1  christos \t\t-v\tverbose mode\n\
     94  1.1  christos ", prog);
     95  1.1  christos 	exit(1);
     96  1.1  christos }
     97  1.1  christos 
     98  1.1  christos 
     99  1.1  christos static void do_icmp(ip, args)
    100  1.1  christos 	ip_t *ip;
    101  1.1  christos 	char *args;
    102  1.1  christos {
    103  1.1  christos 	struct	icmp	*ic;
    104  1.1  christos 	char	*s;
    105  1.1  christos 
    106  1.1  christos 	ip->ip_p = IPPROTO_ICMP;
    107  1.1  christos 	ip->ip_len += sizeof(*ic);
    108  1.1  christos 	ic = (struct icmp *)(ip + 1);
    109  1.1  christos 	bzero((char *)ic, sizeof(*ic));
    110  1.1  christos 	if (!(s = strchr(args, ',')))
    111  1.1  christos 	    {
    112  1.1  christos 		fprintf(stderr, "ICMP args missing: ,\n");
    113  1.1  christos 		return;
    114  1.1  christos 	    }
    115  1.1  christos 	*s++ = '\0';
    116  1.1  christos 	ic->icmp_type = atoi(args);
    117  1.1  christos 	ic->icmp_code = atoi(s);
    118  1.1  christos 	if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ','))
    119  1.1  christos 	    {
    120  1.1  christos 		char	*t;
    121  1.1  christos 
    122  1.1  christos 		t = strtok(s, ",");
    123  1.1  christos 		t = strtok(NULL, ",");
    124  1.1  christos 		if (resolve(t, (char *)&ic->icmp_gwaddr) == -1)
    125  1.1  christos 		    {
    126  1.1  christos 			fprintf(stderr,"Cant resolve %s\n", t);
    127  1.1  christos 			exit(2);
    128  1.1  christos 		    }
    129  1.1  christos 		if ((t = strtok(NULL, ",")))
    130  1.1  christos 		    {
    131  1.1  christos 			if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1)
    132  1.1  christos 			    {
    133  1.1  christos 				fprintf(stderr,"Cant resolve %s\n", t);
    134  1.1  christos 				exit(2);
    135  1.1  christos 			    }
    136  1.1  christos 			if ((t = strtok(NULL, ",")))
    137  1.1  christos 			    {
    138  1.1  christos 				if (resolve(t,
    139  1.1  christos 					    (char *)&ic->icmp_ip.ip_src) == -1)
    140  1.1  christos 				    {
    141  1.1  christos 					fprintf(stderr,"Cant resolve %s\n", t);
    142  1.1  christos 					exit(2);
    143  1.1  christos 				    }
    144  1.1  christos 			    }
    145  1.1  christos 		    }
    146  1.1  christos 	    }
    147  1.1  christos }
    148  1.1  christos 
    149  1.1  christos 
    150  1.1  christos int send_packets(dev, mtu, ip, gwip)
    151  1.1  christos 	char *dev;
    152  1.1  christos 	int mtu;
    153  1.1  christos 	ip_t *ip;
    154  1.1  christos 	struct in_addr gwip;
    155  1.1  christos {
    156  1.1  christos 	int wfd;
    157  1.1  christos 
    158  1.1  christos 	wfd = initdevice(dev, 5);
    159  1.1  christos 	if (wfd == -1)
    160  1.1  christos 		return -1;
    161  1.1  christos 	return send_packet(wfd, mtu, ip, gwip);
    162  1.1  christos }
    163  1.1  christos 
    164  1.1  christos void
    165  1.1  christos udpcksum(ip_t *ip, struct udphdr *udp, int len)
    166  1.1  christos {
    167  1.1  christos 	union pseudoh {
    168  1.1  christos 		struct hdr {
    169  1.1  christos 			u_short len;
    170  1.1  christos 			u_char ttl;
    171  1.1  christos 			u_char proto;
    172  1.1  christos 			u_32_t src;
    173  1.1  christos 			u_32_t dst;
    174  1.1  christos 		} h;
    175  1.1  christos 		u_short w[6];
    176  1.1  christos 	} ph;
    177  1.1  christos 	u_32_t temp32;
    178  1.1  christos 	u_short *opts;
    179  1.1  christos 
    180  1.1  christos 	ph.h.len = htons(len);
    181  1.1  christos 	ph.h.ttl = 0;
    182  1.1  christos 	ph.h.proto = IPPROTO_UDP;
    183  1.1  christos 	ph.h.src = ip->ip_src.s_addr;
    184  1.1  christos 	ph.h.dst = ip->ip_dst.s_addr;
    185  1.1  christos 	temp32 = 0;
    186  1.1  christos 	opts = &ph.w[0];
    187  1.1  christos 	temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5];
    188  1.1  christos 	temp32 = (temp32 >> 16) + (temp32 & 65535);
    189  1.1  christos 	temp32 += (temp32 >> 16);
    190  1.1  christos 	udp->uh_sum = temp32 & 65535;
    191  1.1  christos 	udp->uh_sum = chksum((u_short *)udp, len);
    192  1.1  christos 	if (udp->uh_sum == 0)
    193  1.1  christos 		udp->uh_sum = 0xffff;
    194  1.1  christos }
    195  1.1  christos 
    196  1.1  christos int main(argc, argv)
    197  1.1  christos 	int	argc;
    198  1.1  christos 	char	**argv;
    199  1.1  christos {
    200  1.1  christos 	FILE	*langfile = NULL;
    201  1.1  christos 	struct	in_addr	gwip;
    202  1.1  christos 	tcphdr_t	*tcp;
    203  1.1  christos 	udphdr_t	*udp;
    204  1.1  christos 	ip_t	*ip;
    205  1.1  christos 	char	*name =  argv[0], host[MAXHOSTNAMELEN + 1];
    206  1.1  christos 	char	*gateway = NULL, *dev = NULL;
    207  1.1  christos 	char	*src = NULL, *dst, *s;
    208  1.1  christos 	int	mtu = 1500, olen = 0, c, nonl = 0;
    209  1.1  christos 
    210  1.1  christos 	/*
    211  1.1  christos 	 * 65535 is maximum packet size...you never know...
    212  1.1  christos 	 */
    213  1.1  christos 	ip = (ip_t *)calloc(1, 65536);
    214  1.1  christos 	tcp = (tcphdr_t *)(ip + 1);
    215  1.1  christos 	udp = (udphdr_t *)tcp;
    216  1.1  christos 	ip->ip_len = sizeof(*ip);
    217  1.1  christos 	IP_HL_A(ip, sizeof(*ip) >> 2);
    218  1.1  christos 
    219  1.1  christos 	while ((c = getopt(argc, argv, "I:L:P:TUdf:i:g:m:o:s:t:vw:")) != -1) {
    220  1.1  christos 		switch (c)
    221  1.1  christos 		{
    222  1.1  christos 		case 'I' :
    223  1.1  christos 			nonl++;
    224  1.1  christos 			if (ip->ip_p)
    225  1.1  christos 			    {
    226  1.1  christos 				fprintf(stderr, "Protocol already set: %d\n",
    227  1.1  christos 					ip->ip_p);
    228  1.1  christos 				break;
    229  1.1  christos 			    }
    230  1.1  christos 			do_icmp(ip, optarg);
    231  1.1  christos 			break;
    232  1.1  christos 		case 'L' :
    233  1.1  christos 			if (nonl) {
    234  1.1  christos 				fprintf(stderr,
    235  1.1  christos 					"Incorrect usage of -L option.\n");
    236  1.1  christos 				usage(name);
    237  1.1  christos 			}
    238  1.1  christos 			if (!strcmp(optarg, "-"))
    239  1.1  christos 				langfile = stdin;
    240  1.1  christos 			else if (!(langfile = fopen(optarg, "r"))) {
    241  1.1  christos 				fprintf(stderr, "can't open file %s\n",
    242  1.1  christos 					optarg);
    243  1.1  christos 				exit(1);
    244  1.1  christos 			}
    245  1.1  christos 			iplang(langfile);
    246  1.1  christos 			return 0;
    247  1.1  christos 		case 'P' :
    248  1.1  christos 		    {
    249  1.1  christos 			struct	protoent	*p;
    250  1.1  christos 
    251  1.1  christos 			nonl++;
    252  1.1  christos 			if (ip->ip_p)
    253  1.1  christos 			    {
    254  1.1  christos 				fprintf(stderr, "Protocol already set: %d\n",
    255  1.1  christos 					ip->ip_p);
    256  1.1  christos 				break;
    257  1.1  christos 			    }
    258  1.1  christos 			if ((p = getprotobyname(optarg)))
    259  1.1  christos 				ip->ip_p = p->p_proto;
    260  1.1  christos 			else
    261  1.1  christos 				fprintf(stderr, "Unknown protocol: %s\n",
    262  1.1  christos 					optarg);
    263  1.1  christos 			break;
    264  1.1  christos 		    }
    265  1.1  christos 		case 'T' :
    266  1.1  christos 			nonl++;
    267  1.1  christos 			if (ip->ip_p)
    268  1.1  christos 			    {
    269  1.1  christos 				fprintf(stderr, "Protocol already set: %d\n",
    270  1.1  christos 					ip->ip_p);
    271  1.1  christos 				break;
    272  1.1  christos 			    }
    273  1.1  christos 			ip->ip_p = IPPROTO_TCP;
    274  1.1  christos 			ip->ip_len += sizeof(tcphdr_t);
    275  1.1  christos 			break;
    276  1.1  christos 		case 'U' :
    277  1.1  christos 			nonl++;
    278  1.1  christos 			if (ip->ip_p)
    279  1.1  christos 			    {
    280  1.1  christos 				fprintf(stderr, "Protocol already set: %d\n",
    281  1.1  christos 					ip->ip_p);
    282  1.1  christos 				break;
    283  1.1  christos 			    }
    284  1.1  christos 			ip->ip_p = IPPROTO_UDP;
    285  1.1  christos 			ip->ip_len += sizeof(udphdr_t);
    286  1.1  christos 			break;
    287  1.1  christos 		case 'd' :
    288  1.1  christos 			opts |= OPT_DEBUG;
    289  1.1  christos 			break;
    290  1.1  christos 		case 'f' :
    291  1.1  christos 			nonl++;
    292  1.1  christos 			ip->ip_off = strtol(optarg, NULL, 0);
    293  1.1  christos 			break;
    294  1.1  christos 		case 'g' :
    295  1.1  christos 			nonl++;
    296  1.1  christos 			gateway = optarg;
    297  1.1  christos 			break;
    298  1.1  christos 		case 'i' :
    299  1.1  christos 			nonl++;
    300  1.1  christos 			dev = optarg;
    301  1.1  christos 			break;
    302  1.1  christos 		case 'm' :
    303  1.1  christos 			nonl++;
    304  1.1  christos 			mtu = atoi(optarg);
    305  1.1  christos 			if (mtu < 28)
    306  1.1  christos 			    {
    307  1.1  christos 				fprintf(stderr, "mtu must be > 28\n");
    308  1.1  christos 				exit(1);
    309  1.1  christos 			    }
    310  1.1  christos 			break;
    311  1.1  christos 		case 'o' :
    312  1.1  christos 			nonl++;
    313  1.1  christos 			olen = buildopts(optarg, options, (IP_HL(ip) - 5) << 2);
    314  1.1  christos 			break;
    315  1.1  christos 		case 's' :
    316  1.1  christos 			nonl++;
    317  1.1  christos 			src = optarg;
    318  1.1  christos 			break;
    319  1.1  christos 		case 't' :
    320  1.1  christos 			nonl++;
    321  1.1  christos 			if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
    322  1.1  christos 				tcp->th_dport = htons(atoi(optarg));
    323  1.1  christos 			break;
    324  1.1  christos 		case 'v' :
    325  1.1  christos 			opts |= OPT_VERBOSE;
    326  1.1  christos 			break;
    327  1.1  christos 		case 'w' :
    328  1.1  christos 			nonl++;
    329  1.1  christos 			if (ip->ip_p == IPPROTO_TCP)
    330  1.1  christos 				tcp->th_win = atoi(optarg);
    331  1.1  christos 			else
    332  1.1  christos 				fprintf(stderr, "set protocol to TCP first\n");
    333  1.1  christos 			break;
    334  1.1  christos 		default :
    335  1.1  christos 			fprintf(stderr, "Unknown option \"%c\"\n", c);
    336  1.1  christos 			usage(name);
    337  1.1  christos 		}
    338  1.1  christos 	}
    339  1.1  christos 
    340  1.1  christos 	if (argc - optind < 1)
    341  1.1  christos 		usage(name);
    342  1.1  christos 	dst = argv[optind++];
    343  1.1  christos 
    344  1.1  christos 	if (!src)
    345  1.1  christos 	    {
    346  1.1  christos 		gethostname(host, sizeof(host));
    347  1.1  christos 		src = host;
    348  1.1  christos 	    }
    349  1.1  christos 
    350  1.1  christos 	if (resolve(src, (char *)&ip->ip_src) == -1)
    351  1.1  christos 	    {
    352  1.1  christos 		fprintf(stderr,"Cant resolve %s\n", src);
    353  1.1  christos 		exit(2);
    354  1.1  christos 	    }
    355  1.1  christos 
    356  1.1  christos 	if (resolve(dst, (char *)&ip->ip_dst) == -1)
    357  1.1  christos 	    {
    358  1.1  christos 		fprintf(stderr,"Cant resolve %s\n", dst);
    359  1.1  christos 		exit(2);
    360  1.1  christos 	    }
    361  1.1  christos 
    362  1.1  christos 	if (!gateway)
    363  1.1  christos 		gwip = ip->ip_dst;
    364  1.1  christos 	else if (resolve(gateway, (char *)&gwip) == -1)
    365  1.1  christos 	    {
    366  1.1  christos 		fprintf(stderr,"Cant resolve %s\n", gateway);
    367  1.1  christos 		exit(2);
    368  1.1  christos 	    }
    369  1.1  christos 
    370  1.1  christos 	if (olen)
    371  1.1  christos 	    {
    372  1.1  christos 		int hlen;
    373  1.1  christos 		char *p;
    374  1.1  christos 
    375  1.1  christos 		printf("Options: %d\n", olen);
    376  1.1  christos 		hlen = sizeof(*ip) + olen;
    377  1.1  christos 		IP_HL_A(ip, hlen >> 2);
    378  1.1  christos 		ip->ip_len += olen;
    379  1.1  christos 		p = (char *)malloc(65536);
    380  1.1  christos 		if (p == NULL)
    381  1.1  christos 		    {
    382  1.1  christos 			fprintf(stderr, "malloc failed\n");
    383  1.1  christos 			exit(2);
    384  1.1  christos 		    }
    385  1.1  christos 
    386  1.1  christos 		bcopy(ip, p, sizeof(*ip));
    387  1.1  christos 		bcopy(options, p + sizeof(*ip), olen);
    388  1.1  christos 		bcopy(ip + 1, p + hlen, ip->ip_len - hlen);
    389  1.1  christos 		ip = (ip_t *)p;
    390  1.1  christos 
    391  1.1  christos 		if (ip->ip_p == IPPROTO_TCP) {
    392  1.1  christos 			tcp = (tcphdr_t *)(p + hlen);
    393  1.1  christos 		} else if (ip->ip_p == IPPROTO_UDP) {
    394  1.1  christos 			udp = (udphdr_t *)(p + hlen);
    395  1.1  christos 		}
    396  1.1  christos 	    }
    397  1.1  christos 
    398  1.1  christos 	if (ip->ip_p == IPPROTO_TCP)
    399  1.1  christos 		for (s = argv[optind]; s && (c = *s); s++)
    400  1.1  christos 			switch(c)
    401  1.1  christos 			{
    402  1.1  christos 			case 'S' : case 's' :
    403  1.1  christos 				tcp->th_flags |= TH_SYN;
    404  1.1  christos 				break;
    405  1.1  christos 			case 'A' : case 'a' :
    406  1.1  christos 				tcp->th_flags |= TH_ACK;
    407  1.1  christos 				break;
    408  1.1  christos 			case 'F' : case 'f' :
    409  1.1  christos 				tcp->th_flags |= TH_FIN;
    410  1.1  christos 				break;
    411  1.1  christos 			case 'R' : case 'r' :
    412  1.1  christos 				tcp->th_flags |= TH_RST;
    413  1.1  christos 				break;
    414  1.1  christos 			case 'P' : case 'p' :
    415  1.1  christos 				tcp->th_flags |= TH_PUSH;
    416  1.1  christos 				break;
    417  1.1  christos 			case 'U' : case 'u' :
    418  1.1  christos 				tcp->th_flags |= TH_URG;
    419  1.1  christos 				break;
    420  1.1  christos 			}
    421  1.1  christos 
    422  1.1  christos 	if (!dev)
    423  1.1  christos 		dev = default_device;
    424  1.1  christos 	printf("Device:  %s\n", dev);
    425  1.1  christos 	printf("Source:  %s\n", inet_ntoa(ip->ip_src));
    426  1.1  christos 	printf("Dest:    %s\n", inet_ntoa(ip->ip_dst));
    427  1.1  christos 	printf("Gateway: %s\n", inet_ntoa(gwip));
    428  1.1  christos 	if (ip->ip_p == IPPROTO_TCP && tcp->th_flags)
    429  1.1  christos 		printf("Flags:   %#x\n", tcp->th_flags);
    430  1.1  christos 	printf("mtu:     %d\n", mtu);
    431  1.1  christos 
    432  1.1  christos 	if (ip->ip_p == IPPROTO_UDP) {
    433  1.1  christos 		udp->uh_sum = 0;
    434  1.1  christos 		udpcksum(ip, udp, ip->ip_len - (IP_HL(ip) << 2));
    435  1.1  christos 	}
    436  1.1  christos #ifdef	DOSOCKET
    437  1.1  christos 	if (ip->ip_p == IPPROTO_TCP && tcp->th_dport)
    438  1.1  christos 		return do_socket(dev, mtu, ip, gwip);
    439  1.1  christos #endif
    440  1.1  christos 	return send_packets(dev, mtu, ip, gwip);
    441  1.1  christos }
    442