HAMMER: Mass storage flush command support
[dragonfly.git] / contrib / ipfilter / ipsend / ipsend.c
blob221214dc72f27691b7d80c145f12fe05fc0efa84
1 /* $FreeBSD: src/contrib/ipfilter/ipsend/ipsend.c,v 1.4.2.6 2004/07/04 09:24:40 darrenr Exp $ */
2 /* $DragonFly: src/contrib/ipfilter/ipsend/ipsend.c,v 1.4 2004/07/28 00:49:54 hmp Exp $ */
3 /*
4 * ipsend.c (C) 1995-1998 Darren Reed
6 * This was written to test what size TCP fragments would get through
7 * various TCP/IP packet filters, as used in IP firewalls. In certain
8 * conditions, enough of the TCP header is missing for unpredictable
9 * results unless the filter is aware that this can happen.
11 * See the IPFILTER.LICENCE file for details on licencing.
13 #if defined(__sgi) && (IRIX > 602)
14 # include <sys/ptimers.h>
15 #endif
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <netdb.h>
20 #include <string.h>
21 #include <sys/param.h>
22 #include <sys/types.h>
23 #include <sys/time.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <netinet/in_systm.h>
28 #include <netinet/ip.h>
29 #include <netinet/ip_var.h>
30 #include <netinet/tcp.h>
31 #include <netinet/udp.h>
32 #include <netinet/udp_var.h>
33 #include <netinet/ip_icmp.h>
34 #ifndef linux
35 #include <netinet/ip_var.h>
36 #endif
37 #include "ipsend.h"
39 #if !defined(lint)
40 static const char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed";
41 static const char rcsid[] = "@(#)$Id: ipsend.c,v 2.2.2.6 2002/12/06 11:40:35 darrenr Exp $";
42 #endif
45 extern char *optarg;
46 extern int optind;
47 extern void iplang __P((FILE *));
49 char options[68];
50 int opts;
51 #ifdef linux
52 char default_device[] = "eth0";
53 #else
54 # ifdef sun
55 char default_device[] = "le0";
56 # else
57 # ifdef ultrix
58 char default_device[] = "ln0";
59 # else
60 # ifdef __bsdi__
61 char default_device[] = "ef0";
62 # else
63 # ifdef __sgi
64 char default_device[] = "ec0";
65 # else
66 char default_device[] = "lan0";
67 # endif
68 # endif
69 # endif
70 # endif
71 #endif
74 static void usage __P((char *));
75 static void do_icmp __P((ip_t *, char *));
76 void udpcksum(ip_t *, struct udphdr *, int);
77 int main __P((int, char **));
80 static void usage(prog)
81 char *prog;
83 fprintf(stderr, "Usage: %s [options] dest [flags]\n\
84 \toptions:\n\
85 \t\t-d\tdebug mode\n\
86 \t\t-i device\tSend out on this device\n\
87 \t\t-f fragflags\tcan set IP_MF or IP_DF\n\
88 \t\t-g gateway\tIP gateway to use if non-local dest.\n\
89 \t\t-I code,type[,gw[,dst[,src]]]\tSet ICMP protocol\n\
90 \t\t-m mtu\t\tfake MTU to use when sending out\n\
91 \t\t-P protocol\tSet protocol by name\n\
92 \t\t-s src\t\tsource address for IP packet\n\
93 \t\t-T\t\tSet TCP protocol\n\
94 \t\t-t port\t\tdestination port\n\
95 \t\t-U\t\tSet UDP protocol\n\
96 \t\t-v\tverbose mode\n\
97 \t\t-w <window>\tSet the TCP window size\n\
98 ", prog);
99 fprintf(stderr, "Usage: %s [-dv] -L <filename>\n\
100 \toptions:\n\
101 \t\t-d\tdebug mode\n\
102 \t\t-L filename\tUse IP language for sending packets\n\
103 \t\t-v\tverbose mode\n\
104 ", prog);
105 exit(1);
109 static void do_icmp(ip, args)
110 ip_t *ip;
111 char *args;
113 struct icmp *ic;
114 char *s;
116 ip->ip_p = IPPROTO_ICMP;
117 ip->ip_len += sizeof(*ic);
118 ic = (struct icmp *)(ip + 1);
119 bzero((char *)ic, sizeof(*ic));
120 if (!(s = strchr(args, ',')))
122 fprintf(stderr, "ICMP args missing: ,\n");
123 return;
125 *s++ = '\0';
126 ic->icmp_type = atoi(args);
127 ic->icmp_code = atoi(s);
128 if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ','))
130 char *t;
132 t = strtok(s, ",");
133 t = strtok(NULL, ",");
134 if (resolve(t, (char *)&ic->icmp_gwaddr) == -1)
136 fprintf(stderr,"Cant resolve %s\n", t);
137 exit(2);
139 if ((t = strtok(NULL, ",")))
141 if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1)
143 fprintf(stderr,"Cant resolve %s\n", t);
144 exit(2);
146 if ((t = strtok(NULL, ",")))
148 if (resolve(t,
149 (char *)&ic->icmp_ip.ip_src) == -1)
151 fprintf(stderr,"Cant resolve %s\n", t);
152 exit(2);
160 int send_packets(dev, mtu, ip, gwip)
161 char *dev;
162 int mtu;
163 ip_t *ip;
164 struct in_addr gwip;
166 u_short sport = 0;
167 int wfd;
169 if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
170 sport = ((struct tcpiphdr *)ip)->ti_sport;
171 wfd = initdevice(dev, sport, 5);
173 return send_packet(wfd, mtu, ip, gwip);
176 void
177 udpcksum(ip_t *ip, struct udphdr *udp, int len)
179 union pseudoh {
180 struct hdr {
181 u_short len;
182 u_char ttl;
183 u_char proto;
184 u_32_t src;
185 u_32_t dst;
186 } h;
187 u_short w[6];
188 } ph;
189 u_32_t temp32;
190 u_short cksum, *opts;
192 ph.h.len = htons(len);
193 ph.h.ttl = 0;
194 ph.h.proto = IPPROTO_UDP;
195 ph.h.src = ip->ip_src.s_addr;
196 ph.h.dst = ip->ip_dst.s_addr;
197 temp32 = 0;
198 opts = &ph.w[0];
199 temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5];
200 temp32 = (temp32 >> 16) + (temp32 & 65535);
201 temp32 += (temp32 >> 16);
202 udp->uh_sum = temp32 & 65535;
203 udp->uh_sum = chksum((u_short *)udp, len);
204 if (udp->uh_sum == 0)
205 udp->uh_sum = 0xffff;
208 int main(argc, argv)
209 int argc;
210 char **argv;
212 FILE *langfile = NULL;
213 struct tcpiphdr *ti;
214 struct udpiphdr *ui;
215 struct in_addr gwip;
216 tcphdr_t *tcp;
217 udphdr_t *udp;
218 ip_t *ip;
219 char *name = argv[0], host[MAXHOSTNAMELEN + 1];
220 char *gateway = NULL, *dev = NULL;
221 char *src = NULL, *dst, *s;
222 int mtu = 1500, olen = 0, c, nonl = 0;
225 * 65535 is maximum packet size...you never know...
227 ip = (ip_t *)calloc(1, 65536);
228 ti = (struct tcpiphdr *)ip;
229 ui = (struct udpiphdr *)ip;
230 tcp = (tcphdr_t *)&ti->ti_sport;
231 udp = (udphdr_t *)&ui->ui_sport;
232 ui->ui_ulen = htons(sizeof(*udp));
233 ip->ip_len = sizeof(*ip);
234 ip->ip_hl = sizeof(*ip) >> 2;
236 while ((c = getopt(argc, argv, "I:L:P:TUdf:i:g:m:o:s:t:vw:")) != -1)
237 switch (c)
239 case 'I' :
240 nonl++;
241 if (ip->ip_p)
243 fprintf(stderr, "Protocol already set: %d\n",
244 ip->ip_p);
245 break;
247 do_icmp(ip, optarg);
248 break;
249 case 'L' :
250 if (nonl) {
251 fprintf(stderr,
252 "Incorrect usage of -L option.\n");
253 usage(name);
255 if (!strcmp(optarg, "-"))
256 langfile = stdin;
257 else if (!(langfile = fopen(optarg, "r"))) {
258 fprintf(stderr, "can't open file %s\n",
259 optarg);
260 exit(1);
262 iplang(langfile);
263 return 0;
264 case 'P' :
266 struct protoent *p;
268 nonl++;
269 if (ip->ip_p)
271 fprintf(stderr, "Protocol already set: %d\n",
272 ip->ip_p);
273 break;
275 if ((p = getprotobyname(optarg)))
276 ip->ip_p = p->p_proto;
277 else
278 fprintf(stderr, "Unknown protocol: %s\n",
279 optarg);
280 break;
282 case 'T' :
283 nonl++;
284 if (ip->ip_p)
286 fprintf(stderr, "Protocol already set: %d\n",
287 ip->ip_p);
288 break;
290 ip->ip_p = IPPROTO_TCP;
291 ip->ip_len += sizeof(tcphdr_t);
292 break;
293 case 'U' :
294 nonl++;
295 if (ip->ip_p)
297 fprintf(stderr, "Protocol already set: %d\n",
298 ip->ip_p);
299 break;
301 ip->ip_p = IPPROTO_UDP;
302 ip->ip_len += sizeof(udphdr_t);
303 break;
304 case 'd' :
305 opts |= OPT_DEBUG;
306 break;
307 case 'f' :
308 nonl++;
309 ip->ip_off = strtol(optarg, NULL, 0);
310 break;
311 case 'g' :
312 nonl++;
313 gateway = optarg;
314 break;
315 case 'i' :
316 nonl++;
317 dev = optarg;
318 break;
319 case 'm' :
320 nonl++;
321 mtu = atoi(optarg);
322 if (mtu < 28)
324 fprintf(stderr, "mtu must be > 28\n");
325 exit(1);
327 break;
328 case 'o' :
329 nonl++;
330 olen = buildopts(optarg, options, (ip->ip_hl - 5) << 2);
331 break;
332 case 's' :
333 nonl++;
334 src = optarg;
335 break;
336 case 't' :
337 nonl++;
338 if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
339 tcp->th_dport = htons(atoi(optarg));
340 break;
341 case 'v' :
342 opts |= OPT_VERBOSE;
343 break;
344 case 'w' :
345 nonl++;
346 if (ip->ip_p == IPPROTO_TCP)
347 tcp->th_win = atoi(optarg);
348 else
349 fprintf(stderr, "set protocol to TCP first\n");
350 break;
351 default :
352 fprintf(stderr, "Unknown option \"%c\"\n", c);
353 usage(name);
356 if (argc - optind < 1)
357 usage(name);
358 dst = argv[optind++];
360 if (!src)
362 gethostname(host, sizeof(host));
363 src = host;
366 if (resolve(src, (char *)&ip->ip_src) == -1)
368 fprintf(stderr,"Cant resolve %s\n", src);
369 exit(2);
372 if (resolve(dst, (char *)&ip->ip_dst) == -1)
374 fprintf(stderr,"Cant resolve %s\n", dst);
375 exit(2);
378 if (!gateway)
379 gwip = ip->ip_dst;
380 else if (resolve(gateway, (char *)&gwip) == -1)
382 fprintf(stderr,"Cant resolve %s\n", gateway);
383 exit(2);
386 if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP) {
387 fprintf(stderr,"Unsupported protocol %d\n", ip->ip_p);
388 exit(2);
391 if (olen)
393 int hlen;
394 char *p;
396 printf("Options: %d\n", olen);
397 hlen = sizeof(*ip) + olen;
398 ip->ip_hl = hlen >> 2;
399 ip->ip_len += olen;
400 p = (char *)malloc(65536);
401 if(!p)
403 fprintf(stderr,"malloc failed\n");
404 exit(2);
406 bcopy(ip, p, sizeof(*ip));
407 bcopy(options, p + sizeof(*ip), olen);
408 bcopy(ip + 1, p + hlen, ip->ip_len - hlen);
409 ip = (ip_t *)p;
410 if (ip->ip_p == IPPROTO_TCP) {
411 tcp = (tcphdr_t *)((char *)ip + hlen);
412 } else {
413 udp = (udphdr_t *)((char *)ip + hlen);
417 if (ip->ip_p == IPPROTO_TCP)
418 for (s = argv[optind]; s && (c = *s); s++)
419 switch(c)
421 case 'S' : case 's' :
422 tcp->th_flags |= TH_SYN;
423 break;
424 case 'A' : case 'a' :
425 tcp->th_flags |= TH_ACK;
426 break;
427 case 'F' : case 'f' :
428 tcp->th_flags |= TH_FIN;
429 break;
430 case 'R' : case 'r' :
431 tcp->th_flags |= TH_RST;
432 break;
433 case 'P' : case 'p' :
434 tcp->th_flags |= TH_PUSH;
435 break;
436 case 'U' : case 'u' :
437 tcp->th_flags |= TH_URG;
438 break;
441 if (!dev)
442 dev = default_device;
443 printf("Device: %s\n", dev);
444 printf("Source: %s\n", inet_ntoa(ip->ip_src));
445 printf("Dest: %s\n", inet_ntoa(ip->ip_dst));
446 printf("Gateway: %s\n", inet_ntoa(gwip));
447 if (ip->ip_p == IPPROTO_TCP && tcp->th_flags)
448 printf("Flags: %#x\n", tcp->th_flags);
449 printf("mtu: %d\n", mtu);
451 if (ip->ip_p == IPPROTO_UDP) {
452 udp->uh_sum = 0;
453 udpcksum(ip, udp, (ip->ip_len) - (ip->ip_hl << 2));
455 #ifdef DOSOCKET
456 if (ip->ip_p == IPPROTO_TCP && tcp->th_dport)
457 return do_socket(dev, mtu, (struct tcpiphdr *)ip, gwip);
458 #endif
459 return send_packets(dev, mtu, ip, gwip);