/*
    troll -- ettercap plugin -- ARP responder

    Copyright (C) 2002  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: H02_troll.c,v 1.2 2003/04/16 11:14:04 lordnaga Exp $
*/

#include "../../src/include/ec_main.h"
#include "../../src/include/ec_version.h"
#include "../../src/include/ec_plugins.h"
#include "../../src/include/ec_inet_structures.h"
#include "../../src/include/ec_inet.h"
#include "../../src/include/ec_inet_forge.h"
#include "../../src/include/ec_error.h"

int sock;
char MyMAC[6];
static char ETH_BROADCAST[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
static char ARP_BROADCAST[6] = {0x0,0x0,0x0,0x0,0x0,0x0};

// protos...

int Plugin_Init(void *);
int Plugin_Fini(void *);
int Parse_Packet(void *buffer);
int To_Respond(char *source, char *dest);
int In_List(char *ip);

// plugin operation

struct plugin_ops troll_ops = {
   ettercap_version: VERSION,
   plug_info:        "ARP responder",
   plug_version:     12,
   plug_type:        PT_HOOK,
   hook_point:       PCK_RECEIVED_RAW,
   hook_function:    &Parse_Packet,
};

//==================================

int Plugin_Init(void *params)
{
   sock = Inet_OpenRawSock(Options.netiface);
   Inet_GetIfaceInfo(Options.netiface, NULL, MyMAC, NULL, NULL);

   return Plugin_Register(params, &troll_ops);
}

int Plugin_Fini(void *params)
{
   Inet_CloseRawSock(sock);

   return 0;
}

// =================================
int In_List(char *ip)
{
   int i, value;

   if (host_to_be_scanned<=0) return 1;

   for (i=0; i<host_to_be_scanned; i++)
   {
	value = inet_addr(Host_List[i]);
	if (!memcmp(&value, ip, 4)) return 1;
   }

   return 0;
}

int To_Respond(char *source, char *dest)
{
    int inl_s, inl_d;
    u_int32 IPS, IPD;

    if (!memcmp(source, dest, 4)) return 0; // hmmmm...some nasty trick?

    inl_s = In_List(source);
    inl_d = In_List(dest);
    IPS = inet_addr(Host_Source.ip);
    IPD = inet_addr(Host_Dest.ip);

    if ( ((IPS==-1 && inl_s) || !memcmp(source, &IPS, 4)) && ((IPD==-1 && inl_d) || !memcmp(dest, &IPD, 4)) )
    	return 1;
    if ( ((IPS==-1 && inl_d) || !memcmp(dest, &IPS, 4)) && ((IPD==-1 && inl_s) || !memcmp(source, &IPD, 4)) )
    	return 1;

    return 0;
}

int To_Replie(char *source)
{
    u_int32 IPS, IPD;
    IPS = inet_addr(Host_Source.ip);
    IPD = inet_addr(Host_Dest.ip);

    if (IPD==-1 && !memcmp(source, &IPS, 4)) return 1;
    if (IPS==-1 && !memcmp(source, &IPD, 4)) return 1;
    return 0;	
}

int Parse_Packet(void *buffer)
{

   ETH_header *eth;
   ARP_header *arp;
   RAW_PACKET *pck_raw;

   pck_raw = (RAW_PACKET *)buffer;
   eth = (ETH_header *) pck_raw->buffer;

   if (eth->type == htons(ETH_P_ARP))
   {
      arp = (ARP_header *)(eth+1);
      // ARP request...let's forge a reply!
      if (ntohs(arp->opcode)==ARPOP_REQUEST)
      {
          if (To_Respond(arp->source_ip, arp->dest_ip))
          {
             char *reply;
             reply = Inet_Forge_packet( ETH_HEADER + ARP_HEADER );
             Inet_Forge_ethernet( reply, MyMAC, arp->source_add, ETH_P_ARP );
             Inet_Forge_arp( reply + ETH_HEADER, ARPOP_REPLY, MyMAC, *(u_int32 *)arp->dest_ip, arp->source_add, *(u_int32 *)arp->source_ip );
             Inet_SendRawPacket(sock, reply, ETH_HEADER + ARP_HEADER);
	     usleep(Options.storm_delay);
             Inet_SendRawPacket(sock, reply, ETH_HEADER + ARP_HEADER);
	     Inet_Forge_packet_destroy( reply );
          }
	  
	  if (To_Replie(arp->source_ip))
	  {
	     char *reply;
             reply = Inet_Forge_packet( ETH_HEADER + ARP_HEADER );
             Inet_Forge_ethernet( reply, MyMAC, ETH_BROADCAST, ETH_P_ARP );
             Inet_Forge_arp( reply + ETH_HEADER, ARPOP_REQUEST, MyMAC, *(u_int32 *)arp->source_ip, arp->dest_add, *(u_int32 *)arp->dest_ip );
             Inet_SendRawPacket(sock, reply, ETH_HEADER + ARP_HEADER);
             usleep(Options.storm_delay);
	     Inet_SendRawPacket(sock, reply, ETH_HEADER + ARP_HEADER);
	     Inet_Forge_packet_destroy( reply );
	  }
      }
   }
   return 0;
}


/* EOF */
