#include <sys/socket.h> #include <linux/if_ether.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <linux/if_packet.h> #include <ctype.h> #include <sys/types.h> #include <sys/socket.h> #include <linux/sockios.h> #include <sys/ioctl.h> #include <net/if.h> #include <fcntl.h> #include <time.h> #ifndef ARPHRD_ETHER #define ARPHRD_ETHER 1 #endif #ifndef ARPOP_REQUEST #define ARPOP_REQUEST 1 #endif #ifndef ARPOP_REPLY #define ARPOP_REPLY 2 #endif #define VERSION 2 /* Trame ARP */ struct arphdr{ unsigned short arp_hrdad; unsigned short arp_prot; unsigned char arp_halen; unsigned char arp_prlen; unsigned short arp_opcode; unsigned char ar_sha[ETH_ALEN]; unsigned char ar_sip[4]; unsigned char ar_tha[ETH_ALEN]; unsigned char ar_tip[4]; }; /* Ethernet header*/ struct packet{ struct ethhdr ethhdr; struct arphdr arphdr; } *ppacket, *ppacket_r; /* We get IP address, netmask, index number and mac address of the adapter */ int get_iface_infos(struct packet * ppacket, int * index, char * iface, struct sockaddr_in * ipaddr, struct sockaddr_in * netmask){ int tmpsock; struct ifreq ifr; if((tmpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0){ perror("Socket creation problem"); return(1); } /* Initialize */ memset(&ifr, 0x0, sizeof(struct ifreq)); /* We put into the ifreq srtuct the name of adapter */ strncpy(ifr.ifr_name, iface, IF_NAMESIZE-1); /* IP */ if(ioctl(tmpsock, SIOCGIFADDR, &ifr)< 0){ close(tmpsock); perror("Cannot get the ip address"); return(1); } memcpy(&ipaddr->sin_addr, &((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr, 4); memcpy(ppacket->arphdr.ar_sip, &((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr, 4); /*******************/ /* SNM */ if(ioctl(tmpsock, SIOCGIFNETMASK, &ifr)< 0){ close(tmpsock); perror("Cannot get the net submask"); return(1); } memcpy(&netmask->sin_addr, &((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr, 4); /*******************/ /* MAC */ if(ioctl(tmpsock, SIOCGIFHWADDR, &ifr)< 0){ close(tmpsock); perror("Cannot get the mac address"); return(1); } memcpy(ppacket->ethhdr.h_source, (unsigned char *)&ifr.ifr_hwaddr.sa_data, ETH_ALEN); memcpy(ppacket->arphdr.ar_sha, (unsigned char *)&ifr.ifr_hwaddr.sa_data, ETH_ALEN); /*******************/ /* INDEX */ if(ioctl(tmpsock, SIOCGIFINDEX, &ifr)< 0){ close(tmpsock); perror("Cannot get the interface index"); return(1); } *index = ifr.ifr_ifindex; /*******************/ close(tmpsock); return(0); } int main(int argc, char ** argv){ int sd,flag,index; unsigned long unet,uhost,ipdst,tip; /* The name of the interface is given in parameter to the binary */ char * iface; if(argc==2){ iface = argv[1]; }else{ printf("IPDISCOVER binary ver. %d \nUsage : ipdiscover [iface name]\n", VERSION); exit(0); } struct sockaddr_in ipaddr, netmask; memset(&ipaddr, 0x00, sizeof(struct sockaddr_in)); memset(&netmask, 0x00, sizeof(struct sockaddr_in)); /* Arp structure */ ppacket = malloc(sizeof(struct packet)); /* Pour lire les infos de l'interface */ if(get_iface_infos(ppacket, &index, iface, &ipaddr, &netmask)){ printf("Cannot get all adapter parameters - stop\n"); exit(1); } /* Tie to adapter */ struct sockaddr_ll sll = {0x0}; sll.sll_family = AF_PACKET; sll.sll_protocol = htons(ETH_P_ARP); sll.sll_ifindex = index; /* Socket creation */ sd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ARP)); if(sd < 0){ perror("Socket creation problem"); exit(1); } if(fcntl(sd,F_SETFL,O_NONBLOCK) == -1){ perror("Cannot set socket mode to O_NONBLOCK"); exit(1); } /* Bind */ if(bind(sd, (struct sockaddr*) &sll, sizeof(sll)) == -1){ perror("Bind error"); exit(1); } /* Building the packet */ memset(ppacket->ethhdr.h_dest, 0xFF, 6); ppacket->ethhdr.h_proto = htons(0x806); /* arp header */ ppacket->arphdr.arp_hrdad = htons(ARPHRD_ETHER); ppacket->arphdr.arp_prot = htons(ETH_P_IP); ppacket->arphdr.arp_halen = ETH_ALEN; ppacket->arphdr.arp_prlen = 4; ppacket->arphdr.arp_opcode = htons(ARPOP_REQUEST); memset(ppacket->arphdr.ar_tha, 0x0,ETH_ALEN); /* IPDISCOVER */ /* Check the sunet mask (B class max) */ if( ntohl(netmask.sin_addr.s_addr) < 0xFFFF0000){ printf("Net too large (%s). Stop\n", inet_ntoa(netmask.sin_addr)); exit(0); } /* Netid */ unet = ntohl(ipaddr.sin_addr.s_addr) & ntohl(netmask.sin_addr.s_addr); /* Supposed number of hosts */ uhost = ~(ntohl(netmask.sin_addr.s_addr)); struct in_addr ipsrc; memset(&ipsrc, 0, sizeof(struct in_addr)); flag=1; ppacket_r = malloc(sizeof(struct packet)); int p=0; /* We are looking for all the possible connected host */ for(ipdst=1;ipdst<uhost;ipdst++){ tip = htonl(ipdst+unet); memcpy(ppacket->arphdr.ar_tip, &tip, 4); if(write(sd,ppacket,sizeof(struct packet)) < 0){ perror("Transmission error"); exit(1); } flag = 0; usleep(10000); while(flag>=0){ memset(ppacket_r, 0, sizeof(struct packet)); flag = read(sd, ppacket_r, sizeof(struct packet)); if(flag>0){memcpy(&ipsrc, ppacket_r->arphdr.ar_sip, sizeof(struct in_addr));} if(ntohs(ppacket_r->arphdr.arp_opcode) == 2){ if(p==0){printf("<IPDISCOVER>\n");} p++; printf("<H><I>%s</I><M>%02x:%02x:%02x:%02x:%02x:%02x</M></H>\n",inet_ntoa(ipsrc), *ppacket_r->arphdr.ar_sha,ppacket_r->arphdr.ar_sha[1],ppacket_r->arphdr.ar_sha[2], ppacket_r->arphdr.ar_sha[3],ppacket_r->arphdr.ar_sha[4],ppacket_r->arphdr.ar_sha[5]); } } } if(p) printf("</IPDISCOVER>\n"); /* That's all */ exit(0); }