/*
 * This program tries how to set an ip to a network interface without having to call extra commands
 */

#define _GNU_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h> 
#include <sys/socket.h> 
#include <stdio.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>  

typedef unsigned char u8;
typedef unsigned short u16;

int fd;
int set_interface(char *interface);
struct ifreq *req;

//Get the ip string from a sockaddr_in
char *addr2str(struct sockaddr_in *sock) {
        char *ret;
        union {
                char car[4];
                __u32 ent;
        } ipv4_addr;
        ipv4_addr.ent=sock->sin_addr.s_addr;
        union {
                char car[4];
                __u32 ent;
        } ipv4_port;
        ipv4_port.ent=sock->sin_port;
        asprintf(&ret"%hhu.%hhu.%hhu.%hhu"ipv4_port.car[0], ipv4_port.car[1], ipv4_addr.car[0], ipv4_addr.car[1]);
        return ret;
}

//Get a sockaddr_in structure, with an ip string
struct sockaddr_in *str2addr(char *addresse) {
        struct sockaddr_in *ret=malloc(sizeof(struct sockaddr_in));
        ret->sin_family=AF_INET;
        //Separate both parts of the address
        //Get the port part
        union {
                char car[4];
                __u32 ent;
        } ipv4_port;
        ipv4_port.car[2]=0;
        ipv4_port.car[3]=0;
        sscanf(addresse"%hhu.%hhu.%hhu.%hhu", &(ipv4_port.car[0]), &(ipv4_port.car[1]), &(ipv4_port.car[2]), &(ipv4_port.car[3]));
        ret->sin_addr.s_addr=ipv4_port.ent;
        return ret;
}

//Takes the interface and the ip as arguments and set the ip to the interface
int setaddr(char *interfacechar *ip) {
        if(set_interface(interface)!=0)
                return -1;
        if(ioctl(fdSIOCGIFADDRreq)!=0)
                return -1;
        struct sockaddr *socket=(struct sockaddr*)str2addr(ip);
        req->ifr_addr=*socket;
        if(ioctl(fdSIOCSIFADDRreq)!=0)
                return -1;
        return 0;
}

//Set the current if_req
int set_interface(char *interface) {
        strcpy(req->ifr_nameinterface);
        if(ioctl(fdSIOCGIFFLAGSreq)!=0) {
                return -1;
        }
        return 0;
}

//Get the current address of a network interface
char *getaddr(char *interface) {
        if(set_interface(interface)==-1)
                return NULL;
        if(ioctl(fdSIOCGIFADDRreq)!=0)
                return NULL;
        return addr2str((struct sockaddr_in*)req->ifr_addr.sa_data);
}

int main(int argcchar **argvchar **envp) {
        int i;
        struct if_nameindex *index;
        fd=socket(PF_PACKETSOCK_RAW0);
        req=malloc(sizeof(struct ifreq));
        index=if_nameindex();
        //Let's navigate into available interfaces
        for(i=0;index[i].if_name!=NULL;i++) {
                if(strstr(index[i].if_name"ath")==index[i].if_name ) {
                        struct sockaddr_ll addr;
                        bzero(&addrsizeof(addr));
                        addr.sll_family=AF_PACKET;
                        addr.sll_protocol=htons(0x03);
                        addr.sll_pkttype=PACKET_HOST;
                        addr.sll_ifindex=index[i].if_index;
                        addr.sll_halen=0;
                        bind(fd, (struct sockaddr*)&addrsizeof(addr));
                        char str[]="\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0";
                        str[0]=index[i].if_index;
                        setsockopt(fdSOL_PACKETPACKET_ADD_MEMBERSHIPstr16);
                        {
                                u8 *framehdr=malloc(60);
                                int i;
                                for(i=0;i<60;i++)
                                        framehdr[i]=0;
                                ((u16*)framehdr)[0]=0x0008;
                                memcpy(((u8*)framehdr)+4 , "\xff\xff\xff\xff\xff\xff",6);
                                memcpy(((u8*)framehdr)+10"\x01\x1a\xe9\x1e\xb7\xf8",6);
                                memcpy(((u8*)framehdr)+16"\xff\xff\xff\xff\xff\xff",6);
                                //char str[]="\xaa\xaa\x03\x00\x00\x00\x08\xfe\x01\x00\x00\x1a\xe9\x1e\xb7\xf9\x68\x75\x73\x73\x6f\x6e\x00\x00";
                                char str[]="plop";
                                memcpy(framehdr+24strsizeof(str)-1);

                                framehdr[22]=0xb0;
                                framehdr[23]=0x02;
                                write(fdframehdr24+sizeof(str)-1);
                                free(framehdr);
                        }
                }
        }
        if_freenameindex(index);
        close(fd);
        free(req);
        return 0;
}