[問題] kernel 裡面寫 socket 的連線問題
小弟嘗試寫了一個在 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)
→
01/04 00:01, , 1F
01/04 00:01, 1F
LinuxDev 近期熱門文章
PTT數位生活區 即時熱門文章