Sophie

Sophie

distrib > Mandriva > 2009.0 > x86_64 > by-pkgid > 4600e36867221e7b25edae93f646cf9f > files > 10

ocsng-1.0-0.3mdv2009.0.src.rpm

#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);
}