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 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 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 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 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