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