+++ http://developerweb.net/viewtopic.php?id=3704
this is the structure defining the protocol:
struct arphdr_t
{
unsigned short ar_hrd; // 2
unsigned short ar_pro; // 2
unsigned char ar_hln; // 1
unsigned char ar_pln; // 1
unsigned short ar_op; // 2
unsigned char ar_sha[6]; // 6
unsigned char ar_sip[4]; // 4
unsigned char ar_tha[6]; // 6
unsigned char ar_tip[4]; // 4
};
2 functions I use to send & recv messages over UDP :
int
common_send_message(int sd, unsigned char* msg, int msg_len, unsigned char mac[], int interface, int pkttype)
{
fd_set writefs;
struct timeval tv;
struct msghdr msgs;
struct iovec iov;
struct sockaddr_ll socknfo;
int len, fdv;
memset(&msgs, '\0', sizeof(struct msghdr));
msgs.msg_name = &socknfo;
msgs.msg_namelen = sizeof(struct sockaddr_ll);
msgs.msg_iovlen = 1;
msgs.msg_iov = &iov;
iov.iov_len = msg_len;
iov.iov_base = msg;
socknfo.sll_family = AF_PACKET;
socknfo.sll_protocol = htons(ETH_P_RARP);
socknfo.sll_ifindex = interface;
socknfo.sll_hatype = 0;
socknfo.sll_pkttype = pkttype;
socknfo.sll_halen = 6;
socknfo.sll_addr[0] = mac[0] ;
socknfo.sll_addr[1] = mac[1] ;
socknfo.sll_addr[2] = mac[2] ;
socknfo.sll_addr[3] = mac[3] ;
socknfo.sll_addr[4] = mac[4] ;
socknfo.sll_addr[5] = mac[5] ;
FD_ZERO( &writefs ) ;
FD_SET( sd, &writefs ) ;
tv.tv_sec = 30 ; // 30 seconds
tv.tv_usec = 0 ;
fdv = select( sd+1, NULL, &writefs, NULL, &tv ) ;
if ( fdv == 0 || !FD_ISSET( sd, &writefs ) )
{
printf( "Send timed out [30 seconds]\n" ) ;
return -1;
}
return (int)sendmsg(sd, &msgs, 0);
}
int
common_recv_message(int sd, unsigned char* data, int maxlen, unsigned char mac[])
{
fd_set readfs;
struct timeval tv;
struct msghdr msgs;
struct iovec iov;
struct sockaddr_ll socknfo;
int len, fdv;
memset(&msgs, '\0', sizeof(struct msghdr));
msgs.msg_name = &socknfo;
msgs.msg_namelen = sizeof(struct sockaddr_ll);
msgs.msg_iovlen = 1;
msgs.msg_iov = &iov;
iov.iov_len = maxlen;
iov.iov_base = data;
tv.tv_sec = 30; // 30 seconds
tv.tv_usec = 0;
FD_ZERO(&readfs);
FD_SET(sd, &readfs);
fdv = select(sd+1, &readfs, NULL, NULL, &tv);
if(fdv == 0 || !FD_ISSET(sd, &readfs))
{
printf("Read timed out [30 seconds]\n");
return -1;
}
len = recvmsg(sd, &msgs, 0);
memcpy(mac, socknfo.sll_addr, 6);
return len;
}
to find out the interface index you must use :
int common_find_interface(const char* name)
{
struct ifreq ifr;
int iindex = 1;
int sock = socket(PF_PACKET, SOCK_RAW, 0);
ifr.ifr_ifindex = iindex;
while(ioctl(sock, SIOCGIFNAME, &ifr) == 0)
{
if(strcmp(ifr.ifr_name, name) == 0)
{
close(sock);
return iindex;
}
ifr.ifr_ifindex = ++iindex;
}
close(sock);
return -1;
}
You don't need to use raw sockets. It is easier to use SOCK_DGRAM because you must not implement ethernet protocol