/* ############################################################################### ##OCSInventory Version NG Beta ##Copyleft Pascal DANEK 2006 ##Web : http://ocsinventory.sourceforge.net ## ##This code is open source and may be copied and modified as long as the source ##code is always made freely available. ##Please refer to the General Public Licence http://www.gnu.org/ or Licence.txt ################################################################################ */ #include "ipdiscover.h" /* We get IP address, netmask, index number and mac address of the adapter */ void get_iface_infos( 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"); exit(1); } /* Initialize */ memset( &ifr, 0x0, sizeof(struct ifreq)); /* We put into the ifreq struct 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"); exit(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"); exit(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"); exit(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"); exit(1); } *index = ifr.ifr_ifindex; /*******************/ close(tmpsock); } void data_init( struct sockaddr_in *ipaddr, struct sockaddr_in *netmask, packet **ppacket, struct sockaddr_ll *sll, int index ){ memset(ipaddr, 0x00, sizeof(struct sockaddr_in)); memset(netmask, 0x00, sizeof(struct sockaddr_in)); /* Arp structure */ *ppacket = malloc( sizeof( packet ) ); /* Tie to adapter */ sll->sll_family = AF_PACKET; sll->sll_protocol = htons(ETH_P_ARP); /* 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 ); } void print_xml(struct in_addr *ipsrc, packet *ppacket_r, struct hostent* name){ printf("%s%02x:%02x:%02x:%02x:%02x:%02x%s\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], name?name->h_name:"-"); } void create_socket(int *sd, struct sockaddr_ll *sll, int index){ /* Socket creation */ *sd = socket( PF_PACKET, SOCK_RAW, htons( ETH_P_ARP ) ); /* Put the iface index in sockaddr_ll structure to bind */ sll->sll_ifindex = index; 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); } } void validate_iface( struct sockaddr_in *ipaddr, struct sockaddr_in *netmask, packet *ppacket ){ char error_str[100]; if( ntohl(netmask->sin_addr.s_addr) < 0xFFFF0000){ snprintf(error_str, 100, "Invalid netmask -> too large (%s). Stop\n", inet_ntoa(netmask->sin_addr)); perror( error_str ); exit(1); } } void scan_init( unsigned long *unet, unsigned long *uhost, struct sockaddr_in *ipaddr, struct sockaddr_in *netmask, struct in_addr *ipsrc, packet **ppacket_r ){ /* 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) ); memset(ipsrc, 0, sizeof(struct in_addr)); *ppacket_r = malloc( sizeof( packet ) ); } int main(int argc, char ** argv){ /* Declarations */ /* full packet (tx and rx) */ packet *ppacket, *ppacket_r; /* Socket descriptor, nic index */ int sd = 0; int flag = 0; int index = 0; /* ip data */ unsigned long unet,uhost,ipdst,tip; /* The name of the interface is given in parameter to the binary */ char * iface; /* detected device's FQDN */ struct hostent* name; /* ip level sockaddr */ struct sockaddr_in ipaddr, netmask; /* Lowlevel sockaddr */ struct sockaddr_ll sll = {0x0}; /* source ip to put in packet */ struct in_addr ipsrc; int request_latency = REQUEST_LATENCY_DEFAULT; int p=0; /* Take at least one argument */ if(argc<2){ printf("IPDISCOVER binary ver. %d \nUsage : ipdiscover [iface name] [latency in ms]\n", VERSION); exit(0); }else{ iface = argv[1]; if( argc==3 ) request_latency = atoi( argv[2] ); } /* Initialize data */ data_init( &ipaddr, &netmask, &ppacket, &sll, index ); /* Reading nic parameters */ get_iface_infos( ppacket, &index, iface, &ipaddr, &netmask ); /* Check iface settings */ validate_iface( &ipaddr, &netmask, ppacket ); /* Creating socket */ create_socket( &sd, &sll, index ); /* Initialize packet target ip, potential hosts number... */ scan_init( &unet, &uhost, &ipaddr, &netmask, &ipsrc, &ppacket_r ); /* We are looking for all the possible connected host */ for(ipdst=1;ipdstarphdr.ar_tip, &tip, 4 ); /* Sending the packet */ if( write( sd, ppacket, sizeof(packet) ) < 0 ){ perror("Transmission error"); exit(1); } flag = 0; usleep( request_latency * 1000 ); while( flag>=0 ){ memset( ppacket_r, 0, sizeof( packet ) ); flag = read( sd, ppacket_r, sizeof( packet ) ); if( flag>0 ) memcpy(&ipsrc, ppacket_r->arphdr.ar_sip, sizeof(struct in_addr)); if(ntohs(ppacket_r->arphdr.arp_opcode) == 2){ char * c; if(p==0) printf("\n"); p++; name = gethostbyaddr(&ipsrc, sizeof(struct in_addr), AF_INET); if(name){ while((c=strchr(name->h_name,'<')) || (c=strchr(name->h_name,'>'))){ strncpy(c,"x",sizeof(c)); } } usleep( NAME_RES_LATENCY ); print_xml( &ipsrc, ppacket_r, name ); } } } if(p) printf("\n"); /* That's all */ exit(0); }