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