/*
    ettercap -- comunication buffer between illithid and ettercap

    Copyright (C) 2001  ALoR <alor@users.sourceforge.net>, NaGA <crwm@freemail.it>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

    $Id: ec_binder.c,v 1.8 2002/09/06 08:57:31 alor Exp $
*/

#include "include/ec_main.h"
#include "include/ec_inet.h"
#include "include/ec_buffer.h"
#include "include/ec_thread.h"
#include "include/ec_binder.h"
#include "include/ec_inet_structures.h"

int binder_pipe = -1;
int bi_sock = -1;
int tmpsock = -1;
u_short Global_Binder_Port;

// protos...

void Binder_fini(void *dummy);
void * Binder_Run(void *param);
pthread_t Binder_Start(u_long ipS, u_long ipD, u_short portS, ushort portD, char proto);

// ----------------------------

void Binder_fini(void *dummy)
{
   // A possible race-condition? I don't think so.....
   if (bi_sock>0) close(bi_sock);
   bi_sock = -1;
   if (tmpsock>0) close(tmpsock);
   tmpsock = -1;
   DEBUG_MSG("Binder_fini -- binder closed gracefully...");
}

void * Binder_Run(void *param)
{
   SNIFFED_DATA sniff_data;
   INJECTED_DATA inject_data;
   struct sockaddr_in dest;
   u_int32 addrlen;
   u_long IP1, IP2;
   u_long IP_S1, IP_S2;
   u_int16 binder_port;

   dest.sin_family = AF_INET;
   dest.sin_port = htons(BINDER_PORT);
   dest.sin_addr.s_addr = inet_addr("127.0.0.1");

   tmpsock = socket(AF_INET, SOCK_STREAM, 0);
   if (tmpsock < 0) ERROR_MSG("socket()");

   binder_port=BINDER_PORT;
   while (bind(tmpsock, (struct sockaddr *)&dest, sizeof(dest)) < 0)
   {
       binder_port++;
       dest.sin_port = htons(binder_port);
   }
   DEBUG_MSG("Binder_Run -- Binded port %d",binder_port);

   Global_Binder_Port = binder_port;

   if ( listen(tmpsock,1) < 0)
      ERROR_MSG("listen()");

   addrlen = sizeof(dest);

   exit_func(Binder_fini);

   pthread_testcancel();

   bi_sock = accept(tmpsock, (struct sockaddr *)&dest, &addrlen);

   close(tmpsock);
   tmpsock = -1;

   if (bi_sock < 0) ERROR_MSG("accept()");

   DEBUG_MSG("Binder_Run -- Connection accepted on fd %d", bi_sock);

   Inet_SetNonBlock(bi_sock);

   Buffer_Flush(binder_pipe);

   inject_data.source_ip   = IP2 = ((INJECTED_DATA *)param)->source_ip;
   inject_data.dest_ip     = IP1 = ((INJECTED_DATA *)param)->dest_ip;
   inject_data.source_port = ((INJECTED_DATA *)param)->source_port;
   inject_data.dest_port   = ((INJECTED_DATA *)param)->dest_port;
   inject_data.proto =  ((INJECTED_DATA *)param)->proto;

   LOOP {
      int datalen;

      pthread_testcancel();

      datalen = Buffer_Get(binder_pipe, &sniff_data, sizeof(SNIFFED_DATA));

      if (datalen > 0) {
         // Already filtered by illithid
         IP_S1=inet_addr(sniff_data.source_ip);
         IP_S2=inet_addr(sniff_data.dest_ip);

         if (IP_S1 == IP1 && IP_S2 == IP2)
            if (write(bi_sock, sniff_data.data, sniff_data.datasize)<0) {
               //DEBUG_MSG("Binder_Run -- Connection closed");
               //while(1) { pthread_testcancel(); sleep(1);}
            }
      }
      else
         usleep(500);

      datalen = read(bi_sock, inject_data.data, MAX_INJECT);
      if (datalen>0) {
         inject_data.datalen = datalen;
         if (Options.arpsniff)
            write(pipe_inject[1], &inject_data, sizeof(INJECTED_DATA));
         else
            DEBUG_MSG("Cant inject when not in arp sniffing method");
      }
   }

   exit_func_end();

   return NULL;
}

pthread_t Binder_Start(u_long ipS, u_long ipD, u_short portS, ushort portD, char proto)
{
   static INJECTED_DATA param;

   DEBUG_MSG("Binder_Start -- Ready to accept connections!");

   param.source_ip = ipS;
   param.dest_ip = ipD;
   param.source_port = htons(portS);
   param.dest_port = htons(portD);
   param.proto = proto;

   return ECThread_create("binder", &Binder_Run, &param);
}

/* EOF */

// vim:ts=3:expandtab

