#include "../tcpip.h"

extern struct ops o;

//DWORD getreg_ip(char *path);
//DWORD getreg_gw(char *path);
//DWORD getreg_ip9x(int iface);
//DWORD getreg_gw9x(DWORD IP);
BYTE *getmac_info(LPADAPTER adapter);
BOOL send_arp(DWORD IP,struct interface_info *ainfo);
BYTE * FindMAC(DWORD IP,struct interface_info *ainfo);
BYTE * get_remote_mac(DWORD IP,struct interface_info *ainfo);
int build_ethernet(u_char *dst, u_char *src, u_short type, const u_char *payload, int payload_s, u_char *buf);
char *readarp_pcap(pcap_t *pd, unsigned int *len, long to_usec);

int FillIfList(struct _IFlist *iflist, int *icount);
int FillIpList(struct _IPlist *iplist);


struct ethernet_hdr
{
#ifndef ETHER_ADDR_LEN
#define ETHER_ADDR_LEN 6
#endif
    u_char  ether_dhost[ETHER_ADDR_LEN];    /* destination ethernet address */
    u_char  ether_shost[ETHER_ADDR_LEN];    /* source ethernet address */
    u_short ether_type;                     /* packet type ID */
};

struct arp_hdr
{
    u_short ar_hrd;                         /* format of hardware address */
#define ARPHRD_ETHER     1                  /* ethernet hardware format */
    u_short ar_pro;                         /* format of protocol address */
    u_char  ar_hln;                         /* length of hardware address */
    u_char  ar_pln;                         /* length of protocol addres */
    u_short ar_op;                          /* operation type */
#define ARPOP_REQUEST    1                  /* req to resolve address */
#define ARPOP_REPLY      2                  /* resp to previous request */
#define ARPOP_REVREQUEST 3                  /* req protocol address given hardware */
#define ARPOP_REVREPLY   4                  /* resp giving protocol address */
#define ARPOP_INVREQUEST 8                  /* req to identify peer */
#define ARPOP_INVREPLY   9                  /* resp identifying peer */

    /*
     *  These should implementation defined but I've hardcoded eth/IP.
     */
    BYTE ar_sha[6];                         /* sender hardware address */
    DWORD ar_spa;                         /* sender protocol address */
   BYTE ar_tha[6];                         /* target hardware address */
    DWORD ar_tpa;                         /* target protocol address */
};

inline void sethdrinclude(int sd) 
{
	int one = 1;
	//setsockopt(sd, IPPROTO_IP, IP_HDRINCL, (void *) &one, sizeof(one));
}


//inline void max_rcvbuf(int sd) {
//}

inline void max_rcvbuf(int sd) {
	int optval = 524288 /*2^19*/, optlen = sizeof(int);

	if (setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *) &optval, optlen))
	if (o.debugging) perror("Problem setting large socket recieve buffer");
	if (o.debugging) 
	{
		getsockopt(sd, SOL_SOCKET, SO_RCVBUF,(void *) &optval, &optlen);
		log_write(LOG_STDOUT, "Our buffer size is now %d\n", optval);
	}
}
/* Maximize the open file descriptor limit for this process go up to the
   max allowed  */

int max_sd() 
{
	return 64;
}

/* gotta make theese using winsock*/
inline int block_socket(int sd) 
{
	unsigned long options=0;
	ioctlsocket(sd, FIONBIO, (unsigned long *)&options);
	return 1;
}

inline int unblock_socket(int sd) 
{
	u_long b=1;
	ioctlsocket (sd, FIONBIO, &b);
	return 1;
}


inline void broadcast_socket(int sd) 
{
	BOOL one = TRUE;
	if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, (char *)&one, sizeof(BOOL)) != 0) 
	{
		fprintf(stderr, "Failed to secure socket broadcasting permission\n");
		perror("setsockopt");
	}
}
/* We set the socket lingering so we will RST connection instead of wasting
   bandwidth with the four step close  */
inline void init_socket(int sd) 
{
  struct linger l;
  int res;
  static int bind_failed=0;
  struct sockaddr_in sin;

  l.l_onoff = 1;
  l.l_linger = 0;

	if (setsockopt(sd, SOL_SOCKET, SO_LINGER,  (void *) &l, sizeof(struct linger)))
    {
		fprintf(stderr, "Problem setting socket SO_LINGER, errno: %d\n", errno);
		perror("setsockopt");
    }
	if (o.spoofsource && !bind_failed)
    {
		bzero(&sin,sizeof(sin));
		sin.sin_family=AF_INET;
		memcpy(&sin.sin_addr,o.source,sizeof(sin.sin_addr));
		res=bind(sd,(struct sockaddr*)&sin,sizeof(sin));
		if (res<0)
		{
			fprintf(stderr, "init_socket: Problem binding source address (%s), errno :%d\n", inet_ntoa(sin.sin_addr), errno);
			perror("bind");
			bind_failed=1;
		}
	}
}




/* Tests whether a packet sent to  IP is LIKELY to route 
 through the kernel localhost interface */
int islocalhost(struct in_addr *addr) 
{
	struct interface_info dev;
  /* If it is 0.0.0.0 or starts with 127.0.0.1 then it is 
     probably localhost */
	if ((addr->s_addr & htonl(0xFF000000)) == htonl(0x7F000000)) return 1;
	if (!addr->s_addr) return 1;
  /* If it is the same addy as a local interface, then it is
     probably localhost */
	if (ipaddr2dev(&dev, addr) != -1) return 1;
  /* OK, so to a first approximation, this addy is probably not
     localhost */
	return 0;
}

/* Calls pcap_open_live and spits out an error (and quits) if the call faile.
   So a valid pcap_t will always be returned. */
pcap_t *my_pcap_open_live(char *device, int snaplen, int promisc, int to_ms) 
{
	char err0r[PCAP_ERRBUF_SIZE];
	pcap_t *pt;
	if (!((pt = pcap_open_live(device, snaplen, promisc, to_ms, err0r)))) 
	{
		fatal("pcap_open_live: %s\nThere are several possible reasons for this, depending on your operating system:\n"
          "LINUX: If you are getting Socket type not supported, try modprobe af_packet or recompile your kernel with SOCK_PACKET enabled.\n"
          "*BSD:  If you are getting device not configured, you need to recompile your kernel with Berkeley Packet Filter support.  If you are getting No such file or directory, try creating the device (eg cd /dev; MAKEDEV <device>; or use mknod).\n"
          "SOLARIS:  If you are trying to scan localhost and getting '/dev/lo0: No such file or directory', complain to Sun.  I don't think Solaris can support advanced localhost scans.  You can probably use \"-P0 -sT localhost\" though.\n\n", err0r);
	}
	return pt;
}

/* Standard swiped internet checksum routine */
inline unsigned short in_cksum(unsigned short *ptr,int nbytes) 
{
	register int		sum;            /* XXX assumes long == 32 bits */
	u_short				oddbyte;
	register u_short	answer;         /* assumes u_short == 16 bits */

/*
 * Our algorithm is simple, using a 32-bit accumulator (sum),
 * we add sequential 16-bit words to it, and at the end, fold back
 * all the carry bits from the top 16 bits into the lower 16 bits.
 */

	sum = 0;
	while (nbytes > 1)  
	{
		sum += *ptr++;
		nbytes -= 2;
	}
/* mop up an odd byte, if necessary */
	if (nbytes == 1) 
	{
		oddbyte = 0;            /* make sure top half is zero */
		*((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
		sum += oddbyte;
	}
/*
 * Add back carry outs from top 16 bits to low 16 bits.
 */
	sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
	sum += (sum >> 16);                     /* add carry */
	answer = ~sum;          /* ones-complement, then truncate to 16 bits */
	return(answer);
}



/* Tries to resolve given hostname and stores
   result in ip .  returns 0 if hostname cannot
   be resolved */
int resolve(char *hostname, struct in_addr *ip) 
{
	struct hostent *h;
	if (!hostname || !*hostname) fatal("NULL or zero-length hostname passed to resolve()");
	if (inet_aton(hostname, ip)) return 1; /* damn, that was easy ;) */
	if ((h = gethostbyname(hostname))) 
	{
		memcpy(ip, h->h_addr_list[0], sizeof(struct in_addr));
		return 1;
	}
	return 0;
}

int send_tcp_raw_decoys( int sd, struct in_addr *victim, unsigned short sport, 
			 unsigned short dport, unsigned int seq,
			 unsigned int ack, unsigned char flags,
			 unsigned short window, char *options, int optlen,
			 char *data, unsigned short datalen,struct interface_info *ainfo) 
{
	int decoy;
	for(decoy = 0; decoy < o.numdecoys; decoy++) 
	{
		if (send_tcp_raw(sd, &o.decoys[decoy], victim, sport, dport, seq, ack, flags, window, options, optlen, data, datalen,ainfo) == -1) return -1;
	}
	return 0;
}


int send_tcp_raw( int sd, struct in_addr *source, 
		  struct in_addr *victim, unsigned short sport, 
		  unsigned short dport, unsigned int seq,
		  unsigned int ack, unsigned char flags,
		  unsigned short window, char *options, int optlen,
		  char *data, unsigned short datalen,struct interface_info *ainfo) 
{

	struct pseudo_header 
	{ 
  /*for computing TCP checksum, see TCP/IP Illustrated p. 145 */
		unsigned int s_addy;
		unsigned int d_addr;
		char zer0;
		unsigned char protocol;
		unsigned short length;
	};
	char *packet = safe_malloc(sizeof(struct ip) + sizeof(struct tcphdr) + optlen + datalen);
	struct ip *ip = (struct ip *) packet;
	struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ip));
	struct pseudo_header *pseudo =  (struct pseudo_header *) (packet + sizeof(struct ip) - sizeof(struct pseudo_header)); 
	static int myttl = 0;

	/*With these placement we get data and some field alignment so we aren't
	wasting too much in computing the checksum */
	int res = -1;
	struct sockaddr_in sock;
	char myname[MAXHOSTNAMELEN + 1];
	struct hostent *myhostent = NULL;
	int source_malloced = 0;

	/* check that required fields are there and not too silly */
	/* We used to check that sport and dport were nonzer0, but scr3w that! */
	if ( !victim || sd < 0) 
	{
		fprintf(stderr, "send_tcp_raw: One or more of your parameters suck!\n");
		free(packet);
		return -1;
	}

	if (optlen % 4) 
	{
		fatal("send_tcp_raw called with an option length argument of %d which is illegal because it is not divisible by 4", optlen);
	}


	if (!myttl) myttl = (get_random_uint() % 23) + 37;

	/* It was a tough decision whether to do this here for every packet
	or let the calling function deal with it.  In the end I grudgingly decided
	to do it here and potentially waste a couple microseconds... */
	sethdrinclude(sd); 

	/* if they didn't give a source address, fill in our first address */
	if (!source) 
	{
		source_malloced = 1;
		source = safe_malloc(sizeof(struct in_addr));
		if (gethostname(myname, MAXHOSTNAMELEN) || !(myhostent = gethostbyname(myname)))
		{
			fatal("Cannot get hostname!  Try using -S <my_IP_address> or -e <interface to scan through>\n");
		}
		memcpy(source, myhostent->h_addr_list[0], sizeof(struct in_addr));
#if ( TCPIP_DEBUGGING )
		printf("We skillfully deduced that your address is %s\n", inet_ntoa(*source));
#endif
	}

	/*do we even have to fill out this damn thing?  This is a raw packet, 
	after all */
	sock.sin_family = AF_INET;
	sock.sin_port = htons(dport);
	sock.sin_addr.s_addr = victim->s_addr;
	bzero((char *) packet, sizeof(struct ip) + sizeof(struct tcphdr));
	pseudo->s_addy = source->s_addr;
	pseudo->d_addr = victim->s_addr;
	pseudo->protocol = IPPROTO_TCP;
	pseudo->length = (unsigned short)htons(sizeof(struct tcphdr) + optlen + datalen);

	tcp->th_sport = htons(sport);
	tcp->th_dport = htons(dport);
	if (seq) 
	{
		tcp->th_seq = htonl(seq);
	}
	else if (flags & TH_SYN) 
	{
		get_random_bytes(&(tcp->th_seq), 4);
	}

	if (ack) tcp->th_ack = htonl(ack);
	/*else if (flags & TH_ACK)
	tcp->th_ack = rand() + rand();*/

	tcp->th_off = 5 + (optlen /4) /*words*/;
	tcp->th_flags = flags;

	if (window) tcp->th_win = htons(window);
	else tcp->th_win = htons(1024 * (myttl % 4 + 1)); /* Who cares */

	/* We should probably copy the data over too */
	if (data && datalen) memcpy(packet + sizeof(struct ip) + sizeof(struct tcphdr) + optlen, data, datalen);
	/* And the options */
	if (optlen) 
	{
		memcpy(packet + sizeof(struct ip) + sizeof(struct tcphdr), options, optlen);
	}

	tcp->th_sum = in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr) + optlen + sizeof(struct pseudo_header) + datalen);

	/* Now for the ip header */
	bzero(packet, sizeof(struct ip)); 
	ip->ip_v = 4;
	ip->ip_hl = 5;
	ip->ip_len = BSDFIX(sizeof(struct ip) + sizeof(struct tcphdr) + optlen + datalen);
	get_random_bytes(&(ip->ip_id), 2);
	ip->ip_ttl = myttl;
	ip->ip_p = IPPROTO_TCP;
	if(source->s_addr == victim->s_addr) source->s_addr++;
	ip->ip_src.s_addr = source->s_addr;
	ip->ip_dst.s_addr= victim->s_addr;

	ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip));


	if (TCPIP_DEBUGGING > 1) 
	{
		log_write(LOG_STDOUT, "Raw TCP packet creation completed!  Here it is:\n");
		readtcppacket(packet,BSDUFIX(ip->ip_len));
	}

	res = Sendto("send_tcp_raw", sd, packet, BSDUFIX(ip->ip_len), 0, (struct sockaddr *)&sock,  (int)sizeof(struct sockaddr_in),ainfo);
	if (source_malloced) free(source);
	free(packet);
	return res;
}

inline int Sendto(char *functionname, int sd, char *packet, int len, 
	   unsigned int flags, struct sockaddr *to, int tolen,struct interface_info *ainfo) 
{
	struct sockaddr_in *sin = (struct sockaddr_in *) to;
//	DWORD scanlocalip;
	u_char packetbuf[2048];
//	DWORD remoteip;
//	struct in_addr *addr;
	LPPACKET   lpPacket;
	BYTE *r_mac=NULL;
//	BYTE s_mac[]= {0xAB,0xCD,0xEF,0x12,0x34,0x56};
	if(ainfo->adapter != NULL)
	{
			if (TCPIP_DEBUGGING > 1) 
		{  
			log_write(LOG_STDOUT, "trying sendto(%d, packet, %d, 0, %s, %d)", sd, len, inet_ntoa(sin->sin_addr), tolen);
		}
	memset(packetbuf,0,2048);
//	addr = &sin->sin_addr;
	//memcpy(&remoteip,packet+16,4);
	//scanning ourselves
//		build_ethernet(r_mac,s_mac,0x0800,packet,len,packetbuf);		
//	}
//	else
//	{
//	r_mac=get_remote_mac(sin->sin_addr.S_un.S_addr);
	r_mac=get_remote_mac(sin->sin_addr.S_un.S_addr,ainfo);
	if (islocalhost(&sin->sin_addr))// filter[0] = '\0';
	{
		build_ethernet(ainfo->MAC,r_mac,0x0800,packet,len,packetbuf);
	}
	else
	{

		build_ethernet(r_mac,ainfo->MAC,0x0800,packet,len,packetbuf);		
	}
//	}
//	build_ethernet(r_mac,global_adapter.MAC,0x0800,packet,len,packetbuf);		
	if((lpPacket = PacketAllocatePacket())==NULL){
		printf("\nError:failed to allocate the LPPACKET structure.");
		return (-1);
	}
//	printf("OUTPACKET\n");
//	hdump(packetbuf, len+14);
	PacketInitPacket(lpPacket,packetbuf,len+14);
	PacketSendPacket(ainfo->adapter,lpPacket,TRUE);
	PacketFreePacket(lpPacket);
	if (TCPIP_DEBUGGING > 1) log_write(LOG_STDOUT, "successfully sent %d bytes of raw_tcp!\n", len);
	}
	return (len);

	

//	return res;
}

/* A simple function I wrote to help in debugging, shows the important fields
   of a TCP packet*/
int readtcppacket(char *packet, int readdata) 
{
	struct ip *ip = (struct ip *) packet;
	struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ip));
	char *data = packet +  sizeof(struct ip) + sizeof(struct tcphdr);
	int tot_len;
	struct in_addr bullshit, bullshit2;
	char sourcehost[16];
	int i;
	int realfrag = 0;

	if (!packet) 
	{
		fprintf(stderr, "readtcppacket: packet is NULL!\n");
		return -1;
    }
	bullshit.s_addr = ip->ip_src.s_addr; bullshit2.s_addr = ip->ip_dst.s_addr;
	/* this is gay */
	realfrag = BSDFIX(ntohs(ip->ip_off) & 8191 /* 2^13 - 1 */);
	tot_len = BSDFIX(ip->ip_len);
	strncpy(sourcehost, inet_ntoa(bullshit), 16);
	i =  4 * (ntohs(ip->ip_hl) + ntohs(tcp->th_off));
	if (ip->ip_p== IPPROTO_TCP) 
	{
		if (realfrag) printf("Packet is fragmented, offset field: %u\n", realfrag);
		else 
		{
			printf("TCP packet: %s:%d -> %s:%d (total: %d bytes)\n", sourcehost, ntohs(tcp->th_sport), inet_ntoa(bullshit2), ntohs(tcp->th_dport), tot_len);
			printf("Flags: ");
			if (!tcp->th_flags) printf("(none)");
			if (tcp->th_flags & TH_RST) printf("RST ");
			if (tcp->th_flags & TH_SYN) printf("SYN ");
			if (tcp->th_flags & TH_ACK) printf("ACK ");
			if (tcp->th_flags & TH_PUSH) printf("PSH ");
			if (tcp->th_flags & TH_FIN) printf("FIN ");
			if (tcp->th_flags & TH_URG) printf("URG ");
			printf("\n");
			printf("ttl: %hu ", ip->ip_ttl);
			if (tcp->th_flags & (TH_SYN | TH_ACK)) printf("Seq: %u\tAck: %u\n", (unsigned int) ntohl(tcp->th_seq), (unsigned int) ntohl(tcp->th_ack));
			else if (tcp->th_flags & TH_SYN) printf("Seq: %u\n", (unsigned int) ntohl(tcp->th_seq));
			else if (tcp->th_flags & TH_ACK) printf("Ack: %u\n", (unsigned int) ntohl(tcp->th_ack));
		}
	}
	if (readdata && i < tot_len) 
	{
		printf("Data portion:\n");
		while(i < tot_len)  printf("%2X%c", data[i], (++i%16)? ' ' : '\n');
		printf("\n");
	}
	return 0;
}

/* A simple function I wrote to help in debugging, shows the important fields
   of a UDP packet*/
int readudppacket(char *packet, int readdata) 
{

	struct ip *ip = (struct ip *) packet;
	udphdr_bsd *udp = (udphdr_bsd *) (packet + sizeof(struct ip));
	char *data = packet +  sizeof(struct ip) + sizeof(udphdr_bsd);
	int tot_len;
	struct in_addr bullshit, bullshit2;
	char sourcehost[16];
	int i;
	int realfrag = 0;

	if (!packet) 
	{
		fprintf(stderr, "readudppacket: packet is NULL!\n");
		return -1;
	}

	bullshit.s_addr = ip->ip_src.s_addr; bullshit2.s_addr = ip->ip_dst.s_addr;
	/* this is gay */
	realfrag = BSDFIX(ntohs(ip->ip_off) & 8191 /* 2^13 - 1 */);
	tot_len = BSDFIX(ip->ip_len);
	strncpy(sourcehost, inet_ntoa(bullshit), 16);
	i =  4 * (ntohs(ip->ip_hl)) + 8;
	if (ip->ip_p== IPPROTO_UDP) 
	{
		if (realfrag) printf("Packet is fragmented, offset field: %u\n", realfrag);
		else 
		{
			printf("UDP packet: %s:%d -> %s:%d (total: %d bytes)\n", sourcehost, ntohs(udp->uh_sport), inet_ntoa(bullshit2), ntohs(udp->uh_dport), tot_len);
			printf("ttl: %hu ", ip->ip_ttl);
		}
	}
	if (readdata && i < tot_len) 
	{
		printf("Data portion:\n");
		while(i < tot_len)  printf("%2X%c", data[i], (++i%16)? ' ' : '\n');
		printf("\n");
	}
	return 0;
}

int send_udp_raw_decoys( int sd, struct in_addr *victim, unsigned short sport, 
		  unsigned short dport, char *data, unsigned short datalen,struct interface_info *ainfo) 
{
	int decoy;
  
	for(decoy = 0; decoy < o.numdecoys; decoy++)
	{
		if (send_udp_raw(sd, &o.decoys[decoy], victim, sport, dport, data, datalen,ainfo) == -1) return -1;
	}
	return 0;
}



int send_udp_raw( int sd, struct in_addr *source, 
		  struct in_addr *victim, unsigned short sport, 
		  unsigned short dport, char *data, unsigned short datalen,struct interface_info *ainfo) 
{

	char *packet = safe_malloc(sizeof(struct ip) + sizeof(udphdr_bsd) + datalen);
	struct ip *ip = (struct ip *) packet;
	udphdr_bsd *udp = (udphdr_bsd *) (packet + sizeof(struct ip));
	static int myttl = 0;

	int res;
	struct sockaddr_in sock;
	char myname[MAXHOSTNAMELEN + 1];
	struct hostent *myhostent = NULL;
	int source_malloced = 0;
	struct pseudo_udp_hdr 
	{
		struct in_addr source;
		struct in_addr dest;        
		char zero;
		char proto;        
		unsigned short length;
	} *pseudo = (struct pseudo_udp_hdr *) ((char *)udp - 12) ;

	/* check that required fields are there and not too silly */
	if ( !victim || !sport || !dport || sd < 0) 
	{
		fprintf(stderr, "send_udp_raw: One or more of your parameters suck!\n");
		free(packet);
		return -1;
	}
	if (!myttl) myttl = (get_random_uint() % 23) + 37;
	/* It was a tough decision whether to do this here for every packet
	or let the calling function deal with it.  In the end I grudgingly decided
	to do it here and potentially waste a couple microseconds... */
	sethdrinclude(sd); 
	/* if they didn't give a source address, fill in our first address */
	if (!source) 
	{
		source_malloced = 1;
		source = safe_malloc(sizeof(struct in_addr));
		if (gethostname(myname, MAXHOSTNAMELEN) || !(myhostent = gethostbyname(myname)))
		{
			fatal("Cannot get hostname!  Try using -S <my_IP_address> or -e <interface to scan through>\n");
		}
		memcpy(source, myhostent->h_addr_list[0], sizeof(struct in_addr));
#if ( TCPIP_DEBUGGING )
		printf("We skillfully deduced that your address is %s\n", inet_ntoa(*source));
#endif
	}
	/*do we even have to fill out this damn thing?  This is a raw packet, 
	after all */
	sock.sin_family = AF_INET;
	sock.sin_port = htons(dport);
	sock.sin_addr.s_addr = victim->s_addr;
	bzero((char *) packet, sizeof(struct ip) + sizeof(udphdr_bsd));
	udp->uh_sport = htons(sport);
	udp->uh_dport = htons(dport);
	udp->uh_ulen = htons(8 + datalen);
	/* We should probably copy the data over too */
	if (data) memcpy(packet + sizeof(struct ip) + sizeof(udphdr_bsd), data, datalen);
	/* Now the psuedo header for checksuming */
	pseudo->source.s_addr = source->s_addr;
	pseudo->dest.s_addr = victim->s_addr;
	pseudo->proto = IPPROTO_UDP;
	pseudo->length = htons(sizeof(udphdr_bsd) + datalen);
	/* OK, now we should be able to compute a valid checksum */
	udp->uh_sum = in_cksum((unsigned short *)pseudo, 20 /* pseudo + UDP headers */ + datalen);
	/* Goodbye, pseudo header! */
	bzero(pseudo, 12);
	/* Now for the ip header */
	ip->ip_v = 4;
	ip->ip_hl = 5;
	ip->ip_len = BSDFIX(sizeof(struct ip) + sizeof(udphdr_bsd) + datalen);
	get_random_bytes(&(ip->ip_id), 2);
	ip->ip_ttl = myttl;
	ip->ip_p = IPPROTO_UDP;
	if(source->s_addr == victim->s_addr) source->s_addr++;
	ip->ip_src.s_addr = source->s_addr;
	ip->ip_dst.s_addr= victim->s_addr;
	ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip));


	if (TCPIP_DEBUGGING > 1) 
	{
		printf("Raw UDP packet creation completed!  Here it is:\n");
		readudppacket(packet,1);
	}
	res = Sendto("send_udp_raw", sd, packet, BSDUFIX(ip->ip_len), 0, (struct sockaddr *)&sock,  (int)sizeof(struct sockaddr_in),ainfo);
	if (source_malloced) free(source);
	free(packet);
	return res;
}

int send_small_fragz_decoys(int sd, struct in_addr *victim, unsigned long seq, 
			    int sport, int dport, int flags,struct interface_info *ainfo) {
	int decoy;

	for(decoy = 0; decoy < o.numdecoys; decoy++)
	{
		if (send_small_fragz(sd, &o.decoys[decoy], victim, seq, sport, dport, flags,ainfo) == -1) return -1;
	}
	return 0;
}

/* Much of this is swiped from my send_tcp_raw function above, which 
   doesn't support fragmentation */
int send_small_fragz(int sd, struct in_addr *source, struct in_addr *victim,
		     unsigned long seq, int sport, int dport, int flags,struct interface_info *ainfo)
{
	struct pseudo_header 
	{ 
		/*for computing TCP checksum, see TCP/IP Illustrated p. 145 */
		unsigned long s_addy;
		unsigned long d_addr;
		char zer0;
		unsigned char protocol;
		unsigned short length;
	};
	/*In this placement we get data and some field alignment so we aren't wasting
	too much to compute the TCP checksum.*/
	char packet[sizeof(struct ip) + sizeof(struct tcphdr) + 100];
	struct ip *ip = (struct ip *) packet;
	struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ip));
	struct pseudo_header *pseudo = (struct pseudo_header *) (packet + sizeof(struct ip) - sizeof(struct pseudo_header)); 
	char *frag2 = packet + sizeof(struct ip) + 16;
	struct ip *ip2 = (struct ip *) (frag2 - sizeof(struct ip));
	static int myttl = 0;
	int res;
	struct sockaddr_in sock;
	int id;

	if (!myttl)  myttl = (time(NULL) % 14) + 51;
	/* It was a tough decision whether to do this here for every packet
	or let the calling function deal with it.  In the end I grudgingly decided
	to do it here and potentially waste a couple microseconds... */
	sethdrinclude(sd);
	/*Why do we have to fill out this damn thing? This is a raw packet, after all */
	sock.sin_family = AF_INET;
	sock.sin_port = htons(dport);
	sock.sin_addr.s_addr = victim->s_addr;
	bzero((char *)packet, sizeof(struct ip) + sizeof(struct tcphdr));
	pseudo->s_addy = source->s_addr;
	pseudo->d_addr = victim->s_addr;
	pseudo->protocol = IPPROTO_TCP;
	pseudo->length = htons(sizeof(struct tcphdr));
	tcp->th_sport = htons(sport);
	tcp->th_dport = htons(dport);
	tcp->th_seq = (seq)? htonl(seq) : get_random_uint();
	tcp->th_off = 5 /*words*/;
	tcp->th_flags = flags;
	tcp->th_win = htons(2048); /* Who cares */
	tcp->th_sum = in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr) + sizeof(struct pseudo_header));
	/* Now for the ip header of frag1 */
	bzero((char *) packet, sizeof(struct ip)); 
	ip->ip_v = 4;
	ip->ip_hl = 5;
	/*RFC 791 allows 8 octet frags, but I get "operation not permitted" (EPERM)
	when I try that.  */
	ip->ip_len = BSDFIX(sizeof(struct ip) + 16);
	id = ip->ip_id = get_random_uint();
	ip->ip_off = BSDFIX(MORE_FRAGMENTS);
	ip->ip_ttl = myttl;
	ip->ip_p = IPPROTO_TCP;
	ip->ip_src.s_addr = source->s_addr;
	ip->ip_dst.s_addr = victim->s_addr;

	ip->ip_sum= in_cksum((unsigned short *)ip, sizeof(struct ip));
	if (o.debugging > 1) 
	{
		log_write(LOG_STDOUT, "Raw TCP packet fragment #1 creation completed!  Here it is:\n");
		log_write(LOG_STDOUT, "\nTrying sendto(%d , packet, %d, 0 , %s , %d)\n", sd, ntohs(ip->ip_len), inet_ntoa(*victim),(int) sizeof(struct sockaddr_in));
		hdump(packet,20);
	}

		
	/* Lets save this and send it AFTER we send the second one, just to be
	cute ;) */
		/*if ((res = sendto(sd, packet,sizeof(struct ip) + 16 , 0, (struct sockaddr *)&sock, sizeof(struct sockaddr_in))) == -1)*/
	if ((res = Sendto("send_small_fragz",sd, packet,sizeof(struct ip) + 16 , 0, (struct sockaddr *)&sock, sizeof(struct sockaddr_in),ainfo)) == -1)
	{
		perror("sendto in send_syn_fragz");
		return -1;
	}
	if (o.debugging > 1) log_write(LOG_STDOUT, "successfully sent %d bytes of raw_tcp!\n", res);

	/* Create the second fragment */
	bzero((char *) ip2, sizeof(struct ip));
	ip2->ip_v= 4;
	ip2->ip_hl = 5;
	ip2->ip_len = BSDFIX(sizeof(struct ip) + 4); /* the rest of our TCP packet */
	ip2->ip_id = id;
	ip2->ip_off = BSDFIX(2);
	ip2->ip_ttl = myttl;
	ip2->ip_p = IPPROTO_TCP;
		if(source->s_addr == victim->s_addr) source->s_addr++;
	ip2->ip_src.s_addr = source->s_addr;
	ip2->ip_dst.s_addr = victim->s_addr;
	ip2->ip_sum = in_cksum((unsigned short *)ip2, sizeof(struct ip));
	if (o.debugging > 1) 
	{
		log_write(LOG_STDOUT, "Raw TCP packet fragment creation completed!  Here it is:\n");
		hdump(packet,20);
		log_write(LOG_STDOUT, "\nTrying sendto(%d , ip2, %d, 0 , %s , %d)\n", sd, ntohs(ip2->ip_len), inet_ntoa(*victim), (int) sizeof(struct sockaddr_in));
	}
		/*if ((res = sendto(sd, (void *)ip2,sizeof(struct ip) + 4 , 0, (struct sockaddr *)&sock, (int) sizeof(struct sockaddr_in))) == -1)*/
	if ((res = Sendto("send_small_fragz",sd, (void *)ip2,sizeof(struct ip) + 4 , 0, (struct sockaddr *)&sock, (int) sizeof(struct sockaddr_in),ainfo)) == -1)
	{
		perror("sendto in send_tcp_raw frag #2");
		return -1;
	}
	return 1;
}

int send_ip_raw_decoys( int sd, struct in_addr *victim, unsigned char proto,
			char *data, unsigned short datalen,struct interface_info *ainfo) 
{
	int decoy;
	for(decoy = 0; decoy < o.numdecoys; decoy++)
	{
		if (send_ip_raw(sd, &o.decoys[decoy], victim, proto, data, datalen,ainfo) == -1) return -1;
	}
	return 0;
}

int send_ip_raw( int sd, struct in_addr *source, 
		  struct in_addr *victim, unsigned char proto,
		  char *data, unsigned short datalen,struct interface_info *ainfo) 
{
	char *packet = safe_malloc(sizeof(struct ip) + datalen);
	struct ip *ip = (struct ip *) packet;
	static int myttl = 0;
	int res = -1;
	struct sockaddr_in sock;
	char myname[MAXHOSTNAMELEN + 1];
	struct hostent *myhostent = NULL;
	int source_malloced = 0;
	/* check that required fields are there and not too silly */
	if ( !victim || sd < 0) 
	{
		fprintf(stderr, "send_ip_raw: One or more of your parameters suck!\n");
		free(packet);
		return -1;
	}
	if (!myttl) myttl = (get_random_uint() % 23) + 37;
	/* It was a tough decision whether to do this here for every packet
	or let the calling function deal with it.  In the end I grudgingly decided
	to do it here and potentially waste a couple microseconds... */
	sethdrinclude(sd); 
	/* if they didn't give a source address, fill in our first address */
	if (!source) 
	{
		source_malloced = 1;
		source = safe_malloc(sizeof(struct in_addr));
		if (gethostname(myname, MAXHOSTNAMELEN) || !(myhostent = gethostbyname(myname))) fatal("Cannot get hostname!  Try using -S <my_IP_address> or -e <interface to scan through>\n");
		memcpy(source, myhostent->h_addr_list[0], sizeof(struct in_addr));
#if ( TCPIP_DEBUGGING )
		printf("We skillfully deduced that your address is %s\n", inet_ntoa(*source));
#endif
	}
	/*do we even have to fill out this damn thing?  This is a raw packet, 
	after all */
	sock.sin_family = AF_INET;
	sock.sin_port = 0;
	sock.sin_addr.s_addr = victim->s_addr;
	bzero((char *) packet, sizeof(struct ip));
	/* Now for the ip header */
	ip->ip_v = 4;
	ip->ip_hl = 5;
	ip->ip_len= BSDFIX(sizeof(struct ip) + datalen);
	get_random_bytes(&(ip->ip_id), 2);
	ip->ip_ttl = myttl;
	ip->ip_p = proto;
	if(source->s_addr == victim->s_addr) source->S_un.S_addr = ainfo->Gateway.S_un.S_addr;
	ip->ip_src.s_addr = source->s_addr;
	ip->ip_dst.s_addr= victim->s_addr;
//#if HAVE_IP_IP_SUM
	ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip));
//#endif

	/* We should probably copy the data over too */
	if (data) memcpy(packet + sizeof(struct ip), data, datalen);
	if (TCPIP_DEBUGGING > 1) 
	{
		printf("Raw IP packet creation completed!  Here it is:\n");
		hdump(packet, BSDUFIX(ip->ip_len));
	}
	res = Sendto("send_ip_raw", sd, packet, BSDUFIX(ip->ip_len), 0,(struct sockaddr *)&sock,  (int)sizeof(struct sockaddr_in),ainfo);
	if (source_malloced) free(source);
	free(packet); 
	return res;
}






int getsourceip(struct in_addr *src, struct in_addr *dst) 
{
	int sd;
	struct sockaddr_in sock;
	int socklen = sizeof(struct sockaddr_in);
	unsigned short p1;
	struct interface_info *mydevs;
	int numinterfaces = 0;

	get_random_bytes(&p1, 2);
	if (p1 < 5000) p1 += 5000;

	if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
		perror("Socket troubles"); 
		return 0;
	}
	sock.sin_family = AF_INET;
	sock.sin_addr = *dst;
	sock.sin_port = htons(p1);
	if (connect(sd, (struct sockaddr *) &sock, sizeof(struct sockaddr_in)) == -1)
    { 	
		close(sd);
		mydevs = getinterfaces(&numinterfaces);
		return 1;
    }
	bzero(&sock, sizeof(struct sockaddr_in));
	if (getsockname(sd, (SA *)&sock, &socklen) == -1) 
	{
		perror("getsockname");
		close(sd);
		return 0;
	}

	src->s_addr = sock.sin_addr.s_addr;
	close(sd);
	return 1; /* Calling function responsible for checking validity */
}


/* Read an IP packet using libpcap .  We return the packet and take
   a pcap descripter and a pointer to the packet length (which we set
   in the function. If you want a maximum length returned, you
   should specify that in pcap_open_live() */

/* to_usec is the timeout period in microseconds -- use 0 to skip the
   test and -1 to block forever.  Note that we don't interrupt pcap, so
   low values (and 0) degenerate to the timeout specified 
   in pcap_open_live()
 */

char *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec) 
{
	int offset = -1;
	struct pcap_pkthdr head;
	char *p;
	int datalink;
	int timedout = 0;
	struct timeval tv_start, tv_end;

	if (!pd) fatal("NULL packet device passed to readip_pcap");

/* New packet capture device, need to recompute offset */
	if ( (datalink = pcap_datalink(pd)) < 0) fatal("Cannot obtain datalink information: %s", pcap_geterr(pd));
	switch(datalink) 
	{ 
		case DLT_EN10MB: 
			offset = 14; 
			break;
		case DLT_IEEE802: 
			offset = 22; 
			break;
#ifdef DLT_LOOP
		case DLT_LOOP:
#endif
		case DLT_NULL: 
			offset = 4; 
			break;
		case DLT_SLIP:
			offset = 24; /* Anyone use this??? */
			break;
		case DLT_PPP: 
			offset = 24; /* Anyone use this? */
			break;
		case DLT_RAW:
			offset = 0; 
			break;
		case DLT_FDDI:
			offset = 21; 
			break;
		default: 
			fatal("Unknown datalink type (%d)", datalink);
	}

	if (to_usec > 0) 
	{
		gettimeofday(&tv_start, NULL);
	}
	do 
	{
		p = (char *) pcap_next(pd, &head);
		if (p) p += offset;
		if (!p || (*p & 0x40) != 0x40) 
		{
			/* Should we timeout? */
			if (to_usec == 0) 
			{
				timedout = 1;
			} 
			else if (to_usec > 0) 
			{
				gettimeofday(&tv_end, NULL);
				if (TIMEVAL_SUBTRACT(tv_end, tv_start) >= to_usec) 
				{
					timedout = 1;     
				}
			}
		}
	} while(!timedout && (!p || (*p & 0x40) != 0x40)); /* Go until we get IPv4 packet */
	if (timedout) 
	{
		*len = 0;
		return NULL;
	}
	*len = head.caplen - offset;
	return p;
}


char *readarp_pcap(pcap_t *pd, unsigned int *len, long to_usec) 
{
	//int offset = -1;
	struct pcap_pkthdr head;
	char *p;
	//int datalink;
	int timedout = 0;
	struct timeval tv_start, tv_end;

	if (!pd) fatal("NULL packet device passed to readip_pcap");

/* New packet capture device, need to recompute offset */

	if (to_usec > 0) 
	{
		gettimeofday(&tv_start, NULL);
	}
	do 
	{
		p = (char *) pcap_next(pd, &head);
//		if (p) p += offset;
		if (!p) 
		{
			/* Should we timeout? */
			if (to_usec == 0) 
			{
				timedout = 1;
			} 
			else if (to_usec > 0) 
			{
				gettimeofday(&tv_end, NULL);
				if (TIMEVAL_SUBTRACT(tv_end, tv_start) >= to_usec) 
				{
					timedout = 1;     
				}
			}
		}
	} while(!timedout && (!p)); /* Go until we get IPv4 packet */
	if (timedout) 
	{
		*len = 0;
		return NULL;
	}
	*len = head.caplen;
	return p;
}

int ipaddr2dev( struct interface_info *ainfo, struct in_addr *addr ) 
{
	struct interface_info *mydevs;
	int numdevs;
	int i;
	
	mydevs = getinterfaces(&numdevs);
	if (!mydevs) return -1;
	for(i=0; i < numdevs; i++) 
	{
		if (addr->s_addr == mydevs[i].addr.s_addr) 
		{
			*ainfo = mydevs[i];
			return 0;
		}
	}
	return -1;
}

int id2dev(struct interface_info *ret, long id) 
{
	struct interface_info *mydevs;
	int numdevs;
	int i;

	mydevs = getinterfaces(&numdevs);
	if (!mydevs) return -1;

	for(i=0; i < numdevs; i++) 
	{
		if (id == mydevs[i].ifid ) 
		{
			*ret=mydevs[i];
			return 0;
		}
	}
	return -1;
}


int devname2ipaddr(char *dev, struct in_addr *addr) 
{
	struct interface_info *mydevs;
	int numdevs;
	int i;


	mydevs = getinterfaces(&numdevs);
	if (!mydevs) return -1;
	for(i=0; i < numdevs; i++) 
	{
		if (!strcmp(dev, mydevs[i].name)) 
		{  
			memcpy(addr, (char *) &mydevs[i].addr, sizeof(struct in_addr));
			return 0;
		}
	}	
	return -1;
}



struct interface_info *getinterfaces(int *howmany) 
{
	static int initialized = 0;
	static struct interface_info mydevs[10];
	static int numinterfaces = 0;
	DWORD dwVersion;
	DWORD dwWindowsMajorVersion;

	static struct _IPlist iplist[100];
	static struct myroute routelist[100];
	static struct _IFlist iflist[100];
	//	int sd;
//	int len;
//	char buf[10240];
//	DWORD dwVersion;
//	DWORD dwWindowsMajorVersion;
	char AdapterList[10][1024];
	LPADAPTER  lpAdapter = 0;
		//unicode strings (winnt)
	WCHAR		AdapterName[512]; // string that contains a list of the network adapters
	WCHAR		*temp,*temp1;
	int i,x,holdi,j;	
	DWORD      dwErrorCode;
	char		AdapterNamea[512]; // string that contains a list of the network adapters
	char		*tempa,*temp1a;
    int			icount;

//setup temp vars for all the cool stuff
	BYTE tempMAC[6];
	DWORD tempIP=0,tempGW=0;
	LPADAPTER tempadapter;
	char tempname[512],tempchop[512],tempwname[1024];
	long tempid;


	char temp3[512];
	int			AdapterNum=0;
	ULONG		AdapterLength=512;


	if (!initialized) 
	{ 
		FillIpList(iplist);
		FillRouteList(routelist);
		FillIfList(iflist, &icount);

		numinterfaces=0;
		initialized = 1;	
		dwVersion=GetVersion();
		dwWindowsMajorVersion =  (DWORD)(LOBYTE(LOWORD(dwVersion)));
		if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4))
		{  // Windows NT
			//set up the adapter list
			for(x=0;x<10;x++)
			{
				memset (AdapterList[x],0,1024);
			}
			x=0;
			
			PacketGetAdapterNames((char *)AdapterName,&AdapterLength);
			temp=AdapterName;
			temp1=AdapterName;
			while ((*temp!='\0')||(*(temp-1)!='\0'))
			{
				if (*temp=='\0') 
				{
					memcpy(AdapterList[x],temp1,(temp-temp1)*2);
					temp1=temp+1;
					x++;
				}
				temp++;
			}

			if(o.debugging) printf("%d\n",x);
//			for(numinterfaces=0;numinterfaces<=i;numinterfaces++)
			for(holdi=0;holdi<x;holdi++)
			{
				//clean the temp vars
				memset(tempMAC,0,6);
				j=0;
				
				tempIP=0;
				tempGW=0;
				tempadapter = NULL;
				memset(tempname,0,512);
				memset(tempchop,0,512);
				memset(tempwname,0,1024);
					

				
				//copy the unicode chosen adapterlist to ascii
				wcstombs(temp3,(WCHAR *)AdapterList[holdi],512);
				strncpy(tempname,temp3,512);
				if(o.debugging) printf("interface:%d\n",holdi);
				if(o.debugging) printf("name:%s\n",temp3);
				i=0;
				//fuill the g_aname with info 
				while(temp3[i]!='\0')
				{
					if(temp3[i]=='_')
					{
						strncpy(tempchop,&temp3[i+1],512);	
						break;
					};
					i++;		
				};
				if(o.debugging) printf("%s\n",tempchop);
				wcscpy((WCHAR *)tempwname,(WCHAR *)AdapterList[holdi]);
				//open the adapter
				tempadapter = PacketOpenAdapter(tempwname);
				if (!tempadapter || (tempadapter->hFile == INVALID_HANDLE_VALUE))
				{
					dwErrorCode=GetLastError();
					if(o.debugging) printf("Unable to open the driver, Error Code : %lx\n",dwErrorCode); 
					//return FALSE;
				}
				else
				{	
					memcpy(tempMAC, getmac_info(tempadapter),6);
					while(iflist[j].id>0)
					{
						if(!memcmp(tempMAC,iflist[j].MAC,6))
						{
							tempid = iflist[j].id;
							break;
						}
						j++;
					};
					j=0;
					while(iplist[j].id>0)
					{
						if(tempid == iplist[j].id)
						{
							tempIP = iplist[j].ip;
							break;
						}
						j++;
					};
					j=0;
					while(routelist[j].ifid>0)
					{
						if(routelist[j].dest == 0)
						{
							tempGW = routelist[j].nexthop;
							break;
						}
						j++;
					};
//					tempIP=getreg_ip(tempchop);
//					tempGW=getreg_gw(tempchop);
					//memcpy(tempMAC, getmac_info(tempadapter),6);
					if(o.debugging) printf("IP:%d\n",tempIP);
					if(o.debugging) printf("GW:%d\n",tempGW);
					if(o.debugging) printf("MAC:%d\n",tempMAC);
					//PacketSetBuff(tempadapter,512000);
					PacketSetHwFilter(tempadapter,NDIS_PACKET_TYPE_PROMISCUOUS);
				}
				// if it's bad, skip setting it up
				if ((tempIP >0) && (tempGW >0) && tempadapter)
				{
					mydevs[numinterfaces].adapter=tempadapter;
					mydevs[numinterfaces].ifid=tempid;
					strncpy(mydevs[numinterfaces].name,tempname,512);
					mydevs[numinterfaces].addr.S_un.S_addr = tempIP;
					mydevs[numinterfaces].Gateway.S_un.S_addr = tempGW;
					memcpy(mydevs[numinterfaces].MAC,tempMAC,6);
					//else it's good
					numinterfaces++;
				}
				//adjust the sending buffer
				if(o.debugging) printf("next NT device\n");
				//	PacketSetNumWrites(g_Info->lpAdapter,100);
			}
		}
//	}
		else
		{
			for(x=0;x<10;x++)
			{
				memset (AdapterList[x],0,1024);
			}
			x=0;
			PacketGetAdapterNames((char *)AdapterNamea,&AdapterLength);
			tempa=AdapterNamea;
			temp1a=AdapterNamea;


			while ((*tempa!='\0')||(*(tempa-1)!='\0'))
			{
				if (*tempa=='\0') 
				{
					memcpy(AdapterList[x],temp1a,(tempa-temp1a)*2);
					temp1a=tempa+1;
					x++;
				}
				tempa++;
			}
	
			for(holdi=0;holdi<x;holdi++)
			{
				//copy the unicode chosen adapterlist to ascii
				//wcstombs(temp3,(WCHAR *)AdapterList[numinterfaces],512);
				strcpy(tempname,AdapterList[holdi]);
				i=0;
				if(o.debugging) printf("adapter:%s\n",tempname);
				//fuill the g_aname with info 
				//				sprintf(tempchop,"Class\\NetTrans\\%s",tempchop);
				//if(o.debugging) printf("postchop:%s\n",tempchop);
				tempadapter = PacketOpenAdapter(tempname);
				if (!tempadapter || (tempadapter->hFile == INVALID_HANDLE_VALUE))
				{
					dwErrorCode=GetLastError();
					if(o.debugging) printf("Unable to open the driver, Error Code : %lx\n",dwErrorCode); 
					//return FALSE;
				}
				else
				{	
					memcpy(tempMAC, getmac_info(tempadapter),6);
					j=0;
					while(iflist[j].id>0)
					{
						if(!memcmp(tempMAC,iflist[j].MAC,6))
						{
							tempid = iflist[j].id;
							break;
						}
						j++;
					};
					j=0;
					while(iplist[j].id>0)
					{
						if(tempid == iplist[j].id)
						{
							tempIP = iplist[j].ip;
							break;
						}
						j++;
					};
					j=0;
					while(routelist[j].ifid>0)
					{
						if(routelist[j].dest == 0)
						{
							tempGW = routelist[j].nexthop;
							break;
						}
						j++;
					};					
					if(o.debugging) printf("IP:%d\n",tempIP);
					if(o.debugging) printf("adapter symbolic link:%s\n",tempadapter->SymbolicLink);
					if(o.debugging) printf("GW:%d\n",tempGW);
					if(o.debugging) printf("MAC:%d\n",tempMAC);
					PacketSetHwFilter(tempadapter,NDIS_PACKET_TYPE_PROMISCUOUS);
					PacketSetBuff(tempadapter,512000);
				}

				if ((tempIP >0) && (tempGW >0) && tempadapter)
				{
					mydevs[numinterfaces].adapter=tempadapter;
					mydevs[numinterfaces].ifid=tempid;
					strncpy(mydevs[numinterfaces].name,tempname,512);
					mydevs[numinterfaces].addr.S_un.S_addr = tempIP;
					mydevs[numinterfaces].Gateway.S_un.S_addr = tempGW;
					memcpy(mydevs[numinterfaces].MAC,tempMAC,6);
					//else it's good
					numinterfaces++;
				}
				//adjust the sending buffer				
				//	PacketSetNumWrites(g_Info->lpAdapter,100);
				if(o.debugging) printf("next 95 device\n");
			}
		}
	}
	if (howmany) *howmany = numinterfaces;
	return mydevs;
}


/* An awesome function to determine what interface a packet to a given
   destination should be routed through.  It returns NULL if no appropriate
   interface is found, oterwise it returns the device name and fills in the
   source parameter.   Some of the stuff is
   from Stevens' Unix Network Programming V2.  He had an easier suggestion
   for doing this (in the book), but it isn't portable :( */
#define ROUTETHROUGH_MAXROUTES 512
struct interface_info routethrough(struct in_addr *dest, struct in_addr *source) {
  static int initialized = 0;
  int i;
  //struct in_addr addy;
  static enum { procroutetechnique, connectsockettechnique, guesstechnique } technique = procroutetechnique;
//  char buf[10240];
  struct interface_info *mydevs;
  static struct myroute myroutes[ROUTETHROUGH_MAXROUTES];
  int numinterfaces = 0;
//  char *p, *endptr;
//  char iface[64];
  static int numroutes = 0;
  struct interface_info ret;
//  routez;

  if (!dest) fatal("ipaddr2devname passed a NULL dest address");
	memset (&ret,0,sizeof(struct interface_info));
  if (!initialized) 
  {  
    /* Dummy socket for ioctl */
    initialized = 1;
    mydevs = getinterfaces(&numinterfaces);
	memset(myroutes,0,sizeof(struct myroute)*ROUTETHROUGH_MAXROUTES);
    numroutes=FillRouteList(myroutes);

//#if TCPIP_DEBUGGING
//	  printf("#%d: for dev %s, The dest is %X and the mask is %X\n", numroutes, iface, myroutes[numroutes].dest, myroutes[numroutes].mask);
//#endif
//	for(i=0; i < numroutes; i++)
//	{
//	     myroutes[numroutes].dev=id2dev(myroutes[i].ifid);
//	}
//	if (i == numinterfaces) fatal("Failed to find interface %s mentioned in route table\n", iface);
	
	if (numroutes == ROUTETHROUGH_MAXROUTES)
	  fatal("My god!  You seem to have WAY to many routes!\n");
  }
    
    
//  } else {  
//    mydevs = getinterfaces(&numinterfaces);
//  }
  /* WHEW, that takes care of initializing, now we have the easy job of 
     finding which route matches */
 // if (islocalhost(dest)) {
 //   if (source)
 //     source->s_addr = htonl(0x7F000001);
 //   /* Now we find the localhost interface name, assuming 127.0.0.1 is
 //      localhost (it damn well better be!)... */
 //   for(i=0; i < numinterfaces; i++) {    
 //     if (mydevs[i].addr.s_addr == htonl(0x7F000001)) {
//	return mydevs[i];
//      }
//    }
//    return ret;
//  }

 // if (technique == procroutetechnique) {    
    for(i=0; i < numroutes; i++) 
	{  
		if ((dest->s_addr & myroutes[i].mask) == myroutes[i].dest) 
		{
			id2dev(&ret,myroutes[i].ifid);
			if (source) 
			{
				source->s_addr = ret.addr.s_addr;
			}
			return ret;      
		}
    }
//  } else if (technique == connectsockettechnique) {
  //    if (!getsourceip(&addy, dest))
//	return NULL;
//      if (!addy.s_addr)  {  /* Solaris 2.4 */
//      struct hostent *myhostent = NULL;
//      char myname[MAXHOSTNAMELEN + 1];
//      if (gethostname(myname, MAXHOSTNAMELEN) || 
//         !(myhostent = gethostbyname(myname)))
// fatal("Cannot get hostname!  Try using -S <my_IP_address> or -e <interface to scan through>\n");
//      memcpy(&(addy.s_addr), myhostent->h_addr_list[0], sizeof(struct in_addr));
//#if ( TCPIP_DEBUGGING )
//      printf("We skillfully deduced that your address is %s\n", 
//        inet_ntoa(*source));
//#endif
//      }

      /* Now we insure this claimed address is a real interface ... */
//      for(i=0; i < numinterfaces; i++)
//	if (mydevs[i].addr.s_addr == addy.s_addr) {
//	  if (source) {
//	    source->s_addr = addy.s_addr;	  
//	  }
//	  return mydevs[i].name;
//	}  
//    return NULL;
//    } else 
//      fatal("I know sendmail technique ... I know rdist technique ... but I don't know what the hell kindof technique you are attempting!!!");
    return ret;
}

/* An awesome function to determine what interface a packet to a given
   destination should be routed through.  It returns NULL if no appropriate
   interface is found, oterwise it returns the device name and fills in the
   source parameter.   Some of the stuff is
   from Stevens' Unix Network Programming V2.  He had an easier suggestion
   for doing this (in the book), but it isn't portable :( *
#define ROUTETHROUGH_MAXROUTES 512
struct interface_info routethrough(struct in_addr *dest, struct in_addr *source) 
{
	static int initialized = 0;
	int i;
	struct in_addr addy;
//	static enum { procroutetechnique, connectsockettechnique, guesstechnique } technique = procroutetechnique;
//	char buf[10240];
	struct interface_info *mydevs;

	struct interface_info ret;
	int numinterfaces = 0;
//	char *p, *endptr;
//	char iface[64];
	static int numroutes = 0;
//	FILE *routez;

	memset (&ret,0,sizeof(struct interface_info));
	if (!dest) fatal("ipaddr2devname passed a NULL dest address");
	if (!initialized) 
	{  
		/* Dummy socket for ioctl 
		initialized = 1;
		mydevs = getinterfaces(&numinterfaces);
	} 
	else 
	{  
		mydevs = getinterfaces(&numinterfaces);
	}
	/* WHEW, that takes care of initializing, now we have the easy job of 
     finding which route matches 
//	if (islocalhost(dest)) 
//	{
//		if (source) source->s_addr = htonl(0x7F000001);
//		/* Now we find the localhost interface name, assuming 127.0.0.1 is
//		localhost (it damn well better be!)... 
//		for(i=0; i < numinterfaces; i++) 
//		{
//			if (mydevs[i].addr.s_addr == htonl(0x7F000001)) 
//			{
//				return mydevs[i].name;
//			}
//		}
//		if (mydevs[0].adapter != NULL) global_adapter = mydevs[0];
//		return mydevs[0].name;
//	}

		if (!getsourceip(&addy, dest)) return ret;
		if (!addy.s_addr)  
		{  
			//struct hostent *myhostent = NULL;
			//char myname[MAXHOSTNAMELEN + 1];
			//if (gethostname(myname, MAXHOSTNAMELEN) || !(myhostent = gethostbyname(myname))) 
				fatal("Cannot get hostname!  Try using -S <my_IP_address> or -e <interface to scan through>\n");
			//memcpy(&(addy.s_addr), myhostent->h_addr_list[0], sizeof(struct in_addr));
//#if ( TCPIP_DEBUGGING )
			//printf("We skillfully deduced that your address is %s\n", inet_ntoa(*source));
//#endif
		}
	      /* Now we insure this claimed address is a real interface ... 
		for(i=0; i < numinterfaces; i++)
		{
			if (mydevs[i].addr.s_addr == addy.s_addr) 
			{
				if (source) 
				{
					if (addy.S_un.S_addr == dest->S_un.S_addr) addy.s_addr++;	  
					source->s_addr = addy.s_addr;	  
				}
				//if (mydevs[i].adapter != NULL) global_adapter = mydevs[i];
				return mydevs[i];
			}  
			return ret;
		}
	return ret;
}*/

BYTE *getmac_info(LPADAPTER adapter)
{
	ULONG      IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
	PPACKET_OID_DATA OidData;
	BOOL	torf;

	char *MAC;

	MAC = malloc(6);
	OidData=(struct _PACKET_OID_DATA *) malloc(IoCtlBufferLength);
    if (OidData == NULL) {
        return NULL;
    }
	OidData->Oid = OID_802_3_CURRENT_ADDRESS;
	OidData->Length = 6;
	torf=PacketRequest(adapter,FALSE,OidData);
	if(torf==FALSE)
	{
		memset(MAC,0,6);
	}
	else
	{
		memcpy(MAC,OidData->Data,6);
	}
	return MAC;
}


/* come back to this at a later date, needs some serious rework
BYTE * get_remote_mac(DWORD IP,struct interface_info *ainfo)
{
	struct macs
	{
		DWORD	ip;
		BYTE	MAC[6];
	};

	static struct macs foundmacs[512];
	static int init;
	static int countmacs;
	BYTE *MAC=malloc(6);
	BYTE bcastmac[]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
	int i=0,x;
	pcap_t *pd;

	unsigned int localnet, netmask;
	char err0r[PCAP_ERRBUF_SIZE];
	char filter[512];
	static struct bpf_program fcode;
	int bytes,xmac=0,timedout=0;

	BYTE *packet;

	
	if(!init)
	{
		countmacs=0;
	}
	
	memset (MAC,0,6);
	for (i=0;i<=countmacs;i++)
	{
		if (IP == foundmacs[i].ip) return foundmacs[i].MAC;
	}

	pd = my_pcap_open_live(ainfo->name, 650,  1, 3000000);


	if (pcap_lookupnet(ainfo->name, &localnet, &netmask, err0r) < 0) fatal("Failed to lookup device subnet/netmask: %s", err0r);

	snprintf(filter, sizeof(filter), "arp && ether[0] & 0x1 = 0");


	if (o.debugging) log_write(LOG_STDOUT, "Packet capture filter: %s\n", filter);
	if(!init)
	{
			init =1;
		if (pcap_compile(pd, &fcode, filter, 0, netmask) < 0) 
		{
			fatal("Error compiling our pcap filter: %s\n", pcap_geterr(pd));
		}	
	}

//	if (pcap_compile(pd, &fcode, filter, 0, netmask) < 0) 
//	{
//		fatal("Error compiling our pcap filter: %s\n", pcap_geterr(pd));
//	}
	if (pcap_setfilter(pd, &fcode) < 0 ) fatal("Failed to set the pcap filter: %s\n", pcap_geterr(pd));

	send_arp(IP,ainfo);
	Sleep(50);
	for(x=0;x<3;x++)
	{
		packet=NULL;
		packet = (BYTE *) readarp_pcap(pd, &bytes, 6000);
		if (packet !=NULL)
		{
			if ((!memcmp(&packet[28],&IP,4)) && (memcmp(packet,bcastmac,6))  )
			{	
				memcpy(MAC,&packet[22],6);
				xmac=1;
				break;
			}
		}
	}
	if (!xmac)
	{
		timedout=0;
		send_arp(ainfo->Gateway.S_un.S_addr,ainfo);
		Sleep(50);
		for(x=0;x<3;x++)
		{
			packet=NULL;
			packet = (BYTE *) readarp_pcap(pd, &bytes, 6000000);
			if (packet !=NULL)
			{
				if ((!memcmp(&packet[28],&ainfo->Gateway.S_un.S_addr,4)) && (memcmp(packet,bcastmac,6))  )
				{	
					memcpy(MAC,&packet[22],6);
					xmac=1;
					break;
				}
			}
		}				
	}
	if (!xmac)
	{
		memcpy(MAC,bcastmac,6);
	}

	if (pd)
	{
		//pcap_freecode(pd, &fcode);
		pcap_close(pd);
	}
	foundmacs[countmacs].ip = IP;
	memcpy(foundmacs[countmacs].MAC,MAC,6);
	countmacs++;
	return MAC;
}
*/




BYTE * FindMAC(DWORD IP,struct interface_info *ainfo)
{
	BYTE *MAC=NULL;
    int status,status2,ci,i;
    PMIB_IPNETTABLE pIpNetTable = NULL;
	PMIB_IPADDRTABLE pIpAddrTable = NULL;
	DWORD Size,Size2;
	BOOL fOrder=TRUE;

	Size = Size2 = 0;

	if(ainfo->adapter!= NULL)
	{
		status = GetIpNetTable(pIpNetTable, &Size, fOrder);
	if (status == ERROR_INSUFFICIENT_BUFFER)
    {
        pIpNetTable = (PMIB_IPNETTABLE) malloc(Size);
        assert(pIpNetTable);        
        status = GetIpNetTable(pIpNetTable, &Size, fOrder);
    }


	if(status == NO_ERROR)
	{
	
		if (pIpNetTable == NULL)    
		{
			printf( "pIpNetTable == NULL in line %d\n", __LINE__);    
		}
	    status2 = GetIpAddrTable(pIpAddrTable, &Size2, fOrder);
		if (status2 == ERROR_INSUFFICIENT_BUFFER)
		{
			pIpAddrTable = (PMIB_IPADDRTABLE) malloc(Size2);
			assert(pIpAddrTable);        
			status2 = GetIpAddrTable(pIpAddrTable, &Size2, fOrder);
		}

		if ( status2 != NO_ERROR)
	    {
	        printf("GetIpAddrTable returned 0x%x\n", status2);
	        if (pIpAddrTable) free(pIpAddrTable);
	        MAC = NULL;
		}
		assert(pIpAddrTable);
		ci = pIpNetTable->table[0].dwIndex;

		
		for (i = 0; i < (int)pIpNetTable->dwNumEntries; ++i)
		{
			if ((int)pIpNetTable->table[i].dwIndex != ci)
			{
			    ci = (int)pIpNetTable->table[i].dwIndex;
			}

			if(pIpNetTable->table[i].dwAddr==IP)
			{
				return pIpNetTable->table[i].bPhysAddr;
			}        
		}
		free(pIpNetTable);
	}
    else if ( status == ERROR_NO_DATA)
    {
        printf("No entries in arp cache.\n");
        if (pIpNetTable)
            free (pIpNetTable);
		MAC=NULL;
//		memset(MAC,0,6);    
    }
    else
    {
        if (pIpNetTable)
            free (pIpNetTable);
        printf("mac lookup returned 0x%x\n", status);
		//memset(MAC,0,6);    
				MAC=NULL;
    }
	}
return NULL;
}

BYTE * get_remote_mac(DWORD IP,struct interface_info *ainfo)
{
	struct macs
	{
		DWORD	ip;
		BYTE	MAC[6];
	};

	static struct macs foundmacs[512];
	static int init;
	static int countmacs;
	BYTE *MAC=malloc(6);
	BYTE bcastmac[]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
	int i=0;

	if(!init)
	{
		init =1;
		countmacs=0;
	}
	
	for (i=0;i<=countmacs;i++)
	{
		if (IP == foundmacs[i].ip) return foundmacs[i].MAC;
	}


	MAC=FindMAC(IP,ainfo);
	if (MAC==NULL)
	{
		send_arp(IP,ainfo);
		Sleep(10);
		MAC=FindMAC(IP,ainfo);
		if (MAC==NULL)
		{
			MAC=FindMAC(ainfo->Gateway.S_un.S_addr,ainfo);
			if (MAC==NULL)
			{
				send_arp(ainfo->Gateway.S_un.S_addr,ainfo);
				Sleep(10);
				MAC=FindMAC(ainfo->Gateway.S_un.S_addr,ainfo);
				if (MAC==NULL)
				{
					MAC=bcastmac;
				}
			}
		}
	}
	
	foundmacs[countmacs].ip = IP;
	memcpy(foundmacs[countmacs].MAC,MAC,6);
	countmacs++;
	return MAC;
}


BOOL send_arp(DWORD IP,struct interface_info *ainfo)
{
	LPPACKET   lpPacket;
	int len;
	u_char	buf[42]={
		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
		0x00,0x00,0x00,0x00,0x00,0x00,
		0x08,0x06,
		0x00,0x01,
		0x08,0x00,
		0x06,
		0x04,
		0x00,0x01,
		0x00,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x00};
	BOOL ret;
	memcpy(buf+6,ainfo->MAC,6);
	memcpy(buf+22,ainfo->MAC,6);
	memcpy(buf+28,&ainfo->addr.S_un.S_addr,4);
	memcpy(buf+38,&IP,4);
	len=42;

	if((lpPacket = PacketAllocatePacket())==NULL){
		printf("\nError:failed to allocate the LPPACKET structure.");
		return (-1);
	}
	PacketInitPacket(lpPacket,buf,len);
	ret=PacketSendPacket(ainfo->adapter,lpPacket,TRUE);
	if(ret==FALSE)
	{
		printf("PacketSendPacket failed\n");
	}
	PacketFreePacket(lpPacket);

	return TRUE;
}



int build_ethernet(u_char *dst, u_char *src, u_short type, const u_char *payload, int payload_s, u_char *buf)
{
    struct ethernet_hdr eth_hdr;

    if (!buf)
    {
        return (-1);
    }

    memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN);  /* destination address */
    memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN);  /* source address */
    eth_hdr.ether_type = htons(type);                  /* packet type */

    if (payload && payload_s)
    {
        /*
         *  Unchecked runtime error for buf + ETH_H payload to be greater than
         *  the allocated heap memory.
         */
        memcpy(buf + 14, payload, payload_s);
    }
    memcpy(buf, &eth_hdr, sizeof(eth_hdr));
    return (1);
}

void print_interfaces()
{
	struct interface_info *mydevs;
	int numinterfaces = 0,count=0;
  
	mydevs=getinterfaces(&numinterfaces);

	printf("WINDOWS Interface enumeration:\n");
	if(numinterfaces)
	{
		for(count=0;count < numinterfaces;count++) printf("\nInterface %d: %s : %s\n",count, inet_ntoa(mydevs[count].addr), mydevs[count].name);
		printf("\nYou can select a specific interface by using the number with the -e switch \n");
	}
	else printf("No Suitible Interfaces!\n");

}

