# include < unistd. h> # include < errno . h> # include < netdb. h> # include < signal . h> # include < sys/ socket . h> # include < sys/ poll. h> # include < sys/ ioctl. h> # include < netinet/ if_ether. h> # include < net/ if_arp. h> # include < netinet/ udp. h> # include < netinet/ ip. h> # include < stdio. h> # include < stdarg. h> # include < net/ if . h>
enum { ARP_MSG_SIZE = 0x2a } ;
char * strncpy_IFNAMSIZ( char * dst, const char * src) { # ifndef IFNAMSIZ enum { IFNAMSIZ = 16 } ; # endif return strncpy ( dst, src, IFNAMSIZ) ; }
struct arpMsg { /* Ethernet header */ uint8_t h_dest[ 6] ; /* 00 destination ether addr */ uint8_t h_source[ 6] ; /* 06 source ether addr */ uint16_t h_proto; /* 0c packet type ID field */
/* ARP packet */ uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */ uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */ uint8_t hlen; /* 12 hardware address length (must be 6) */ uint8_t plen; /* 13 protocol address length (must be 4) */ uint16_t operation; /* 14 ARP opcode */ uint8_t sHaddr[ 6] ; /* 16 sender's hardware address */ uint8_t sInaddr[ 4] ; /* 1c sender's IP address */ uint8_t tHaddr[ 6] ; /* 20 target's hardware address */ uint8_t tInaddr[ 4] ; /* 26 target's IP address */ uint8_t pad[ 18] ; /* 2a pad for min. ethernet payload (60 bytes) */ } PACKED; const int const_int_1 = 1; int setsockopt_broadcast( int fd) { return setsockopt ( fd, SOL_SOCKET, SO_BROADCAST, & const_int_1, sizeof ( const_int_1) ) ; }
char * safe_strncpy( char * dst, const char * src, size_t size) { if ( ! size) return dst; dst[ - - size] = '/0' ; return strncpy ( dst, src, size) ; }
int arpping( uint32_t test_ip, uint32_t from_ip, uint8_t * from_mac, const char * interface) { int timeout_ms; int s; int rv = 1; /* "no reply received" yet */ struct sockaddr addr; /* for interface name */ struct arpMsg arp;
s = socket ( PF_PACKET , SOCK_PACKET , htons ( ETH_P_ARP) ) ; if ( s = = - 1) { perror ( "raw_socket" ) ; return - 1; }
if ( setsockopt_broadcast( s) = = - 1) { perror ( "cannot enable bcast on raw socket" ) ; goto ret; }
/* send arp request */ memset ( & arp, 0, sizeof ( arp) ) ; memset ( arp. h_dest, 0xff, 6) ; /* MAC DA */ memcpy ( arp. h_source, from_mac, 6) ; /* MAC SA */ arp. h_proto = htons ( ETH_P_ARP) ; /* protocol type (Ethernet) */ arp. htype = htons ( ARPHRD_ETHER) ; /* hardware type */ arp. ptype = htons ( ETH_P_IP) ; /* protocol type (ARP message) */ arp. hlen = 6; /* hardware address length */ arp. plen = 4; /* protocol address length */ arp. operation = htons ( ARPOP_REQUEST) ; /* ARP op code */ memcpy ( arp. sHaddr, from_mac, 6) ; /* source hardware address */ memcpy ( arp. sInaddr, & from_ip, sizeof ( from_ip) ) ; /* source IP address */ /* tHaddr is zero-fiiled */ /* target hardware address */ memcpy ( arp. tInaddr, & test_ip, sizeof ( test_ip) ) ; /* target IP address */
memset ( & addr, 0, sizeof ( addr) ) ; safe_strncpy( addr. sa_data, interface, sizeof ( addr. sa_data) ) ; if ( sendto ( s, & arp, sizeof ( arp) , 0, & addr, sizeof ( addr) ) < 0) { // TODO: error message? caller didn't expect us to fail, // just returning 1 "no reply received" misleads it. } ret: close ( s) ; return rv; }
int read_interface( const char * interface, int * ifindex, uint32_t * addr, uint8_t * arp) { int fd; struct ifreq ifr; struct sockaddr_in * our_ip;
memset ( & ifr, 0, sizeof ( ifr) ) ; fd = socket ( AF_INET , SOCK_RAW , IPPROTO_RAW ) ;
ifr. ifr_addr. sa_family = AF_INET ; strncpy_IFNAMSIZ( ifr. ifr_name, interface) ; if ( addr) { if ( ioctl( fd, SIOCGIFADDR , & ifr) ! = 0) { perror ( "ioctl" ) ; close ( fd) ; return - 1; } our_ip = ( struct sockaddr_in * ) & ifr. ifr_addr; * addr = our_ip- > sin_addr. s_addr; printf ( "ip of %s = %s /n" , interface, inet_ntoa( our_ip- > sin_addr) ) ; }
if ( ifindex) { if ( ioctl( fd, SIOCGIFINDEX , & ifr) ! = 0) { close ( fd) ; return - 1; } printf ( "adapter index %d" , ifr. ifr_ifindex) ; * ifindex = ifr. ifr_ifindex; }
if ( arp) { if ( ioctl( fd, SIOCGIFHWADDR , & ifr) ! = 0) { close ( fd) ; return - 1; } memcpy ( arp, ifr. ifr_hwaddr. sa_data, 6) ; printf ( "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x/n" , arp[ 0] , arp[ 1] , arp[ 2] , arp[ 3] , arp[ 4] , arp[ 5] ) ; } close ( fd) ; return 0; }
int main( void ) { uint32_t TEST_IP = inet_addr( "191.192.193.194" ) ; char interface[ ] = "eth0" ; uint32_t ip; uint8_t mac[ 6] ; read_interface( interface, NULL , & ip, mac) ; while ( 1) { arpping( TEST_IP, ip, mac, interface) ; sleep ( 1) ; } return 0;
} |