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