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) 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 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 void do_icmp(ip, args) 75 ip_t *ip; 76 char *args; 77 { 78 struct icmp *ic; 79 char *s; 80 81 ip->ip_p = IPPROTO_ICMP; 82 ip->ip_len += sizeof(*ic); 83 ic = (struct icmp *)(ip + 1); 84 bzero((char *)ic, sizeof(*ic)); 85 if (!(s = strchr(args, ','))) 86 { 87 fprintf(stderr, "ICMP args missing: ,\n"); 88 return; 89 } 90 *s++ = '\0'; 91 ic->icmp_type = atoi(args); 92 ic->icmp_code = atoi(s); 93 if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ',')) 94 { 95 char *t; 96 97 t = strtok(s, ","); 98 t = strtok(NULL, ","); 99 if (resolve(t, (char *)&ic->icmp_gwaddr) == -1) 100 { 101 fprintf(stderr,"Cant resolve %s\n", t); 102 exit(2); 103 } 104 if ((t = strtok(NULL, ","))) 105 { 106 if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1) 107 { 108 fprintf(stderr,"Cant resolve %s\n", t); 109 exit(2); 110 } 111 if ((t = strtok(NULL, ","))) 112 { 113 if (resolve(t, 114 (char *)&ic->icmp_ip.ip_src) == -1) 115 { 116 fprintf(stderr,"Cant resolve %s\n", t); 117 exit(2); 118 } 119 } 120 } 121 } 122 } 123 124 125 int send_packets(dev, mtu, ip, gwip) 126 char *dev; 127 int mtu; 128 ip_t *ip; 129 struct in_addr gwip; 130 { 131 int wfd; 132 133 wfd = initdevice(dev, 5); 134 if (wfd == -1) 135 return -1; 136 return send_packet(wfd, mtu, ip, gwip); 137 } 138 139 void 140 udpcksum(ip_t *ip, struct udphdr *udp, int len) 141 { 142 union pseudoh { 143 struct hdr { 144 u_short len; 145 u_char ttl; 146 u_char proto; 147 u_32_t src; 148 u_32_t dst; 149 } h; 150 u_short w[6]; 151 } ph; 152 u_32_t temp32; 153 u_short *opts; 154 155 ph.h.len = htons(len); 156 ph.h.ttl = 0; 157 ph.h.proto = IPPROTO_UDP; 158 ph.h.src = ip->ip_src.s_addr; 159 ph.h.dst = ip->ip_dst.s_addr; 160 temp32 = 0; 161 opts = &ph.w[0]; 162 temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5]; 163 temp32 = (temp32 >> 16) + (temp32 & 65535); 164 temp32 += (temp32 >> 16); 165 udp->uh_sum = temp32 & 65535; 166 udp->uh_sum = chksum((u_short *)udp, len); 167 if (udp->uh_sum == 0) 168 udp->uh_sum = 0xffff; 169 } 170 171 int main(argc, argv) 172 int argc; 173 char **argv; 174 { 175 FILE *langfile = NULL; 176 struct in_addr gwip; 177 tcphdr_t *tcp; 178 udphdr_t *udp; 179 ip_t *ip; 180 char *name = argv[0], host[MAXHOSTNAMELEN + 1]; 181 char *gateway = NULL, *dev = NULL; 182 char *src = NULL, *dst, *s; 183 int mtu = 1500, olen = 0, c, nonl = 0; 184 185 /* 186 * 65535 is maximum packet size...you never know... 187 */ 188 ip = (ip_t *)calloc(1, 65536); 189 tcp = (tcphdr_t *)(ip + 1); 190 udp = (udphdr_t *)tcp; 191 ip->ip_len = sizeof(*ip); 192 IP_HL_A(ip, sizeof(*ip) >> 2); 193 194 while ((c = getopt(argc, argv, "I:L:P:TUdf:i:g:m:o:s:t:vw:")) != -1) { 195 switch (c) 196 { 197 case 'I' : 198 nonl++; 199 if (ip->ip_p) 200 { 201 fprintf(stderr, "Protocol already set: %d\n", 202 ip->ip_p); 203 break; 204 } 205 do_icmp(ip, optarg); 206 break; 207 case 'L' : 208 if (nonl) { 209 fprintf(stderr, 210 "Incorrect usage of -L option.\n"); 211 usage(name); 212 } 213 if (!strcmp(optarg, "-")) 214 langfile = stdin; 215 else if (!(langfile = fopen(optarg, "r"))) { 216 fprintf(stderr, "can't open file %s\n", 217 optarg); 218 exit(1); 219 } 220 iplang(langfile); 221 return 0; 222 case 'P' : 223 { 224 struct protoent *p; 225 226 nonl++; 227 if (ip->ip_p) 228 { 229 fprintf(stderr, "Protocol already set: %d\n", 230 ip->ip_p); 231 break; 232 } 233 if ((p = getprotobyname(optarg))) 234 ip->ip_p = p->p_proto; 235 else 236 fprintf(stderr, "Unknown protocol: %s\n", 237 optarg); 238 break; 239 } 240 case 'T' : 241 nonl++; 242 if (ip->ip_p) 243 { 244 fprintf(stderr, "Protocol already set: %d\n", 245 ip->ip_p); 246 break; 247 } 248 ip->ip_p = IPPROTO_TCP; 249 ip->ip_len += sizeof(tcphdr_t); 250 break; 251 case 'U' : 252 nonl++; 253 if (ip->ip_p) 254 { 255 fprintf(stderr, "Protocol already set: %d\n", 256 ip->ip_p); 257 break; 258 } 259 ip->ip_p = IPPROTO_UDP; 260 ip->ip_len += sizeof(udphdr_t); 261 break; 262 case 'd' : 263 opts |= OPT_DEBUG; 264 break; 265 case 'f' : 266 nonl++; 267 ip->ip_off = strtol(optarg, NULL, 0); 268 break; 269 case 'g' : 270 nonl++; 271 gateway = optarg; 272 break; 273 case 'i' : 274 nonl++; 275 dev = optarg; 276 break; 277 case 'm' : 278 nonl++; 279 mtu = atoi(optarg); 280 if (mtu < 28) 281 { 282 fprintf(stderr, "mtu must be > 28\n"); 283 exit(1); 284 } 285 break; 286 case 'o' : 287 nonl++; 288 olen = buildopts(optarg, options, (IP_HL(ip) - 5) << 2); 289 break; 290 case 's' : 291 nonl++; 292 src = optarg; 293 break; 294 case 't' : 295 nonl++; 296 if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) 297 tcp->th_dport = htons(atoi(optarg)); 298 break; 299 case 'v' : 300 opts |= OPT_VERBOSE; 301 break; 302 case 'w' : 303 nonl++; 304 if (ip->ip_p == IPPROTO_TCP) 305 tcp->th_win = atoi(optarg); 306 else 307 fprintf(stderr, "set protocol to TCP first\n"); 308 break; 309 default : 310 fprintf(stderr, "Unknown option \"%c\"\n", c); 311 usage(name); 312 } 313 } 314 315 if (argc - optind < 1) 316 usage(name); 317 dst = argv[optind++]; 318 319 if (!src) 320 { 321 gethostname(host, sizeof(host)); 322 src = host; 323 } 324 325 if (resolve(src, (char *)&ip->ip_src) == -1) 326 { 327 fprintf(stderr,"Cant resolve %s\n", src); 328 exit(2); 329 } 330 331 if (resolve(dst, (char *)&ip->ip_dst) == -1) 332 { 333 fprintf(stderr,"Cant resolve %s\n", dst); 334 exit(2); 335 } 336 337 if (!gateway) 338 gwip = ip->ip_dst; 339 else if (resolve(gateway, (char *)&gwip) == -1) 340 { 341 fprintf(stderr,"Cant resolve %s\n", gateway); 342 exit(2); 343 } 344 345 if (olen) 346 { 347 int hlen; 348 char *p; 349 350 printf("Options: %d\n", olen); 351 hlen = sizeof(*ip) + olen; 352 IP_HL_A(ip, hlen >> 2); 353 ip->ip_len += olen; 354 p = (char *)malloc(65536); 355 if (p == NULL) 356 { 357 fprintf(stderr, "malloc failed\n"); 358 exit(2); 359 } 360 361 bcopy(ip, p, sizeof(*ip)); 362 bcopy(options, p + sizeof(*ip), olen); 363 bcopy(ip + 1, p + hlen, ip->ip_len - hlen); 364 ip = (ip_t *)p; 365 366 if (ip->ip_p == IPPROTO_TCP) { 367 tcp = (tcphdr_t *)(p + hlen); 368 } else if (ip->ip_p == IPPROTO_UDP) { 369 udp = (udphdr_t *)(p + hlen); 370 } 371 } 372 373 if (ip->ip_p == IPPROTO_TCP) 374 for (s = argv[optind]; s && (c = *s); s++) 375 switch(c) 376 { 377 case 'S' : case 's' : 378 tcp->th_flags |= TH_SYN; 379 break; 380 case 'A' : case 'a' : 381 tcp->th_flags |= TH_ACK; 382 break; 383 case 'F' : case 'f' : 384 tcp->th_flags |= TH_FIN; 385 break; 386 case 'R' : case 'r' : 387 tcp->th_flags |= TH_RST; 388 break; 389 case 'P' : case 'p' : 390 tcp->th_flags |= TH_PUSH; 391 break; 392 case 'U' : case 'u' : 393 tcp->th_flags |= TH_URG; 394 break; 395 } 396 397 if (!dev) 398 dev = default_device; 399 printf("Device: %s\n", dev); 400 printf("Source: %s\n", inet_ntoa(ip->ip_src)); 401 printf("Dest: %s\n", inet_ntoa(ip->ip_dst)); 402 printf("Gateway: %s\n", inet_ntoa(gwip)); 403 if (ip->ip_p == IPPROTO_TCP && tcp->th_flags) 404 printf("Flags: %#x\n", tcp->th_flags); 405 printf("mtu: %d\n", mtu); 406 407 if (ip->ip_p == IPPROTO_UDP) { 408 udp->uh_sum = 0; 409 udpcksum(ip, udp, ip->ip_len - (IP_HL(ip) << 2)); 410 } 411 #ifdef DOSOCKET 412 if (ip->ip_p == IPPROTO_TCP && tcp->th_dport) 413 return do_socket(dev, mtu, ip, gwip); 414 #endif 415 return send_packets(dev, mtu, ip, gwip); 416 } 417