1 /* ------------------------------------------------------------------
2 * $Id: tcpip.c,v 1.15 1998/09/22 20:35:43 savage Exp $
3 * ------------------------------------------------------------------
4 */
5 static char *id = "$Id: tcpip.c,v 1.15 1998/09/22 20:35:43 savage Exp $";
6
7 #include "config.h"
8
9 /* The include files */
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in_systm.h>
13 #include <netinet/in.h>
14 #include <netinet/tcp.h>
15 #include <netinet/ip.h>
16 #include <arpa/inet.h>
17 #include <netdb.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <sys/utsname.h>
22 #include <string.h>
23 #include <fcntl.h>
24 #include <sys/ioctl.h>
25 #include <stdarg.h>
26 #include <net/if.h>
27
28 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
29 #include <err.h>
30 #include <errno.h>
31 #include <sysexits.h>
32 #endif
33
34 #include "tcpip.h"
35
36 /*-- LINUX routilng TABLES */
37 #ifdef LINUX
38 #include <linux/sockios.h> /* GLIBC don't have sockios.h? */
39 typedef struct
40 {
41 char ifname[17];
42 struct in_addr addr;
43 }
44 interfacerec;
45
46 typedef struct
47 {
48 struct in_addr addr;
49 unsigned long naddr; /* netmask */
50 interfacerec *iface;
51 }
52 routerec;
53
54 short numinterfaces, numroutes;
55 interfacerec *interfaces;
56 routerec *routes;
57 #endif /* LINUX */
58
59 #ifdef PCAP
60 #include <pcap.h>
61 pcap_t *PCapHdlr=NULL;
62 #endif
63
64 /* Standard Macro */
65 #ifndef MIN
66 #define MIN(x,y) (x<y) ? x : y;
67 #endif
68
69 int sendsock, readsock;
70 unsigned short ipident;
71
72 /* This function will determine the checksum for a specific packet. Used by */
73 /* nearly EVERYTHING on the internet */
74 unsigned short
inet_checksum(void * addr,int len)75 inet_checksum (void *addr, int len)
76 {
77 register int nleft = len;
78 register u_short *w = addr;
79 register int sum = 0;
80 u_short answer = 0;
81
82 /*
83 * Our algorithm is simple, using a 32 bit accumulator (sum),
84 * we add sequential 16 bit words to it, and at the end, fold
85 * back all the carry bits from the top 16 bits into the lower
86 * 16 bits.
87 */
88 while (nleft > 1)
89 {
90 sum += *w++;
91 nleft -= 2;
92 }
93
94 /* mop up an odd byte, if necessary */
95 if (nleft == 1)
96 {
97 *(u_char *) (&answer) = *(u_char *) w;
98 sum += answer;
99 }
100
101 /*
102 * add back carry outs from top 16 bits to low 16 bits
103 */
104 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
105 sum += (sum >> 16); /* add carry */
106 answer = ~sum; /* truncate to 16 bits */
107 return (answer);
108 }
109
110 struct psuedohdr {
111 struct in_addr source_address;
112 struct in_addr dest_address;
113 unsigned char place_holder;
114 unsigned char protocol;
115 unsigned short length;
116 } psuedohdr;
117
tcp_checksum(char * packet,int length,struct in_addr source_address,struct in_addr dest_address)118 unsigned short tcp_checksum(char *packet,
119 int length,
120 struct in_addr source_address,
121 struct in_addr dest_address)
122 {
123 char *psuedo_packet;
124 unsigned short cksum;
125
126 psuedohdr.protocol = IPPROTO_TCP;
127 psuedohdr.length = htons(length);
128 psuedohdr.place_holder = 0;
129
130 psuedohdr.source_address = source_address;
131 psuedohdr.dest_address = dest_address;
132
133 if((psuedo_packet = malloc(sizeof(psuedohdr) + length)) == NULL) {
134 perror("malloc");
135 exit(EXIT_FAILURE);
136 }
137
138 memcpy(psuedo_packet,&psuedohdr,sizeof(psuedohdr));
139 memcpy((psuedo_packet + sizeof(psuedohdr)),
140 packet,length);
141
142 cksum = inet_checksum((unsigned short *)psuedo_packet,(length + sizeof(psuedohdr)));
143 free(psuedo_packet);
144 return cksum;
145 }
146
147 /* This will resolve the host specified by host (either IP or domain name) */
148 /* and return the result in sa */
149 short
resolve_host(char * host,struct sockaddr_in * sa)150 resolve_host (char *host, struct sockaddr_in *sa)
151 {
152 struct hostent *ent;
153
154 if (!host[0])
155 {
156 fprintf (stderr, "error: unknown host %s\n", host);
157 return (-1);
158 }
159 memset (sa, 0, sizeof (struct sockaddr));
160 sa->sin_family = AF_INET;
161 sa->sin_addr.s_addr = inet_addr (host);
162 if ((long) inet_addr (host) == -1)
163 {
164 ent = gethostbyname (host);
165 if (ent != NULL)
166 {
167 sa->sin_family = ent->h_addrtype;
168 memcpy ((caddr_t) & sa->sin_addr, ent->h_addr, ent->h_length);
169 return (0);
170 }
171 else
172 {
173 fprintf (stderr, "error: unknown host %s\n", host);
174 return (-1);
175 }
176 }
177 return (0);
178 }
179
180 /* Sends a TCP packet */
181 void
sendtcp(spoofrec * spoof,unsigned short flags,short rep)182 sendtcp (spoofrec * spoof, unsigned short flags, short rep)
183 {
184 struct tcphdr tcp;
185 struct ip ip;
186 static char pkt[8192];
187 int i;
188
189 /*-- IP HDR --*/
190 ip.ip_hl = 5;
191 ip.ip_v = 4;
192 ip.ip_tos = 0;
193 #ifdef NEEDS_HTONS_IP_LEN
194 ip.ip_len = htons (40);
195 #else
196 ip.ip_len = 40;
197 #endif
198 ip.ip_id = htons (31337 + spoof->sport);
199 ip.ip_off = 0;
200 ip.ip_ttl = 255;
201 ip.ip_p = IPPROTO_TCP;
202 ip.ip_src = spoof->from.sin_addr;
203 ip.ip_dst = spoof->dest.sin_addr;
204 #ifdef HAVE_STRUCT_IP_CSUM
205 #define ip_sum ip_csum
206 #endif
207 ip.ip_sum = 0;
208 ip.ip_sum = inet_checksum ((void *) &ip, sizeof (ip));
209
210 /*-- TCP HDR --*/
211 tcp.th_sport = htons (spoof->sport);
212 tcp.th_dport = htons (spoof->dport);
213 tcp.th_seq = htonl (spoof->seq);
214 tcp.th_ack = 0;
215 #ifdef X2_OFF
216 tcp.th_x2_off = 0x50;
217 #else
218 tcp.th_x2 = 0;
219 tcp.th_off = 5;
220 #endif /* X2_OFF */
221 tcp.th_flags = flags;
222 tcp.th_win = htons (0x1234);
223 tcp.th_urp = 0;
224 tcp.th_sum = 0;
225
226 /*-- TCP Checksum --*/
227 #ifdef SOLARIS_CKSUM_BUG
228 tcp.th_sum = sizeof (struct tcphdr);
229 #else
230 tcp.th_sum = tcp_checksum ((char *) &tcp,
231 sizeof (struct tcphdr),
232 spoof->from.sin_addr,
233 spoof->dest.sin_addr);
234 #endif /* SOLARIS_CKSUM_BUG */
235
236 memcpy (pkt, (char *) &ip, sizeof (ip));
237 memcpy (pkt + sizeof (ip), (void *) &tcp, sizeof (tcp));
238
239 for (i = 0; i < rep; i++)
240 if (sendto (sendsock, (void *) pkt, sizeof (ip) + sizeof (tcp), 0, (struct sockaddr *) &spoof->dest, sizeof (spoof->dest)) < 0)
241 perror ("sending message");
242
243 }
244
245 /* Get's a TCP packet */
246 #define MAXSIZE 65535
247
248 short
gettcp(spoofrec * spoof,tcprec * dtcp)249 gettcp (spoofrec * spoof, tcprec * dtcp)
250 {
251 char buf[MAXSIZE], *p=buf;
252 tcprec *tcp;
253
254 #ifndef PCAP
255 int numread;
256
257 if ((numread = read (readsock, buf, MAXSIZE)) < 0)
258 return (0);
259
260 #else /* PCAP form tft.c by Lamont Granquist <lamontg@HITL.WASHINGTON.EDU> */
261
262 struct pcap_pkthdr head;
263 static int offset;
264 int datalink;
265
266 if( ! PCapHdlr ) {
267 fprintf(stderr, "Error: libpcap not initialised.\n");
268 return 0;
269 }
270
271 if((datalink = pcap_datalink(PCapHdlr)) < 0)
272 {
273 fprintf(stderr, "libpcap: no datalink info: %s\n", pcap_geterr(PCapHdlr));
274 return 0;
275 }
276
277 switch(datalink) {
278 case DLT_EN10MB:
279 offset = 14; break;
280 case DLT_NULL:
281 case DLT_PPP:
282 offset = 4; break;
283 case DLT_SLIP:
284 offset = 16; break;
285 case DLT_RAW:
286 offset = 0; break;
287 case DLT_SLIP_BSDOS:
288 case DLT_PPP_BSDOS:
289 offset = 24; break;
290 case DLT_ATM_RFC1483:
291 offset = 8; break;
292 case DLT_IEEE802:
293 offset = 22; break;
294 default:
295 fprintf(stderr, "unknown datalink type (%d)", datalink);
296 return(0);
297 }
298
299 p = (char *) pcap_next(PCapHdlr, &head);
300 if(!p)
301 return 0;
302
303 p+=offset;
304
305 #endif /* PCAP */
306
307 /* Check to see if it's an IP packet */
308 if ((p[0] >> 4) != 4)
309 return (0);
310
311 /* Check to see if it's a TCP packet */
312 if (p[9] != 6)
313 return (0);
314
315 tcp = (tcprec *) & p[20];
316 /* Check to see if it's from the correct host */
317 if (memcmp (&spoof->dest.sin_addr, &p[12], 4) != 0)
318 return (0);
319
320 memcpy ((void *) dtcp, (void *) tcp, sizeof (tcprec));
321 return (1);
322 }
323
324
325 /*-- Linux: Search out IP in Routing tables --*/
326 /*-- Other: Return hostname ip ---------------*/
327 struct in_addr
getlocalip(unsigned long dest)328 getlocalip (unsigned long dest)
329 {
330 static struct in_addr ina;
331 #ifdef LINUX /*---------------------------------------------- LINUX --*/
332 int i;
333
334 for (i = 0; i < numroutes; i++)
335 {
336 if ((dest & routes[i].naddr) == (unsigned long) routes[i].addr.s_addr)
337 {
338 return (routes[i].iface->addr);
339 }
340 }
341
342 /*------------------------------- FreeBSD / OpenBSD / NetBSD / BSDI --*/
343 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
344 /*
345 FreeBSD Ref: /usr/share/examples/find_interface/
346 */
347 struct sockaddr_in local, remote;
348 int s, rv, namelen;
349
350 remote.sin_addr.s_addr = dest;
351 remote.sin_port = htons(60000);
352 remote.sin_family = AF_INET;
353 remote.sin_len = sizeof remote;
354
355 local.sin_addr.s_addr = htonl(INADDR_ANY);
356 local.sin_port = htons(60000);
357 local.sin_family = AF_INET;
358 local.sin_len = sizeof local;
359
360 s = socket(PF_INET, SOCK_DGRAM, 0);
361 if (s < 0)
362 err(EX_OSERR, "socket");
363
364 do
365 {
366 rv = bind(s, (struct sockaddr *)&local, sizeof local);
367 local.sin_port = htons(ntohs(local.sin_port) + 1);
368 } while(rv < 0 && errno == EADDRINUSE);
369
370 if (rv < 0)
371 err(EX_OSERR, "bind");
372
373 do
374 {
375 rv = connect(s, (struct sockaddr *)&remote, sizeof remote);
376 remote.sin_port = htons(ntohs(remote.sin_port) + 1);
377 } while(rv < 0 && errno == EADDRINUSE);
378
379 if (rv < 0)
380 err(EX_OSERR, "bind");
381
382 do
383 {
384 rv = connect(s, (struct sockaddr *)&remote, sizeof remote);
385 remote.sin_port = htons(ntohs(remote.sin_port) + 1);
386 } while(rv < 0 && errno == EADDRINUSE);
387
388 if (rv < 0)
389 err(EX_OSERR, "connect");
390
391 namelen = sizeof local;
392 rv = getsockname(s, (struct sockaddr *)&local, &namelen);
393
394 if (rv < 0)
395 err(EX_OSERR, "getsockname");
396
397 return local.sin_addr;
398
399 #else /* !LINUX && !BSD ---------------------------------- OTHER --*/
400 struct sockaddr_in sin;
401 char myname[80];
402
403 if( gethostname(myname,sizeof(myname)-1) || resolve_host(myname,&sin) < 0) {
404 fprintf(stderr,"*** Unable to determine local IP from hostname\n");
405 } else {
406 return (sin.sin_addr);
407 }
408
409 #endif /* LINUX -------------------------------------------------------*/
410 ina.s_addr = 0;
411 return ina;
412 }
413
414 #ifdef LINUX
415 /*-- --*/
init_route_tables(void)416 void init_route_tables(void)
417 {
418 int ifsock, i, i1, found;
419 struct ifconf ifc;
420 struct ifreq *ifr;
421 char buf[1024], iface[16], *ptr;
422 FILE *f;
423
424 /* Create a channel to the NET kernel. */
425 if ((ifsock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
426 {
427 perror ("socket");
428 exit (EXIT_FAILURE);
429 }
430
431 ifc.ifc_len = sizeof (buf);
432 ifc.ifc_buf = buf;
433 if (ioctl (ifsock, SIOCGIFCONF, &ifc) < 0)
434 {
435 perror ("opening interface socket");
436 close (ifsock);
437 exit (EXIT_FAILURE);
438 }
439
440 numinterfaces = (ifc.ifc_len / sizeof (struct ifreq));
441 interfaces = (interfacerec *) malloc (numinterfaces * sizeof (interfacerec));
442
443 ifr = ifc.ifc_req;
444 for (i = 0; i < numinterfaces; i++, ifr++)
445 {
446 strcpy (interfaces[i].ifname, ifr->ifr_name);
447 memcpy (&interfaces[i].addr, &((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr, sizeof (struct in_addr));
448 if (ioctl (ifsock, SIOCGIFADDR, ifr) < 0)
449 printf ("Couldn't get address for %s\n", ifr->ifr_name);
450 }
451 close (ifsock);
452
453 if ((f = fopen ("/proc/net/route", "r")) == NULL)
454 {
455 perror ("opening /proc/net/route");
456 exit (EXIT_FAILURE);
457 }
458
459 numroutes = 0;
460 fgets (buf, sizeof (buf), f); /* strip out description line */
461 while (!feof (f))
462 {
463 fgets (buf, sizeof (buf), f);
464 numroutes++;
465 }
466 numroutes--;
467
468 routes = (routerec *) malloc (numroutes * sizeof (routerec));
469
470 rewind (f);
471
472 fgets (buf, sizeof (buf), f);
473 for (i = 0; i < numroutes; i++)
474 {
475 if (fgets (buf, sizeof (buf), f) == NULL)
476 {
477 /* Important, since an interface might have been removed since our counting,
478 causing us to parse bogus data */
479 fputs ("Error reading /proc/net/route: iface count mismatch\n", stderr);
480 fclose (f);
481 exit (EXIT_FAILURE);
482 }
483 if ( strlen (buf) == sizeof(buf)-1 )
484 {
485 /* skip long lines */
486 fputs ("Long (corrupt) line encountered, skipping.\n", stderr);
487 while ((fgets (buf, sizeof (buf), f)))
488 if (buf [strlen (buf) - 1] == '\n')
489 break;
490 continue; /* continue with next regular line (or fail if EOF */
491 }
492 ptr = strtok (buf, "\t ");
493 if (!ptr)
494 continue;
495 if (strlen (ptr) >= sizeof (iface))
496 continue; /* would overflow if fed with bogus data in a chroot()ed environment */
497 else
498 strcpy (iface, ptr);
499 ptr = strtok (NULL, "\t "); /* hack avoiding fscanf */
500 routes[i].addr.s_addr=(unsigned long)strtol(ptr,NULL,16);
501 for (i1 = 0; i1 < 6; i1++)
502 {
503 ptr = strtok (NULL, "\t "); /* ignore Gateway Flags RefCnt Use Metric */
504 }
505 if (!ptr) {
506 fputs ("Error parsing /proc/net/route\n", stderr);
507 continue;
508 }
509 routes[i].naddr=(unsigned long)strtol(ptr,NULL,16); /* Netmask */
510
511 found = 0;
512 for (i1 = 0; i1 < numinterfaces; i1++)
513 {
514 if (strcmp (interfaces[i1].ifname, iface) == 0)
515 {
516 routes[i].iface = &interfaces[i1];
517 found = 1;
518 }
519
520 }
521
522 if (!found)
523 {
524 printf ("Couldn't find interface %s\n", iface);
525 exit (EXIT_FAILURE);
526 }
527 }
528 fclose (f);
529 }
530 #endif /* LINUX */
531
532 #ifdef PCAP
init_pcap(char * cmdbuf)533 int init_pcap(char *cmdbuf) {
534
535 bpf_u_int32 localnet, netmask;
536 struct bpf_program fcode;
537 char ebuf[PCAP_ERRBUF_SIZE];
538 int i;
539 extern char *DEVICE;
540
541 i = pcap_snapshot(PCapHdlr);
542 if (pcap_lookupnet(DEVICE, &localnet, &netmask, ebuf) < 0) {
543 localnet = 0;
544 netmask = 0;
545 fprintf(stderr, "%s", ebuf);
546 }
547 if (pcap_compile(PCapHdlr, &fcode, cmdbuf, 1, netmask) < 0) {
548 fprintf(stderr, "%s", pcap_geterr(PCapHdlr));
549 return -1;
550 }
551 if (pcap_setfilter(PCapHdlr, &fcode) < 0) {
552 fprintf(stderr, "%s", pcap_geterr(PCapHdlr));
553 return -1;
554 }
555
556 return 0;
557 }
558 #endif /* PCAP */
559
560 void
init_tcpip(void)561 init_tcpip (void)
562 {
563 int on=1;
564 #ifndef PCAP
565 int rsflags;
566 #else
567 extern char *DEVICE;
568 char ebuf[PCAP_ERRBUF_SIZE];
569 #endif
570
571
572 #ifdef LINUX /*-- routing tables --*/
573 init_route_tables();
574 #endif /*-- LINUX routing tables --*/
575
576 /*-- SEND RAW socket --*/
577 if ((sendsock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
578 {
579 perror ("opening raw send socket");
580 exit (EXIT_FAILURE);
581 }
582 if (setsockopt (sendsock, IPPROTO_IP, IP_HDRINCL, (char *) &on, sizeof (on)) < 0)
583 {
584 perror ("setting option IP_HDRINCL");
585 exit (EXIT_FAILURE);
586 }
587
588 #ifndef PCAP
589 /*-- READ RAW socket --*/
590 if ((readsock = socket (AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0)
591 {
592 perror ("opening raw read socket");
593 exit (EXIT_FAILURE);
594 }
595 if ((rsflags = fcntl (readsock, F_GETFL)) == -1)
596 {
597 perror ("fcntl(readsock,F_GETFL)");
598 exit (EXIT_FAILURE);
599 }
600
601 if (fcntl (readsock, F_SETFL, rsflags | O_NONBLOCK) == -1)
602 {
603 perror ("fcntl(readsock,F_SETFL)");
604 exit (EXIT_FAILURE);
605 }
606 #ifdef RAW_NEEDS_BIND
607 name.sin_family = AF_INET;
608 name.sin_addr.s_addr = INADDR_ANY;
609 name.sin_port = 10000;
610 if (bind (readsock, (struct sockaddr *) &name, sizeof (name)))
611 {
612 perror ("binding read socket");
613 exit (EXIT_FAILURE);
614 }
615 #endif /* RAW_NEEDS_BIND */
616 #else /* PCAP */
617
618 if (DEVICE == NULL) {
619 DEVICE = pcap_lookupdev(ebuf);
620 if (DEVICE == NULL) {
621 fprintf(stderr, "pcap_lookupdev: %s", ebuf);
622 exit (EXIT_FAILURE);
623 }
624 }
625 PCapHdlr = pcap_open_live(DEVICE, 64, 0, 100, ebuf);
626 if (PCapHdlr == NULL) {
627 fprintf(stderr, "pcap_open_live: %s", ebuf);
628 exit (EXIT_FAILURE);
629 }
630
631 #endif /* PCAP */
632 }
633
634 char *
tcpip_id(void)635 tcpip_id (void)
636 {
637 return id;
638 }
639