linux 内核模块发送udp,Linux 内核模块实现udp发送字符串

/*

* Kernel Send Udp packet Module

*

* This program is free software; you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation; either version 2 of the License, or

* (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program; if not, write to the Free Software

* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*

* Copyright(C) Tony 2007-2013

*

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Tony ");

char *ifname = "eth0";

module_param(ifname, charp, 0644);

MODULE_PARM_DESC(ifname, "Send packets from which net device");

char *buffer = "Tony test from kernel!\n";

module_param(buffer, charp, 0644);

MODULE_PARM_DESC(buffer, "Packet content");

__u32 dstip = 0xc0a80056;

module_param(dstip, uint, 0644);

__s16 dstport = 8000;

module_param(dstport, short, 0644);

long timeout = 1;

module_param(timeout, long, 0644);

MODULE_PARM_DESC(timeout, "Interval between send packets, default 1(unit second)");

static struct task_struct *kthreadtask = NULL;

static int bind_to_device(struct socket *sock, char *ifname)

{

struct net *net;

struct net_device *dev;

__be32 addr;

struct sockaddr_in sin;

int err;

net = sock_net(sock->sk);

dev = __dev_get_by_name(net, ifname);

if (!dev) {

printk(KERN_ALERT "No such device named %s\n", ifname);

return -ENODEV;

}

addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);

sin.sin_family = AF_INET;

sin.sin_addr.s_addr = addr;

sin.sin_port = 0;

err = sock->ops->bind(sock, (struct sockaddr*)&sin, sizeof(sin));

if (err < 0) {

printk(KERN_ALERT "sock bind err, err=%d\n", err);

return err;

}

return 0;

}

static int connect_to_addr(struct socket *sock)

{

struct sockaddr_in daddr;

int err;

daddr.sin_family = AF_INET;

daddr.sin_addr.s_addr = cpu_to_be32(dstip);

daddr.sin_port = cpu_to_be16(dstport);

err = sock->ops->connect(sock, (struct sockaddr*)&daddr,

sizeof(struct sockaddr), 0);

if (err < 0) {

printk(KERN_ALERT "sock connect err, err=%d\n", err);

return err;

}

return 0;

}

struct threadinfo{

struct socket *sock;

char *buffer;

};

static int sendthread(void *data)

{

struct kvec iov;

struct threadinfo *tinfo = data;

struct msghdr msg = {.msg_flags = MSG_DONTWAIT|MSG_NOSIGNAL};

int len;

while (!kthread_should_stop()) {

iov.iov_base = (void *)tinfo->buffer;

iov.iov_len = strlen(tinfo->buffer);

len = kernel_sendmsg(tinfo->sock, &msg, &iov, 1, strlen(tinfo->buffer));

if (len != strlen(buffer)) {

printk(KERN_ALERT "kernel_sendmsg err, len=%d, buffer=%d\n",

len, (int)strlen(buffer));

if (len == -ECONNREFUSED) {

printk(KERN_ALERT "Receive Port Unreachable packet!\n");

}

break;

}

schedule_timeout_interruptible(timeout * HZ);

}

kthreadtask = NULL;

sk_release_kernel(tinfo->sock->sk);

kfree(tinfo);

return 0;

}

static int __init udp_send_init(void)

{

int err = 0;

struct socket *sock;

struct threadinfo *tinfo;

err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);

if (err < 0) {

printk(KERN_ALERT "UDP create sock err, err=%d\n", err);

goto create_error;

}

sock->sk->sk_reuse = 1;

err = bind_to_device(sock, ifname);

if (err < 0) {

printk(KERN_ALERT "Bind to %s err, err=%d\n", ifname, err);

goto bind_error;

}

err = connect_to_addr(sock);

if (err < 0) {

printk(KERN_ALERT "sock connect err, err=%d\n", err);

goto connect_error;

}

tinfo = kmalloc(sizeof(struct threadinfo), GFP_KERNEL);

if (!tinfo) {

printk(KERN_ALERT "kmalloc threadinfo err\n");

goto kmalloc_error;

}

tinfo->sock = sock;

tinfo->buffer = buffer;

kthreadtask = kthread_run(sendthread, tinfo, "Tony-sendmsg");

if (IS_ERR(kthreadtask)) {

printk(KERN_ALERT "create sendmsg thread err, err=%ld\n",

PTR_ERR(kthreadtask));

goto thread_error;

}

return 0;

thread_error:

kfree(tinfo);

kmalloc_error:

bind_error:

connect_error:

sk_release_kernel(sock->sk);

kthreadtask = NULL;

create_error:

return -1;

}

static void __exit udp_send_exit(void)

{

if (kthreadtask) {

kthread_stop(kthreadtask);

}

printk(KERN_ALERT "UDP send quit\n");

return;

}

module_init(udp_send_init);

module_exit(udp_send_exit);

下面是测试效果:

在192.168.0.86机器上开启netcat从8000端口接收数据包:

86756741fe61

image

在192.168.0.3机器上加载该内核模块:

86756741fe61

image

这个时候,在192.168.0.86机器上就可以每隔1秒钟接收到一个数据包:

86756741fe61

image

在192.168.0.3的机器上可以看到发送数据包的内核线程“Tony-sendmsg":

86756741fe61

image

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值