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