Home | History | Annotate | Line # | Download | only in ipsend
ipsend.c revision 1.1.1.2
      1      1.1  christos /*	$NetBSD: ipsend.c,v 1.1.1.2 2012/07/22 13:44:36 darrenr 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.1  christos static const char sccsid[] = "@(#)ipsend.c	1.5 12/10/95 (C)1995 Darren Reed";
     10  1.1.1.2   darrenr static 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