#ifndef DELIVER_SENDPKT_H
#define DELIVER_SENDPKT_H

#include <arpa/inet.h>
#include <netinet/in.h>



#ifndef ETHER_ADDR_LEN
#define ETHER_ADDR_LEN 6
#endif 

#define ARPHRD_ETHER     1                  /* ethernet hardware format */

#define SENDPACKET_ETH_H			0xe     /* Etherner header:     14 bytes */
#define SENDPACKET_IP_H            	0x14    /* IP header:           20 bytes */
#define SENDPACKET_TCP_H           	0x14    /* TCP header:          20 bytes */


struct mesa_ethernet_hdr
{
	unsigned char  ether_dhost[ETHER_ADDR_LEN];    /* destination ethernet address */
	unsigned char  ether_shost[ETHER_ADDR_LEN];    /* source ethernet address */
	unsigned short ether_type;                     /* packet type ID */
};



struct mesa_ip4_hdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
    u_int8_t ip_hl:4,         /* header length */
            ip_v:4;         /* version */
#elif __BYTE_ORDER == __BIG_ENDIAN
    u_int8_t ip_v:4,          /* version */
            ip_hl:4;        /* header length */
#else
#error "Please check <endian.h>"
#endif
    u_int8_t ip_tos;          /* type of service */
    u_int16_t ip_len;         /* total length */
    u_int16_t ip_id;          /* identification */
    u_int16_t ip_off;
    u_int8_t ip_ttl;          /* time to live */
    u_int8_t ip_p;            /* protocol */
    u_int16_t ip_sum;         /* checksum */
    struct in_addr ip_src, ip_dst; /* source and dest address */
};




/*
 *  IPv6 packet header prototype, add by LiJia 2012-03-19.
 */
struct mesa_ip6_hdr
{
    u_int8_t ip6_flags[4]; /* version, traffic-class, flow-label */
    u_int16_t ip6_payload_len;  /* payload length, not contain header */
    u_int8_t ip6_nxt_hdr;       /* next header, same as protocol in IPv4 */
    u_int8_t ip6_hop;           /* hop limit, same as TTL in IPv4 */
    struct in6_addr ip6_src;     /* source address */
    struct in6_addr ip6_dst;     /* dest address */
};


#ifndef TH_FIN
#define TH_FIN    0x01
#endif
#ifndef TH_SYN
#define TH_SYN    0x02
#endif
#ifndef TH_RST
#define TH_RST    0x04
#endif
#ifndef TH_PUSH
#define TH_PUSH   0x08
#endif
#ifndef TH_ACK
#define TH_ACK    0x10
#endif
#ifndef TH_URG
#define TH_URG    0x20
#endif 


struct mesa_tcp_hdr
{
    u_int16_t th_sport;       /* source port */
    u_int16_t th_dport;       /* destination port */
    u_int32_t th_seq;          /* sequence number */
    u_int32_t th_ack;          /* acknowledgement number */
#if __BYTE_ORDER == __LITTLE_ENDIAN
    u_int8_t th_x2:4,         /* (unused) */
           th_off:4;        /* data offset */
#elif __BYTE_ORDER == __BIG_ENDIAN
    u_int8_t th_off:4,        /* data offset */
           th_x2:4;         /* (unused) */
#else
#error "Please check <endian.h>"
#endif
    u_int8_t  th_flags;       /* control flags */
    u_int16_t th_win;         /* window */
    u_int16_t th_sum;         /* checksum */
    u_int16_t th_urp;         /* urgent pointer */
};


/*
 *  UDP packet header prototype.
 */
struct mesa_udp_hdr
{
    u_int16_t uh_sport;   /* soure port */
    u_int16_t uh_dport;   /* destination port */
    u_int16_t uh_ulen;    /* length */
    u_int16_t uh_sum;     /* checksum */
};

unsigned int deliver_rand(void);
unsigned int deliver_rand_range(unsigned int start, unsigned int end);
int deliver_get_dev_mac(const char *device, unsigned char mac[6]);
int deliver_mac_pton(const char *str, int delim, char *mac);
int deliver_do_checksum(unsigned char *buf, int protocol, int len);
int deliver_build_ethernet(unsigned char *dst, unsigned char *src, unsigned short type,
            				const unsigned char *payload, int payload_s, unsigned char *buf);
int deliver_build_ethhdr(unsigned char *dst, unsigned char *src, unsigned short type,unsigned char *buf);
int deliver_build_ipv6(unsigned char traffic_class, unsigned int flow_lable,
                              unsigned short len, unsigned char next_header, unsigned char hop,
                              const struct in6_addr *src, const struct in6_addr *dst,
                              const unsigned char *payload, int payload_s, unsigned char *buf);
int deliver_build_ipv4(unsigned short carry_layer_len, unsigned char tos, unsigned short id, 
		unsigned short frag, unsigned char ttl, unsigned char prot, unsigned int src, unsigned int dst, 
		const unsigned char *payload,int payload_s, unsigned char *buf);
int deliver_build_tcp(unsigned short sp, unsigned short dp, unsigned int seq, unsigned int ack, 
						unsigned char th_flags, unsigned short win, unsigned short urg, 
						const unsigned char *payload, int payload_s, unsigned char *buf);

#endif

