sendto system call returning with EINVAL - android

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.

Related

How to read all the text in edittext using cpp?

I am trying to set the baud-rate of "/dev/ttyS4" and return the Text(EditText) using C code with the help of JNI in android studio
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#define DEBUG 1
#if DEBUG
#include <android/log.h>
# define D(x...) __android_log_print(ANDROID_LOG_INFO,"hello-jni",x)
#else
# define D(...) do {} while (0)
#endif
char* str;
char buffer[512];
extern "C" JNIEXPORT jstring JNICALL
Java_com_android_uart_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */, jstring text)
{
{
asprintf(&str, "Hi\n");
strlcpy(buffer, str, sizeof buffer);
free(str);
int ttyFD = 0;
struct termios tty;
const char *stringInC = env->GetStringUTFChars(text, NULL);
auto SampleCmd = stringInC;
int i_WriteBytes = 0;
memset (&tty, 0, sizeof tty);
ttyFD = open("/dev/ttyS4", O_RDWR| O_NONBLOCK | O_NDELAY );
if(ttyFD < 0)
{
asprintf(&str, "Error in opening /dev/ttyS4\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
else
{
asprintf(&str, "ttyS4 port opened successfully\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
if (tcgetattr ( ttyFD, &tty ) != 0 )
{
asprintf(&str, "Error from tcgetattr\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
cfsetspeed(&tty, B0);
tty.c_cflag &= ~PARENB; /* parity */
tty.c_cflag &= ~CSTOPB; /* stop bits */
//tty.c_cflag &= ~CSIZE; /* */
tty.c_cflag |= CS8; /* data bits */
tty.c_cflag &= ~CRTSCTS; /* no hardware flow control */
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* no s/w flow ctrl */
tty.c_lflag = 0; /* non canonical */
tty.c_oflag = 0; /* no remapping, no delays */
tty.c_cc[VMIN] = 0; /* read doesn't block */
tty.c_cc[VTIME] = 0; /* read timeout */
tty.c_cflag |=
CREAD | CLOCAL; /* turn on READ & ignore ctrl lines */
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* */
//tty.c_oflag &= ~OPOST; /* */
tcflush(ttyFD, TCIFLUSH);
if (tcsetattr(ttyFD, TCSANOW, &tty) != 0) {
asprintf(&str, "Error from tcsetattr\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
i_WriteBytes = write(ttyFD, SampleCmd, sizeof(SampleCmd) - 1);
asprintf(&str, "written bytes = %d\n", i_WriteBytes);
strlcat(buffer, str, sizeof buffer);
free(str);
if (i_WriteBytes < 0) {
asprintf(&str, "failed to write value on port\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
sleep(1);
char read_buf[1024];
memset(&read_buf, '\0', sizeof(read_buf));
int num_bytes = read(ttyFD, &read_buf, sizeof(read_buf));
if (num_bytes < 0) {
asprintf(&str, "Error reading: %s", strerror(errno));
strlcat(buffer, str, sizeof buffer);
free(str);
}
asprintf(&str, "Read bytes = %i \n Received message: %s", num_bytes, read_buf);
strlcat(buffer, str, sizeof buffer);
free(str);
close(ttyFD);
return env->NewStringUTF(buffer);
}
My problem is that WriteBytes and Read bytes only take 7 bytes of the edittext"Text" and it only display 7 characters of it.
What i want is to display the entire "Text" from the EditText.
This is the result iam getting:
**Input:**
EditText(baud Rate)=0
EditText(message) =this is a test app
**Output:**
TextView(Details)
hi
ttyS4 port opened successfully
written bytes = 7
Read bytes =7
Received message:this is
The line
i_WriteBytes = write(ttyFD, SampleCmd, sizeof(SampleCmd) - 1);
is wrong.
Variable SampleCmd, defined as
const char *stringInC = env->GetStringUTFChars(text, NULL);
auto SampleCmd = stringInC;
is of type int in C or type const char * in C++. (Note that auto is an old keyword in C which defines a storage class is the default for variables inside functions and forbidden at file scope. As you don't specify a type, it defaults to int.)
The value sizeof(SampleCmd) is not related to the length of the string pointed to by stringInC. It is the size of a variable of type int (in C, or type char* in C++). Apparently this size is 8 on your platform, so you will always write 7 bytes.
You could use
i_WriteBytes = write(ttyFD, SampleCmd, strlen(SampleCmd));
or use fdopen on ttyFD and use output functions from stdio.h.

How to get mac address in Android native code

I can get mac address with this C code:
struct ifreq s;
char buffer[12 + 1];
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
int i, j;
memset(buffer, 0 , sizeof(buffer));
strcpy(s.ifr_name, "wlan0");
if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) {
memcpy(mac, s.ifr_addr.sa_data, 6);
return 1;
}
I want to get mac address in Android. but this code does not give MAC address. if (0 == ioctl(fd, SIOCGIFHWADDR, &s) is always false.
I found a code in https://groups.google.com/d/msg/android-ndk/6Y-0Eid3mGw/6bFvtap8xJIJ
But this code gives error:
ioctl(SIOCGIFHWADDR) error
and it gives wrong mac address like 00:00:00:7C::00:01
How can I get mac address in Android native code ?
This code works good on Nexus 5:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <linux/if.h>
#include <linux/in.h>
int get_mac_addr(char *mac_addr)
{
int sockfd;
struct ifreq ifr;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) >= 0) {
//strncpy(ifr.ifr_name, "eth0", IFNAMESIZE);
strncpy(ifr.ifr_name, "wlan0", IFNAMSIZ);
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl(sockfd, SIOCGIFHWADDR, (char*) &ifr) == 0) {
sprintf(mac_addr, "%02X:%02X:%02X:%02X:%02X:%02X",
(unsigned char) ifr.ifr_ifru.ifru_hwaddr.sa_data[0], (unsigned char) ifr.ifr_ifru.ifru_hwaddr.sa_data[1],
(unsigned char) ifr.ifr_ifru.ifru_hwaddr.sa_data[2], (unsigned char) ifr.ifr_ifru.ifru_hwaddr.sa_data[3],
(unsigned char) ifr.ifr_ifru.ifru_hwaddr.sa_data[4], (unsigned char) ifr.ifr_ifru.ifru_hwaddr.sa_data[5]);
return 0;
}
}
/* error */
return -1;
}
int main(int argc, char *argv[], char *envp[])
{
char mac_addr[80] = {0};
printf( "MAC = %d, %s\n", get_mac_addr(mac_addr), mac_addr );
return 0;
}
You must connect to a WiFi network, then try to get mac address.

Android Linux kernel communicate with user space

I'm following this article to implement android linux kernel communicate with user space.
I use insmod kernel to insert my kernel to Android avd goldfish kernel, then I use cat /proc/kmsg to observe the kernel message, but I find the program doesn't execute as intended. Here is my code:
void hello_nl_recv_msg(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
char *msg = "Hello from kernel";
int res;
printk(KERN_INFO "Entering: %sn", __FUNCTION__);
msg_size = strlen(msg);
nlh = (struct nlmsghdr *)skb->data;
printk(KERN_INFO "Netlink received msg payload:%sn", (char *)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; //pid of sending process
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out)
{
printk(KERN_ERR "Failed to allocate new skbn");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; //not in mcast group
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res < 0)
printk(KERN_INFO "Error while sending bak to usern");
}
int init_module()
{
printk("Entering: %sn", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
printk("%s",nl_sk);
// nl_sk = netlink_kernel_create(NETLINK_USER, input);
//if (!nl_sk)
//{
// printk(KERN_ALERT "Error creating socket.n");
// return -10;
//}
return 0;
}
I find when the program exec
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
The kernel returns -1 or other integer, and it can't execute the function "hello_ne_recv_msg". I use android avd, the kernel is goldfish 2.6. Please help me, thanks.
Here is my code (tested on sony z2 kernel).
Note: your code may still fail if seandroid (selinux) is enforced.
Beware of code copy pasting. Check it!
Don't ignore compilation warnings.
Kernel module:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <net/sock.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
static struct sock* nl_sk;
#define NETLINK_USER 31
void hello_nl_recv_msg(struct sk_buff* skb)
{
struct nlmsghdr* nlh;
int pid;
struct sk_buff* skb_out;
int msg_size;
char* msg = "Hello from kernel";
int res;
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
msg_size = strlen(msg);
nlh = (struct nlmsghdr*)skb->data;
printk(KERN_INFO "Netlink received msg payload:%s\n", (char*)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; //pid of sending process
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out) {
printk(KERN_ERR "Failed to allocate new skbn\n");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; //not in mcast group
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res < 0) {
printk(KERN_INFO "Error while sending back to user\n");
}
}
int __init init_netlink_test(void)
{
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
if (!nl_sk) {
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
void __exit exit_netlink_test(void)
{
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
module_init(init_netlink_test);
module_exit(exit_netlink_test);
userspace test app:
#include <sys/socket.h>
#include <linux/netlink.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#define NETLINK_USER 31
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr* nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
int main()
{
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if (sock_fd < 0) {
return -1;
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
/* interested in group 1<<0 */
bind(sock_fd, (struct sockaddr*)&src_addr,
sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
nlh = (struct nlmsghdr*)malloc(
NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "Hello");
iov.iov_base = (void*)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void*)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Sending message to kernel\n");
sendmsg(sock_fd, &msg, 0);
printf("Waiting for message from kernel\n");
/* Read message from kernel */
recvmsg(sock_fd, &msg, 0);
printf(" Received message payload: %s\n",
NLMSG_DATA(nlh));
close(sock_fd);
}

Linux Kernel Module unix domain sockets

I'm trying to share data between kernel and user space. The ultimate goal is to port it to Android, so I'm using unix domain sockets. (I don't know if this is the best option).
I have a kernel module acting as socket client and a c program acting as socket server. And vice-versa, a kernel module acting as socket server and a c program acting as socket client.
Programs are very simple. Servers just send a string to clients and they print it.
I run server_user.c and then I try to insert client_module.ko using insmod. I get the following error:
Kernel panic - not syncing: stack - protector: Kernel stack is corrupted in: ffffffffa0005157
drm-kms-helper: panic occurred, switching back to text console
What's wrong?
Module Server
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/un.h>
#include <net/sock.h>
#define SOCK_PATH "/tmp/usocket"
#define LISTEN 10
struct socket *sock = NULL;
struct socket *newsock = NULL;
static int __init server_module_init( void ) {
int retval;
char* string = "hello_world";
struct sockaddr_un addr;
struct msghdr msg;
struct iovec iov;
mm_segment_t oldfs;
// create
retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &sock);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, SOCK_PATH);
// bind
retval = sock->ops->bind(sock,(struct sockaddr *)&addr, sizeof(addr));
// listen
retval = sock->ops->listen(sock, LISTEN);
//accept
retval = sock->ops->accept(sock, newsock, 0);
//sendmsg
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iov->iov_base = string;
msg.msg_iov->iov_len = strlen(string)+1;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
oldfs = get_fs();
set_fs(KERNEL_DS);
retval = sock_sendmsg(newsock, &msg, strlen(string)+1);
set_fs(oldfs);
return 0;
}
static void __exit server_module_exit( void ) {
printk(KERN_INFO "Exit usocket.");
}
module_init( server_module_init );
module_exit( server_module_exit );
MODULE_LICENSE("GPL");
Module Client
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/un.h>
#include <linux/net.h>
#include <net/sock.h>
#include <linux/socket.h>
#define SOCK_PATH "/tmp/usocket"
#define MAX 100
struct socket *sock = NULL;
static int __init client_module_init( void ) {
int retval;
char str[MAX];
struct sockaddr_un addr;
struct msghdr msg;
struct iovec iov;
mm_segment_t oldfs;
printk(KERN_INFO "Start client module.\n");
// create
retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &sock);
// connect
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, SOCK_PATH);
retval = sock->ops->connect(sock, (struct sockaddr *)&addr, sizeof(addr), 0);
// recvmsg
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_iov->iov_base= str;
msg.msg_iov->iov_len= strlen(str)+1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
oldfs = get_fs();
set_fs(KERNEL_DS);
retval = sock_recvmsg(sock, &msg, strlen(str)+1, 0);
set_fs(oldfs);
// print str
printk(KERN_INFO "client module: %s.\n",str);
// release socket
sock_release(sock);
return 0;
}
static void __exit client_module_exit( void )
{
printk(KERN_INFO "Exit client module.\n");
}
module_init( client_module_init );
module_exit( client_module_exit );
MODULE_LICENSE("GPL");
User Server
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "/tmp/usocket"
int send_msg_to_client(int socketfd, char* data) {
struct msghdr msg;
struct iovec iov;
int s;
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov.iov_base = data;
iov.iov_len = strlen(data)+1;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
s = sendmsg(socketfd, &msg, 0);
printf("after send - iov_base: %s, length: %d\n", (char *) msg.msg_iov->iov_base, (int) strlen(msg.msg_iov->iov_base));
if(s < 0){
perror("sendmsg");
return 0;
}
return s;
}
int main(int argc, char* argv[])
{
if (argc != 2) {
printf("Usage: $ %s <string>\n",argv[0]);
return 0;
}
int s, s2, len, slen;
socklen_t t;
struct sockaddr_un local, remote;
char* data = argv[1];
printf("print data: %s\n",data);
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
memset(&local, 0, sizeof(local));
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
perror("bind");
exit(1);
}
if (listen(s, 5) == -1) {
perror("listen");
exit(1);
}
printf("Waiting for a connection...\n");
t = sizeof(remote);
if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
slen = send_msg_to_client(s2, data);
if(slen < 0)
perror("send");
close(s2);
return 0;
}
User Client
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "/tmp/usocket"
#define MAX 100
int recv_msg_from_server(int socketfd, char data[MAX]) {
struct msghdr msg;
struct iovec iov;
int s;
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov.iov_base = data;
iov.iov_len = MAX;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
s = recvmsg(socketfd, &msg, 0);
printf("after recv - iov_base: %s, length: %d\n", (char *) msg.msg_iov->iov_base, (int) strlen(msg.msg_iov->iov_base));
if(s < 0){
perror("recvmsg");
}
return s;
}
int main(void)
{
int s, len, slen;
struct sockaddr_un remote;
char data[MAX];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
printf("Trying to connect...\n");
memset(&remote, 0, sizeof(remote));
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SOCK_PATH);
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
perror("connect");
exit(1);
}
printf("Connected.\n");
slen = recv_msg_from_server(s, data);
if (slen < 0) {
perror("recvmsg");
}
//printf("print data received > %s\n", data);
close(s);
return 0;
}
I have just faced a similar issue (with UNIX datagrams though), and I believe there is a bug in the unix_mkname() function which is part of the kernel: this function makes sure the sun_path field of the given sockaddr_un structure is always null terminated by adding a NUL character after the end of that field. Since this is the last field, it will corrupt the area (stack or heap) where that structure has been allocated.
The best solution is to patch that function in the kernel source code, so that it only sets to NUL the last character of the sun_path field. Meanwhile, you can make your code work by decreasing by 1 byte the size you give for the sockaddr_un structure:
Module Server
// bind
retval = sock->ops->bind(sock,(struct sockaddr *)&addr, sizeof(addr) - 1);
Module Client
retval = sock->ops->connect(sock, (struct sockaddr *)&addr, sizeof(addr) - 1, 0);
As I am using UNIX datagrams, I cannot really tell if it fixes the issue for bind() and connect(), but a least, it fixes it for sock_sendmsg().
#shu-suzuki: thanks for the leads.
After 5 years I came back here...
I again stucked with this problem and found that I did the same thing 5 years ago.
The cause is as in Tey's answer and the solution is OK (sutbract 1 from the length) but here's another solution.
What you can do is to use struct sockaddr_storage as struct sockaddr_un. As far as I read the kernel code this is what they use to handle bind system call from user space.
sockeaddr_storage is larger than sockaddr_un so kernel code can write beyond the sizeof(sockaddr_un).
The code should be like
struct sockaddr_storage addrStorage;
struct sockaddr_un* addr;
memset(&addrStorage, 0, sizeof(addrStorage));
addr = (struct sockaddr_un*)&addrStorage;
addr->sun_family = AF_UNIX;
strcpy(addr->sun_path, "/my/sock/name");
kernel_bind(listenSock, (struct sockaddr*)addr, sizeof(*addr));
This looks working for me.

Android libusb I/O error

I'm trying to use libusb on Android 2.3 to read a stream of data from a USB device connected to an Android development device using libusb and the Android NDK. The development device supports USB host mode even though my version of Android does not. Through the serial terminal connection I have given 777 permissions to the entire tree under /dev/bus/usb.
When I try to run the following code I get an I/O error (-1 returned) from the line that calls libusb_bulk_transfer.
struct usb_bus *p;
struct usb_device *q;
struct libusb_device *current_device;
libusb_device_handle *current_handle;
libusb_device **deviceList;
libusb_device *dev;
libusb_context *ctx = NULL;
int result;
unsigned char firmware[31]= {...}
unsigned char reset[2]={1,0};
unsigned char buffer[2*BUFF_SIZE];
int er[10];
unsigned char endpoint=0x08;
unsigned int i,j,k,tlen,startTime,endTime;
unsigned int val1,val2,offset;
unsigned int packetCnt;
libusb_init(&ctx);
libusb_set_debug(ctx,3);
cnt = libusb_get_device_list(NULL, &deviceList);
if (cnt < 0)
printf("ERROR: %i", (int) cnt);
while ((dev = deviceList[i++]) != NULL) {
char outputString[255];
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
fprintf(stderr, "failed to get device descriptor");
return (*env)->NewStringUTF(env, str);
}
if (desc.idVendor == 0x4b4 && desc.idProduct == 0x8613) {
current_device = dev;
sprintf(outputString, "%04x:%04x (bus %d, device %d)\n",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev));
__android_log_write(ANDROID_LOG_INFO, "usb_device", outputString);
}
}
if (current_device == NULL) {
__android_log_write(ANDROID_LOG_INFO, "usb_device", "Could not find a CY7C68013\n\n");
return (*env)->NewStringUTF(env, str);
}
result = libusb_open(current_device, &current_handle);
result = libusb_open(current_device, &current_handle);
if (result != 0) {
__android_log_write(ANDROID_LOG_INFO, "usb_device", "Unable to open device\n\n");
return (*env)->NewStringUTF(env, str);
}
char outputString[255];
libusb_free_device_list(deviceList, 1);
libusb_control_transfer(current_handle, 0x40, 0xa0, 0xE600, 0, reset, 1, 1000);
int actual;
for(i=0;i<31;i+=16) //LOAD FIRMWARE
{
tlen = 60-i;
if(tlen > 16)
tlen = 16;
result = libusb_control_transfer(current_handle, 0x40, 0xa0, i, 0, firmware+i, tlen, 1000);
log_result(result);
}
result = libusb_control_transfer(current_handle, 0x40, 0xa0, 0xE600, 0, reset+1, 1, 1000);
log_result(result);
result = libusb_claim_interface(current_handle, 0);
if (result < 0) {
__android_log_write(ANDROID_LOG_INFO, "usb_device", "Cannot Claim Interface\n\n");
return (*env)->NewStringUTF(env, str);
}
result = libusb_bulk_transfer(current_handle, endpoint, buffer, BUFF_SIZE, &actual, 11000);
log_result(result);
libusb_release_interface(current_handle, 0);
libusb_close(current_handle);
libusb_exit(ctx);
Everything succeeds up until this point, including performing the 32 byte control transfer of the device firmware.
I've given myself full permission to the USB /dev files and I've checked using libusb to ensure that there isn't any kernel driver attached to this interface.
What am I doing wrong?

Categories

Resources