作者ciphero (奶油焗蛋饺...:))
看板LinuxDev
标题[问题] kernel 里面写 socket 的连线问题
时间Mon Jan 3 00:24:32 2011
小弟尝试写了一个在 kernel space 中执行的 socket 程式
但是在执行时却无法顺利连线
目前推测可能是出在 connect 时出现问题
但 de 了很久的 bug 还是抓不到虫 @@~
首先简单叙述一下这支程式的用途:
一、client 端:
1. 一次单纯传送一个字元到远端主机
2. 此段程式设计於 kernel space,从一开机便会一直执行
(例如只要触发了某一事件,就会传送资料出去)
二、server 端:
1. 接收由 client 端所传过来的资料 (只接收,不会再回传回去 client)
2. 此段程式以 module 的方式写成,需要时再 insmod 进来就可以使用
下面是程式码:
// client 端主机的程式码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/socket.h>
#include <linux/slab.h>
#include <linux/in.h>
#include <linux/net.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <net/sock.h>
void send_data(char data) {
struct socket *sockt;
struct sockaddr_in *server;
struct iovec *iov;
struct msghdr *sock_msg;
int error,suc;
char *buff;
mm_segment_t old_mm;
int size;
printk("DEBUG: start\n");
server=(struct sockaddr_in*) kmalloc(sizeof(struct sockaddr_in),GFP_KERNEL);
iov = (struct iovec*)kmalloc(sizeof(struct iovec),GFP_KERNEL);
sock_msg = (struct msghdr*)kmalloc(sizeof(struct msghdr),GFP_KERNEL);
buff = (char*) kmalloc(((sizeof(char))*200), GFP_KERNEL);
// 建立一 socket
error = sock_create(AF_INET, SOCK_STREAM, 0, &sockt);
if(error<0) {
// 若 sock_create 不成功,则退出
printk(KERN_ALERT "socket failed %d\n", error);
return 0;
}
printk(KERN_ALERT "client sock %d\n", error);
memset(server,0,sizeof(struct sockaddr_in));
server->sin_family = AF_INET;
server->sin_addr.s_addr = 0x0100A8C0;
// 连线目的IP为 192.168.0.1
server->sin_port = htons(4321);
// 连线目的port为 4321
// 问题推测是出在这里,无法 connect 至目的主机
error=sockt->ops->connect(sockt,(struct sockaddr*)server,sizeof(server),0);
if (error<0) return 0;
// 若connect失败,则退出
printk(KERN_ALERT "connect: %d\n", error);
old_mm = get_fs();
set_fs(KERNEL_DS);
memset(iov,0,sizeof(struct iovec));
memset(sock_msg,0,sizeof(struct msghdr));
buff[0] = data;
// 设定欲传送的资料到 buff
iov[0].iov_base = (void*)buff;
size = 200;
iov[0].iov_len = size;
sock_msg->msg_name = NULL;
sock_msg->msg_namelen = 0;
sock_msg->msg_iov = iov;
sock_msg->msg_iovlen = 1;
sock_msg->msg_control = NULL;
sock_msg->msg_controllen = 0;
sock_msg->msg_flags = 0;
error = sock_sendmsg(sockt, sock_msg, size);
//传送资料至目的主机
printk(KERN_ALERT "send msg in client success:%d\n", error);
set_fs(old_mm);
sock_release(sockt);
}
// server 端主机的程式码:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
int init_module() {
struct socket *sock, *client;
struct sockaddr_in *server,*cl_addr;
struct iovec *iov;
struct msghdr *sock_msg;
char *buff;
mm_segment_t oldms, oldmm;
int size;
int error,suc;
printk("Insert mysyscall module\n");
// 建立一 socket
error=sock_create(AF_INET, SOCK_STREAM, 0, &sock);
if(error < 0) {
printk(KERN_ALERT "\nCan`t create a socket");
return 0;
}
iov = (struct iovec*) kmalloc(sizeof(struct iovec),GFP_KERNEL);
sock_msg = (struct msghdr*) kmalloc(sizeof(struct msghdr),GFP_KERNEL);
server = (struct sockaddr_in *)kmalloc(sizeof(struct sockaddr_in),
GFP_KERNEL);
client = (struct socket*)sock_create_lite(AF_INET, SOCK_STREAM, 0, &client);
cl_addr = (struct sockaddr_in *) kmalloc(sizeof(struct sockaddr_in),
GFP_KERNEL);
buff = (char *)kmalloc((sizeof(char)*200),GFP_KERNEL);
memset(server, 0, sizeof(struct sockaddr_in));
server->sin_family = AF_INET;
server->sin_port = htons(4321);
// 由 port 4321 接收资料
server->sin_addr.s_addr = INADDR_ANY;
// bind
error = sock->ops->bind(sock,(struct sockaddr*) server,
sizeof(struct sockaddr_in));
if(error<0) printk(KERN_ALERT "bind failed\n");
// listen
error= sock->ops->listen(sock,0);
if(error<0) printk(KERN_ALERT "listen failed\n");
// accept
error = sock->ops->accept(sock,client,0);
if(error<0) printk(KERN_ALERT "accept failed\n");
oldmm = get_fs();
set_fs(KERNEL_DS);
client->ops = sock->ops;
memset(iov, 0, sizeof(struct iovec));
memset(sock_msg, 0, sizeof(struct msghdr));
memset(buff, 0, 1000);
while(1) {
iov[0].iov_base=(void *)buff;
size=1000;
iov[0].iov_len=size;
sock_msg->msg_name=cl_addr;
sock_msg->msg_namelen=sizeof(struct sockaddr_in);
sock_msg->msg_iov=iov;
sock_msg->msg_iovlen=1;
sock_msg->msg_control=NULL;
sock_msg->msg_controllen=0;
sock_msg->msg_flags=0;
oldms = get_fs();
set_fs(KERNEL_DS);
suc=sock_recvmsg(client, sock_msg, size, 0);
// 接收资料
set_fs(oldmm);
if(suc<0) return 0;
}
sock_release(sock);
return 1;
}
void cleanup_module() {
printk("Remove mysyscall module\n");
}
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 59.112.83.45
※ 编辑: ciphero 来自: 59.112.83.45 (01/03 00:26)
1F:→ lngod:sin_addr.s_addr should use network order... inet_addr() 01/04 00:01