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