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