Fix LINT64 build.
[dragonfly.git] / contrib / ipfilter / ipsend / ipsend.c
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
5  *
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.
10  *
11  * See the IPFILTER.LICENCE file for details on licencing.
12  */
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"
38
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
43
44
45 extern  char    *optarg;
46 extern  int     optind;
47 extern  void    iplang __P((FILE *));
48
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
72
73
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 **));
78
79
80 static  void    usage(prog)
81 char    *prog;
82 {
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);
106 }
107
108
109 static void do_icmp(ip, args)
110 ip_t *ip;
111 char *args;
112 {
113         struct  icmp    *ic;
114         char    *s;
115
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, ',')))
121             {
122                 fprintf(stderr, "ICMP args missing: ,\n");
123                 return;
124             }
125         *s++ = '\0';
126         ic->icmp_type = atoi(args);
127         ic->icmp_code = atoi(s);
128         if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ','))
129             {
130                 char    *t;
131
132                 t = strtok(s, ",");
133                 t = strtok(NULL, ",");
134                 if (resolve(t, (char *)&ic->icmp_gwaddr) == -1)
135                     {
136                         fprintf(stderr,"Cant resolve %s\n", t);
137                         exit(2);
138                     }
139                 if ((t = strtok(NULL, ",")))
140                     {
141                         if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1)
142                             {
143                                 fprintf(stderr,"Cant resolve %s\n", t);
144                                 exit(2);
145                             }
146                         if ((t = strtok(NULL, ",")))
147                             {
148                                 if (resolve(t,
149                                             (char *)&ic->icmp_ip.ip_src) == -1)
150                                     {
151                                         fprintf(stderr,"Cant resolve %s\n", t);
152                                         exit(2);
153                                     }
154                             }
155                     }
156             }
157 }
158
159
160 int send_packets(dev, mtu, ip, gwip)
161 char *dev;
162 int mtu;
163 ip_t *ip;
164 struct in_addr gwip;
165 {
166         u_short sport = 0;
167         int     wfd;
168
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);
172
173         return send_packet(wfd, mtu, ip, gwip);
174 }
175
176 void
177 udpcksum(ip_t *ip, struct udphdr *udp, int len)
178 {
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;
191
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;
206 }
207
208 int main(argc, argv)
209 int     argc;
210 char    **argv;
211 {
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;
223
224         /*
225          * 65535 is maximum packet size...you never know...
226          */
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;
235
236         while ((c = getopt(argc, argv, "I:L:P:TUdf:i:g:m:o:s:t:vw:")) != -1)
237                 switch (c)
238                 {
239                 case 'I' :
240                         nonl++;
241                         if (ip->ip_p)
242                             {
243                                 fprintf(stderr, "Protocol already set: %d\n",
244                                         ip->ip_p);
245                                 break;
246                             }
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);
254                         }
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);
261                         }
262                         iplang(langfile);
263                         return 0;
264                 case 'P' :
265                     {
266                         struct  protoent        *p;
267
268                         nonl++;
269                         if (ip->ip_p)
270                             {
271                                 fprintf(stderr, "Protocol already set: %d\n",
272                                         ip->ip_p);
273                                 break;
274                             }
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;
281                     }
282                 case 'T' :
283                         nonl++;
284                         if (ip->ip_p)
285                             {
286                                 fprintf(stderr, "Protocol already set: %d\n",
287                                         ip->ip_p);
288                                 break;
289                             }
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)
296                             {
297                                 fprintf(stderr, "Protocol already set: %d\n",
298                                         ip->ip_p);
299                                 break;
300                             }
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)
323                             {
324                                 fprintf(stderr, "mtu must be > 28\n");
325                                 exit(1);
326                             }
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);
354                 }
355
356         if (argc - optind < 1)
357                 usage(name);
358         dst = argv[optind++];
359
360         if (!src)
361             {
362                 gethostname(host, sizeof(host));
363                 src = host;
364             }
365
366         if (resolve(src, (char *)&ip->ip_src) == -1)
367             {
368                 fprintf(stderr,"Cant resolve %s\n", src);
369                 exit(2);
370             }
371
372         if (resolve(dst, (char *)&ip->ip_dst) == -1)
373             {
374                 fprintf(stderr,"Cant resolve %s\n", dst);
375                 exit(2);
376             }
377
378         if (!gateway)
379                 gwip = ip->ip_dst;
380         else if (resolve(gateway, (char *)&gwip) == -1)
381             {
382                 fprintf(stderr,"Cant resolve %s\n", gateway);
383                 exit(2);
384             }
385
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);
389         }
390
391         if (olen)
392             {
393                 int hlen;
394                 char *p;
395
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)
402                     {
403                         fprintf(stderr,"malloc failed\n");
404                         exit(2);
405                     } 
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);
414                 }
415             }
416
417         if (ip->ip_p == IPPROTO_TCP)
418                 for (s = argv[optind]; s && (c = *s); s++)
419                         switch(c)
420                         {
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;
439                         }
440
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);
450
451         if (ip->ip_p == IPPROTO_UDP) {
452                 udp->uh_sum = 0;
453                 udpcksum(ip, udp, (ip->ip_len) - (ip->ip_hl << 2));
454         }
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);
460 }