#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/socket.h>

#include <pcap.h>

#include <netinet/in.h>

#include <arpa/inet.h>

//This code generates an ICMP packet

struct ETHER_HDR{

        unsigned char d_mac[6];                                // destination MAC address

        unsigned char s_mac[6];                                // source MAC address

        unsigned char typecode[2];                        // type code

};

struct IP_HDR{

        unsigned char  ip_ver_ihl;                        // 4-bit IPv4 version  

                                                        // 4-bit header length (in 32-bit words)

                                                        // normally=5 Means 20 Bytes may be 24  

        unsigned char  ip_tos;                                // IP type of service    

        unsigned short ip_total_length;                        // Total length    

        unsigned short ip_id;                                // Unique identifier    

        unsigned short ip_flag_frag_off;                // Flags & Fragment offset field          

        unsigned char  ip_ttl;                                // Time to live    

        unsigned char  ip_protocol;                        // Protocol(TCP,UDP etc)    

        unsigned short ip_checksum;                        // IP checksum    

        unsigned int   ip_srcaddr;                        // Source address    

        unsigned int   ip_destaddr;                        // Source address

};

void prep_ip_hdr(unsigned char* pkt,struct IP_HDR *iph);

void prep_ether_hdr(unsigned char* pkt,struct ETHER_HDR *eh);

int main()

{

            

            pcap_if_t *alldevs;

            pcap_if_t *d;

            int i=0;

            char errbuf[PCAP_ERRBUF_SIZE];

        pcap_t * fp;

   

            /* Retrieve the device list from the local machine */

            if (pcap_findalldevs(&alldevs, errbuf) == -1)

        {

                fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf);

                exit(1);

        }

   

            /* Print the list of devices */

            for(d= alldevs; d != NULL; d= d->next)

            {

                printf("%d. %s", ++i, d->name);

                if (d->description)

                        printf(" (%s)\n", d->description);

                else

                        printf(" (No description available)\n");

            }

   

            if (i == 0)

            {

                printf("\nNo interfaces found! Run the file as admin or use sudo.\n");

                return 0;

            }

        printf("Enter the interface number (1-%d):",i);

        int inum; scanf("%d", &inum);

        if(inum < 1 || inum > i)

        {

                      printf("\nInterface number out of range.\n");

                      /* Free the device list */

                      pcap_freealldevs(alldevs);

                      return 0;

        }

        for (d=alldevs, i=0; i< inum-1 ;d=d->next, i++);

        

        fp = pcap_open_live(d->name, 65536,1,1000,errbuf);  //open the device to enable sending the packet

        

        //  The packet to be sent is made here        

        unsigned char packet[100];

        struct ETHER_HDR *eh;

        struct IP_HDR *iph;

        eh = (struct ETHER_HDR*) (packet);        //we point the eh pointer to the first index of the character array packet

        eh->d_mac[0]=255;

            eh->d_mac[1]=255;

            eh->d_mac[2]=255;

            eh->d_mac[3]=255;

            eh->d_mac[4]=255;

            eh->d_mac[5]=255;

        eh->s_mac[0]=2;

        eh->s_mac[1]=2;

        eh->s_mac[2]=2;

        eh->s_mac[3]=2;

        eh->s_mac[4]=2;

            eh->s_mac[5]=2;

        eh->typecode[0] = 0x08; //so that the payload is interpreted as an IP protocol packet,this is the Type Code for IP

        eh->typecode[1] = 0x00;

          prep_ether_hdr(packet, eh);

        iph = (struct IP_HDR*) (packet + sizeof(struct ETHER_HDR));        //we need to point the iph pointer just below the ethernet header

        iph->ip_ver_ihl = 0x45;

        iph->ip_tos = 0;

        iph->ip_total_length = 100 - sizeof(struct ETHER_HDR);

        iph->ip_id = 2;

        iph->ip_flag_frag_off = htons(0x4000);         // 010 0000000000000 = 0 1000 0000        // see definition of htons, if not used the byte order

                                                                                        //in the packet will be changed

                                                // 0000 0000 = 0x4000

        iph->ip_ttl = 3;

        iph->ip_protocol = 0x01;

        iph->ip_checksum = 0;

        iph->ip_srcaddr = inet_addr("192.168.1.3"); // change IP as needed

        iph->ip_destaddr = inet_addr("192.168.1.2");// change IP as needed

        //prep_ip_hdr(packet, iph);

        /* Send down the packet */

        if (pcap_sendpacket(fp, packet, 100 /* size */) != 0)               //send the packet that we just made, the last parameter size is important

        {                                                                //it actually tells how many bytes are to be put out on the wire

                fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(fp));

        return 0;

            }

            /* We don't need any more the device list. Free it */

            pcap_freealldevs(alldevs);

            return 1;

}

void prep_ether_hdr(unsigned char *pkt,struct ETHER_HDR *eh)

{

        memcpy((pkt), eh->d_mac,6);

        memcpy((pkt+6), eh->s_mac,6);

        memcpy((pkt+12), &(eh->typecode),2);        

}

void prep_ip_hdr (u_char* pkt, struct IP_HDR* iph)

{

// COMPLETE THIS FUNCTION

}