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