代碼來自busybox,函數詢問TEST_IP的mac位址。read_interface函數通過ioctl來擷取接口interface相關資訊,arpping用于發送arp資料包。 也可以使用s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); 則位址則變成了struct sockaddr_ll addr; 在arpping中調用以下函數,則也可以發送 # 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 {
uint8_t h_dest[ 6] ;
uint8_t h_source[ 6] ;
uint16_t h_proto;
uint16_t htype;
uint16_t ptype;
uint8_t hlen;
uint8_t plen;
uint16_t operation;
uint8_t sHaddr[ 6] ;
uint8_t sInaddr[ 4] ;
uint8_t tHaddr[ 6] ;
uint8_t tInaddr[ 4] ;
uint8_t pad[ 18] ;
} 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;
struct sockaddr addr;
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;
}
memset ( & arp, 0, sizeof ( arp) ) ;
memset ( arp. h_dest, 0xff, 6) ;
memcpy ( arp. h_source, from_mac, 6) ;
arp. h_proto = htons ( ETH_P_ARP) ;
arp. htype = htons ( ARPHRD_ETHER) ;
arp. ptype = htons ( ETH_P_IP) ;
arp. hlen = 6;
arp. plen = 4;
arp. operation = htons ( ARPOP_REQUEST) ;
memcpy ( arp. sHaddr, from_mac, 6) ;
memcpy ( arp. sInaddr, & from_ip, sizeof ( from_ip) ) ;
memcpy ( arp. tInaddr, & test_ip, sizeof ( test_ip) ) ;
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;
} | |