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