I'm making an executable in Android. This will be used for sending ARP packets, but the sendto command is failing with EINVAL. The same piece of code is working on ARM, but failing on Cortex A9. Here is the code snippet:
int sendArp( const char *iface, const char *src_ip, const char * trgt_ip)
{
int status, frame_length, bytes;
arp_hdr arphdr;
uint8_t src_mac[6] ={0};
uint8_t dst_mac[6] ={0};
uint8_t ether_frame[ARP_LEN] = {0};
struct addrinfo hints, *res;
struct sockaddr_in *ipv4;
struct sockaddr_ll send_struct;
struct ifreq ifr;
int sd =-1;
int recValue = -1;
pthread_t thread;
if(iface == NULL || src_ip == NULL || trgt_ip == NULL)
return -1;
if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
ALOG ("socket() failed ");
goto out;
}
memset (&ifr, 0, sizeof (ifr));
snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", iface);
if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) {
ALOG ("ioctl() failed to get source MAC address ");
goto out;
}
// Copy source MAC address.
memcpy (src_mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t));
memset (&send_struct, 0, sizeof (send_struct));
if ((send_struct.sll_ifindex = if_nametoindex (iface)) == 0) {
ALOG ("if_nametoindex() failed to obtain iface index ");
goto out;
}
memset (dst_mac, 0xff, 6 * sizeof (uint8_t));
ALOG ("Iface '%s' index='%i', src=%s : dest=%s\n", iface, send_struct.sll_ifindex, src_ip, trgt_ip);
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = hints.ai_flags | AI_CANONNAME;
if ((status = inet_pton (AF_INET, src_ip, &arphdr.sender_ip)) != 1) {
fprintf (stderr, "inet_pton() failed for source IP address.\nError message: %s", strerror (status));
goto out;
}
if ((status = getaddrinfo (trgt_ip, NULL, &hints, &res)) != 0) {
fprintf (stderr, "getaddrinfo() failed - %s\n", strerror (status));
goto out;
}
ipv4 = (struct sockaddr_in *) res->ai_addr;
memcpy (&arphdr.target_ip, &ipv4->sin_addr, 4 * sizeof (uint8_t));
freeaddrinfo (res);
send_struct.sll_family = AF_PACKET;
send_struct.sll_protocol = htons(ETH_P_ARP);
send_struct.sll_hatype = htons(ARPHRD_ETHER);
send_struct.sll_pkttype = (PACKET_BROADCAST);
memcpy (send_struct.sll_addr, src_mac, 6 * sizeof (uint8_t));
send_struct.sll_halen = 6;
send_struct.sll_addr[6] = 0x00;
send_struct.sll_addr[7] = 0x00;
arphdr.htype = htons (1);
arphdr.ptype = htons (ETH_P_IP);
arphdr.hlen = 6;
arphdr.plen = 4;
arphdr.opcode = htons (ARPOP_REQUEST);
memcpy (&arphdr.sender_mac, src_mac, 6 * sizeof (uint8_t));
memset (&arphdr.target_mac, 0, 6 * sizeof (uint8_t));
frame_length = 6 + 6 + 2 + ARP_HDRLEN;
memcpy (ether_frame, dst_mac, 6 * sizeof (uint8_t));
memcpy (ether_frame + 6, src_mac, 6 * sizeof (uint8_t));
ether_frame[12] = ETH_P_ARP / 256;
ether_frame[13] = ETH_P_ARP % 256;
memcpy (ether_frame + ETH_HDRLEN, &arphdr, ARP_HDRLEN * sizeof (uint8_t));
// Send ethernet frame to socket.
if ((bytes = sendto (sd, ether_frame, frame_length, 0, (struct sockaddr *) &send_struct, sizeof (send_struct))) <= 0) {
ALOG ("sendto() failed: error=%s", strerror(errno));
goto out;
}
ALOG("ARP sent, bytes[%d]", bytes);
recValue = arpRecv(sd, (uint8_t*)arphdr.target_ip);
ALOG("main::thread_ret=%d", recValue);
out:
if(sd){
shutdown(sd,2);
close(sd);
}
return recValue;
}
int main(int argc, const char **argv) {
return sendArp("wlan0", "10.10.10.10", "20.20.20.20");
}
From the code snippet, I'm getting the error:
sendto() failed
The Kernel error I'm seeing is:
packet size is too short (42 <= 62)
I have tried modifying socket flags and played around the code a lot, but couldn't figure out the root cause. Any help is greatly appreciated.
Thanks in advance.