i has some problem about sock_sendmsg and sock_recvmsg

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



i wrote loadable kernel module to use for add new system call about send and recv msg on the kernel dynamically

first ... i try to change some kernel code for support add system call dynamically by add EXPORT_SYMBOL(sys_call_table) in file ksyms.c

after that i recmpile my kernel and develop my kernel module for my system call
the code is below:
1. header for my kernel module
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>    /* For module_init and module_clea */
#include <linux/net.h>
#include <linux/socket.h>
#include <net/sock.h>
#include <linux/byteorder/generic.h>
#include <linux/string.h>
#include <asm/fcntl.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/inet.h>
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/compiler.h>
#include <linux/linkage.h>
#include <asm/unistd.h>
#include <asm/ioctls.h>

struct params{
  unsigned char remip[4];
};

2. code of my kernel module is :
#include "testsendrecv.h"

u32 create_address(u8 *ip){
 u32 addr = 0;
 int i;
 for(i=0;i<4;++i){
   addr += ip[i];
   if(i == 3){
     break;
   }
   addr <<= 8;
 }
 return addr;
}

asmlinkage int create_sock_local_addr(struct socket *sock, int port){
 int port_temp;
 int r = 0;
 struct socket *sock_temp = NULL;
 struct sockaddr_in saddr;

	if(unlikely(!access_ok(VERIFY_READ, port, sizeof(port)))){
		printk("access to port is not ok\n");
		return -EFAULT;
	}

 if(__get_user(port_temp, &port)){
		printk("can not copy port number\n");
		return -EFAULT;
	}

 r = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock_temp);
 if(r < 0){
		printk(KERN_ERR "Don't create socket : %d\n", r);
		return -1;
	}

 memset(&saddr, 0, sizeof(saddr));
 saddr.sin_family = AF_INET;
 saddr.sin_port = htons(port_temp);
 saddr.sin_addr.s_addr = INADDR_ANY;

r = sock_temp->ops->bind(sock_temp, (struct sockaddr *)&saddr, sizeof(saddr));

 if(r < 0){
		printk(KERN_ERR "Error on bind socket : %d\n", r);
		sock_release(sock_temp);
		return -1;
	}

 if(unlikely(!access_ok(VERIFY_WRITE, sock, sizeof(sock)))){
		printk("can not access socket for write\n");
		return -EFAULT;
	}
	if(copy_to_user(sock, sock_temp, sizeof(struct socket))){
		printk("can not copy socket to user\n");
		return -EFAULT;
	}

 kfree(sock_temp);
 return 0;
}

asmlinkage int connect_remoteaddr(struct socket *sock, struct params *pm, int port){
 struct socket *sock_temp;
 int port_temp;
 struct sockaddr_in daddr;
 int r;
 struct params pmk;

 sock_temp = kmalloc(sizeof(struct socket), GFP_KERNEL);

 if(unlikely(!access_ok(VERIFY_READ, sock, sizeof(sock)))){
   return -EFAULT;
 }
 if(unlikely(!access_ok(VERIFY_READ, pm, sizeof(pm)))){
   printk("access to param is not ok\n");
   return -EFAULT;
 }
	if(unlikely(!access_ok(VERIFY_READ, port, sizeof(port)))){
		printk("access to port is not ok\n");
		return -EFAULT;
	}

 if(copy_from_user(sock_temp, sock, sizeof(struct socket))){
   printk("can not copy socket\n");
   return -EFAULT;
 }

 if(copy_from_user(&pmk, pm, sizeof(struct params))){
   printk("can not copy params\n");
   return -EFAULT;
 }

 if(__get_user(port_temp, &port)){
		printk("can not copy port number\n");
		return -EFAULT;
	}

 daddr.sin_family = AF_INET;
 daddr.sin_port = htons(port_temp);
 daddr.sin_addr.s_addr = htonl(create_address(pmk.remip));

r = sock->ops->connect(sock, (struct sockaddr *)&daddr, sizeof(daddr), O_RDWR);

 if(r < 0){
		printk(KERN_ERR "socket connect error : %d\n", r);
		sock_release(sock_temp);
		return -1;
	}

 if(unlikely(!access_ok(VERIFY_WRITE, sock, sizeof(sock)))){
		printk("can not access socket for write\n");
		return -EFAULT;
	}
	if(copy_to_user(sock, sock_temp, sizeof(struct socket))){
		printk("can not copy socket to user\n");
		return -EFAULT;
	}

 kfree(sock_temp);
 return 0;
}

asmlinkage int test_sendmsg(struct socket *sock, const char *buf, int len){
 struct socket *sock_temp;
 char *buf_temp;
 int len_temp;

 sock_temp = kmalloc(sizeof(struct socket), GFP_KERNEL);
 buf_temp = kmalloc((sizeof(char) * strlen_user(buf)), GFP_KERNEL);

 if(unlikely(!access_ok(VERIFY_READ, sock, sizeof(sock)))){
   return -EFAULT;
 }
if(unlikely(!access_ok(VERIFY_READ, buf, sizeof(char) * strlen_user(buf)))){
   printk("can not access buf\n");
   return -EFAULT;
 }
 if(unlikely(!access_ok(VERIFY_READ, len, sizeof(len)))){
   printk("can not access len\n");
   return -EFAULT;
 }

 if(copy_from_user(sock_temp, sock, sizeof(struct socket))){
   printk("can not copy socket\n");
   return -EFAULT;
 }
 if(copy_from_user(buf_temp, buf, sizeof(char) * strlen_user(buf))){
   printk("can not copy buffer data\n");
   return -EFAULT;
 }
 if(__get_user(len_temp, &len)){
		printk("can not copy len of buffer\n");
		return -EFAULT;
	}

 struct msghdr msg;
 struct iovec iov;
 int len_send = 0;
 mm_segment_t oldmm;

 msg.msg_name = 0;
 msg.msg_namelen = 0;
 msg.msg_iov = &iov;
 msg.msg_iovlen = 1;
 msg.msg_control = NULL;
 msg.msg_controllen = 0;
 msg.msg_flags = MSG_DONTWAIT;

 oldmm = get_fs();
 set_fs(KERNEL_DS);

 msg.msg_iov->iov_len = len_temp;
 msg.msg_iov->iov_base = buf_temp;

 len_send = sock_sendmsg(sock_temp, &msg, len_temp);

 set_fs(oldmm);
 kfree(buf_temp);
 kfree(sock_temp);
 printk("send msg complete len = %d\n", len_send);
 return len_send;
}

int recvmsg_temp(struct socket *sock, char *str){
 struct msghdr msg;
 struct iovec iov;
 int len_recv;
 int max_size = 160;
 mm_segment_t oldmm;

 for(;;){
 msg.msg_name = 0;
 msg.msg_namelen = 0;
 msg.msg_iov = &iov;
 msg.msg_iovlen = 1;
 msg.msg_control = NULL;
 msg.msg_controllen = 0;
 msg.msg_flags = 0;

 msg.msg_iov->iov_base = str;
 msg.msg_iov->iov_len = max_size;

 oldmm = get_fs(); set_fs(KERNEL_DS);

 //recv_again:
 len_recv = sock_recvmsg(sock, &msg, max_size, 0);
 //if(len_recv == -EAGAIN || len_recv == -ERESTARTSYS){
   //goto recv_again;
 //}
 set_fs(oldmm);
 if(signal_pending(current)){
   //printk("got signal\n");
   //total_recv = -ERESTARTSYS;
   break;
 }
 //printk("recv msg complete len is %d\n", len_recv);
 //printk("str is %s\n", str);
 }
 return len_recv;
}

asmlinkage int test_recvmsg(struct socket *sock, char *str){
 struct socket *sock_temp;
 char *str_temp;
 int len;
 mm_segment_t oldmm;
 int total_recv;

 sock_temp = kmalloc(sizeof(struct socket), GFP_KERNEL);
 str_temp = kmalloc((sizeof(char) * strlen_user(str)), GFP_KERNEL);

 if(unlikely(!access_ok(VERIFY_READ, sock, sizeof(sock)))){
   return -EFAULT;
 }
 if(copy_from_user(sock_temp, sock, sizeof(struct socket))){
   printk("can not copy socket\n");
   return -EFAULT;
 }

 total_recv = 0;
 //for(;;){
 //oldmm = get_fs(); set_fs(KERNEL_DS);
 len = recvmsg_temp(sock_temp, str_temp);
   //wake_up();
 //printk("string is %s\n", str_temp);


/*if(unlikely(!access_ok(VERIFY_WRITE, str, sizeof(char) * strlen_user(str)))){
   printk("can not access str buffer\n");
   return -EFAULT;
 }
 if(copy_to_user(str, str_temp, sizeof(char) * strlen(str_temp))){
   printk("can not copy str buffer to user\n");
   return -EFAULT;
 }*/
 //set_fs(oldmm);
 /*if(signal_pending(current)){
   printk("got signal\n");
   total_recv = -ERESTARTSYS;
   break;
 } */
 printk("string is ...%s\n", str_temp);
 total_recv = len;
 kfree(sock_temp);
 kfree(str_temp);
 //}
 return total_recv;
}

asmlinkage int socket_destroy(struct socket *sock){
	struct socket *sock_temp;
	sock_temp = kmalloc(sizeof(struct socket), GFP_KERNEL);
	if(unlikely(!access_ok(VERIFY_READ, sock, sizeof(sock)))){
   		return -EFAULT;
 	}
 	if(copy_from_user(sock_temp, sock, sizeof(struct socket))){
   		printk("can not copy socket\n");
   		return -EFAULT;
 	}

	sock_release(sock_temp);
	kfree(sock_temp);
	return 0;
}

extern void *sys_call_table[];

asmlinkage long sys_ni_syscall(void){
 return -ENOSYS;
}

int init_module(){
 printk("starting up test send recv msg kernel module\n");
	sys_call_table[259] = create_sock_local_addr;
	sys_call_table[260] = connect_remoteaddr;
	sys_call_table[261] = test_sendmsg;
	sys_call_table[262] = test_recvmsg;
	sys_call_table[263] = socket_destroy;
 return 0;
}

void cleanup_module(void){
 printk("clean up test send recv msg kernel module\n");
 sys_call_table[259] = sys_ni_syscall;
	sys_call_table[260] = sys_ni_syscall;
	sys_call_table[261] = sys_ni_syscall;
	sys_call_table[262] = sys_ni_syscall;
	sys_call_table[263] = sys_ni_syscall;
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sasin Janpungtong");

3. my test program use for send data :
#include "testsendrecv_app.h"
#include <stdio.h>

int runcond = 1;
static char *help = "usage: rtpsend filename dest_ip4addr dest_port localport [--with-clockslide value] [--with-jitter]\n";
unsigned char ip_temp[4];
struct params pm;

void stophandler(int signum){
	runcond = 0;
}

void getip(char *s){
 unsigned char *str;
 unsigned char *ip;
 int i=0;
 //ip = (unsigned char *) calloc(4, sizeof(unsigned char));
 str = strtok(s, ".");
 //ip_temp[i] = atoi(str);
 //printf("ip is %d : %d\n", i, ip_temp[i]);
 pm.remip[i] = atoi(str);
 ++i;
 while(str = strtok(NULL, ".")){
   //ip_temp[i] = atoi(str);
   //printf("ip is %d : %d\n", i, ip_temp[i]);
   pm.remip[i] = atoi(str);
   ++i;
 }
}

int main(int argc, char *argv[]){
 struct socket *sock;
 FILE *infile;
 int err_test = 0;
 char buffer[160];
	int i;

 if(argc < 5){
		printf(help);
		return -1;
	}

 getip(argv[2]);
 //pm.addr_temp = ip_temp;
printf("%d.%d.%d.%d\n",pm.remip[0], pm.remip[1], pm.remip[2], pm.remip[3]);

 sock = malloc(sizeof(struct socket));

 infile = fopen(argv[1], "r");

	if(infile == NULL){
		printf("Can not open file\n");
		return -1;
	}
 err_test = create_sock_local_addr(sock, atoi(argv[4]));
 printf("status of create socket for local addr %i:%i\n", err_test, errno);

 err_test = connect_remoteaddr(sock, &pm, atoi(argv[3]));
 printf("status of connect to remote address %i:%i\n", err_test, errno);

 signal(SIGINT, stophandler);
	while(((i=fread(buffer, 1, 160, infile)) > 0) && (runcond)){
   err_test = test_sendmsg(sock, buffer, i);
   printf("status of sendmsg is %i:%i\n", err_test, errno);
 }
 fclose(infile);
 //sock_release(sock);
 //socket_destroy(sock);
 free(sock);
 return 0;
}

4. my test programe for receive data  from sender (receiver)
#include "testsendrecv_app.h"
#include <stdio.h>

int cond = 1;
void stop_handler(int signum){
	cond = 0;
}

static char *help = "usage: rtprecv filename loc_port [--format format] [--soundcard]\n";

#define MULAW 0
#define ALAW 1

int main(int argc, char *argv[]){
 struct socket *sock;
 char buffer[160];
 FILE *outfile;
 int i;
 int local_port;
 int format = 0;
 int err_test = 0;

	if(argc < 3){
		printf(help);
		return -1;
	}

 local_port = atoi(argv[2]);
	if(local_port <= 0){
		printf(help);
		return -1;
	}

 outfile = fopen(argv[1], "wb");
	if(outfile == NULL){
		printf("Cannot open file for writing\n");
		return -1;
	}

 sock = malloc(sizeof(struct socket));

 err_test = create_sock_local_addr(sock, local_port);
 printf("status of create and set socket is %i:%i\n", err_test, errno);

 while(cond){
   err_test = test_recvmsg(sock, buffer);
   printf("status of receive message is %i:%i\n", err_test, errno);
   if(err_test > 0){
     //fwrite(buffer, 1, err_test, outfile);
   }
 }
 fclose(outfile);
 //sock_release(sock);
 //socket_destroy(sock);
 free(sock);
 return 0;
}

5. header file for all test app is :
#include "testsendrecv.h"
#include <errno.h>

#define __NR_create_sock_local_addr 259
#define __NR_connect_remoteaddr 260
#define __NR_test_sendmsg 261
#define __NR_test_recvmsg 262
#define __NR_socket_destroy 263

static inline _syscall2(int, create_sock_local_addr, struct socket *, sock, int, port) static inline _syscall3(int, connect_remoteaddr, struct socket *, sock, struct params *, pm, int, port) static inline _syscall3(int, test_sendmsg, struct socket *, sock, const char *, buf, int, len) static inline _syscall2(int, test_recvmsg, struct socket *, sock, char *, str)
static inline _syscall1(int, socket_destroy, struct socket *, sock)

and i make my module and load it on kernel
and make my sender and receiver test program to test my system call
but the error was occured....

the sender show it can send all data packet complete (i'm not sure it really send) but receiver look like block after set its socket complete .... look like it wait data coming from sender .... after sender show it send all data packet complete and exit by itself ... the receiver stiil block and not show any message to me. after i wait the result of receiver for a long time.... i decide to press ctrl-c to stop receiver loop and after i press ctrl-c the receiver show it work on sock_recvmsg complete but it receive only first data packet form sender and never return to userspace .... please help me or suggest me about how to fix my problem

thanks for your time
Sasin

_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE! http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/


--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux