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