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