|
在网上到处搜不到如何在内核中创建tcp连接,后来自己参考内核源代码中的linux/net/sunrpc/xprtsock.c写了一个可用的测试程序,与大家分享,代码有可以改进的地方还请高手都指教呀^_^
- /* code is referred to linux/net/sunrpc/xprtsock.c */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/types.h>
- #include <linux/errno.h>
- #include <linux/socket.h>
- #include <linux/in.h>
- #include <linux/inet.h>
- #include <linux/net.h>
- #include <linux/tcp.h>
- #include <net/sock.h>
- #include <net/checksum.h>
- #include <net/tcp.h>
- static char *peer_addr = "192.168.0.100";
- static unsigned short peer_port = 21;
- static char *msg = "USER anonymous\r\n";
- static struct socket *sock = NULL;
- static struct work_struct work;
- static int recvd = 0;
- static int tcp_sendto(struct socket *sock, void * buff, size_t len,
- unsigned flags, struct sockaddr *addr, int addr_len) {
- struct kvec vec;
- struct msghdr msg;
- vec.iov_base=buff;
- vec.iov_len=len;
- memset(&msg, 0x00, sizeof(msg));
- msg.msg_name=addr;
- msg.msg_namelen=addr_len;
- msg.msg_flags = flags | MSG_DONTWAIT | MSG_NOSIGNAL;
- return kernel_sendmsg(sock, &msg, &vec, 1, len);
- }
- static void kernsock_send_msg(void) {
- int n;
- struct sockaddr_in addr;
-
- memset(&addr, 0x00, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(peer_port);
- addr.sin_addr.s_addr = in_aton(peer_addr);
- n = tcp_sendto(sock, msg, strlen(msg), 0, (struct sockaddr *)&addr, sizeof(addr));
- printk("send %d bytes\n", n);
- }
- static int kernsock_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len) {
- struct iphdr *ip;
- struct tcphdr *tcp;
- char *tcp_data;
- int payload,doff;
-
- printk("kernsock_tcp_data_recv started:offset:%d,len:%d\n",offset,len);
-
- if (!skb) return 0;
-
- if (!(skb->nh.iph)) return 0;
-
- ip = skb->nh.iph;
- if(ip->protocol == IPPROTO_TCP) {
- tcp = (struct tcphdr *)(skb->h.th);
- printk("src=%u.%u.%u.%u:%u,dest=%u.%u.%u.%u:%u\n",NIPQUAD(ip->saddr),ntohs(tcp->source),NIPQUAD(ip->daddr),ntohs(tcp->dest));
-
- payload = ntohs(ip->tot_len) - (ip->ihl << 2);
- doff = tcp->doff << 2;
- tcp_data = (char *)((int)tcp + doff);
-
- if(tcp->psh) {
- printk("peer sent psh:%.*s\n",payload - doff,tcp_data);
- recvd = 1;
- }
- }
- printk("kernsock_tcp_data_recv done\n");
- return len;
- }
- static void kernsock_tcp_data_ready(struct sock *sk, int bytes) {
- read_descriptor_t rd_desc;
- read_lock(&sk->sk_callback_lock);
- printk("kernsock_tcp_data_ready\n");
- rd_desc.arg.data = NULL;
- rd_desc.count = 65536;
- tcp_read_sock(sk, &rd_desc, kernsock_tcp_data_recv);
- read_unlock(&sk->sk_callback_lock);
- }
- static void kernsock_tcp_state_change(struct sock *sk) {
- read_lock(&sk->sk_callback_lock);
- switch (sk->sk_state) {
- case TCP_ESTABLISHED:
- printk("TCP_ESTABLISHED\n");
- break;
- case TCP_SYN_SENT:
- printk("TCP_SYN_SENT\n");
- break;
- case TCP_SYN_RECV:
- printk("TCP_SYN_RECV\n");
- break;
- case TCP_CLOSE_WAIT:
- printk("TCP_CLOSE_WAIT\n");
- break;
- }
- read_unlock(&sk->sk_callback_lock);
- }
- static void kernsock_tcp_write_space(struct sock *sk) {
- read_lock(&sk->sk_callback_lock);
- printk("kernsock_tcp_write_space\n");
- read_unlock(&sk->sk_callback_lock);
- }
- static void tcp_connect_worker(struct sockaddr_in *addr) {
- int err, status = -EIO;
- struct sock *sk;
-
- /* start from scratch */
- if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
- printk("can't create TCP transport socket (%d).\n", -err);
- return;
- }
- sk = sock->sk;
- write_lock_bh(&sk->sk_callback_lock);
- sk->sk_data_ready = kernsock_tcp_data_ready;
- sk->sk_state_change = kernsock_tcp_state_change;
- sk->sk_write_space = kernsock_tcp_write_space;
- sk->sk_allocation = GFP_ATOMIC;
- /* socket options */
- sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
- sock_reset_flag(sk, SOCK_LINGER);
- tcp_sk(sk)->linger2 = 0;
- tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
- write_unlock_bh(&sk->sk_callback_lock);
- status = sock->ops->connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_in), O_NONBLOCK);
- if (status < 0) {
- switch (status) {
- case -EINPROGRESS:
- printk("EINPROGRESS\n");
- break;
- case -EALREADY:
- printk("EALREADY\n");
- break;
- case -ECONNREFUSED:
- printk("ECONNREFUSED\n");
- break;
- case -ECONNRESET:
- printk("ECONNRESET\n");
- break;
- }
- }
- }
- static int __init socket_init(void){
- struct sockaddr_in addr;
-
- memset(&addr, 0x00, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(peer_port);
- addr.sin_addr.s_addr = in_aton(peer_addr);
- tcp_connect_worker(&addr);
-
- msleep(1000);
- if(recvd) {
- INIT_WORK(&work, kernsock_send_msg, NULL);
- schedule_work(&work);
- } else {
- printk("time out\n");
- }
- return 0;
- }
- static void __exit socket_exit(void) {
- sock_release(sock);
- }
- module_init(socket_init);
- module_exit(socket_exit);
复制代码 |
|