在 Linux 内核中发送 UDP 数据包 [英] Sending UDP packet in Linux Kernel

查看:18
本文介绍了在 Linux 内核中发送 UDP 数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于一个项目,我试图从 Linux 内核空间发送 UDP 数据包.我目前正在将我的代码硬编码"到内核中(我认为这不是最好/最简洁的方式),但我正在尝试进行一个简单的测试(发送测试").应该提到的是,我是内核黑客的新手 - 我对许多原则和技术并不了解!

For a project, I'm trying to send UDP packets from Linux kernel-space. I'm currently 'hard-coding' my code into the kernel (which I appreciate isn't the best/neatest way) but I'm trying to get a simple test to work (sending "TEST"). It should be mentioned I'm a newbie to kernel hacking - I'm not that clued up on many principles and techniques!

每次我的代码运行时,系统都会挂起,我必须重新启动 - 没有鼠标/键盘响应,滚动和大写锁定键指示灯一起闪烁 - 我不确定这是什么意思,但我假设这是一个内核恐慌?

Every time my code gets run the system hangs and I have to reboot - no mouse/keyboard response and the scroll and caps lock key lights flash together - I'm not sure what this means, but I'm assuming it's a kernel panic?

此测试代码不需要 repeat_send 代码,但是当它工作时,我想发送可能需要多次发送"的大消息 - 我不确定这是否会导致我的问题?

The repeat_send code is unnecessary for this test code, yet when it's working I want to send large messages that may require multiple 'send's - I'm not sure that if could be a cause of my issues?

注意这段代码被插入到linux-source/net/core/源的neighbor.c中,因此使用NEIGH_PRINTK1,它只是一个宏包装器围绕printk.

N.B. This code is being inserted into neighbour.c of linux-source/net/core/ origin, hence the use of NEIGH_PRINTK1, it's just a macro wrapper round printk.

我真的在这里撞墙了,我看不到任何明显的东西,谁能指出我正确的方向(或发现那个明显的明显错误!)?

I'm really banging my head against a brick wall here, I can't spot anything obvious, can anyone point me in the right direction (or spot that blindingly obvious error!)?

这是我目前所拥有的:

void mymethod()
{
    struct socket sock;
    struct sockaddr_in addr_in;
    int ret_val;
    unsigned short port = htons(2048);
    unsigned int host = in_aton("192.168.1.254");
    unsigned int length = 5;
    char *buf = "TEST";
    struct msghdr msg;
    struct iovec iov;
    int len = 0, written = 0, left = length;
    mm_segment_t oldmm;

    NEIGH_PRINTK1("forwarding sk_buff at: %p.
", skb);

    if ((ret_val = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
        NEIGH_PRINTK1("Error during creation of socket; terminating. code: %d
", ret_val);
        return;
    }

    memset(&addr_in, 0, sizeof(struct sockaddr_in));
    addr_in.sin_family=AF_INET;
    addr_in.sin_port = port;
    addr_in.sin_addr.s_addr = host;

    if((ret_val = sock.ops->bind(&sock, (struct sockaddr *)&addr_in, sizeof(struct sockaddr_in))) < 0) {
    NEIGH_PRINTK1("Error trying to bind socket. code: %d
", ret_val);
    goto close;
    }

    memset(&msg, 0, sizeof(struct msghdr));
    msg.msg_flags = 0;
    msg.msg_name = &addr_in;
    msg.msg_namelen = sizeof(struct sockaddr_in);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;

repeat_send:
    msg.msg_iov->iov_len = left;
    msg.msg_iov->iov_base = (char *)buf + written;

    oldmm = get_fs(); 
    set_fs(KERNEL_DS);
    len = sock_sendmsg(&sock, &msg, left);
    set_fs(oldmm);

    if (len == -ERESTARTSYS)
        goto repeat_send;
    if (len > 0) {
        written += len;
        left -= len;
        if (left)
            goto repeat_send;
    }

close:
    sock_release(&sock);
}

非常感谢任何帮助,谢谢!

Any help would be hugely appreciated, thanks!

推荐答案

您可能会发现使用 netpoll API 用于 UDP.查看 netconsole 的示例,了解如何使用它被使用了.您使用的 API 更适用于用户空间(您永远不必使用段描述符来发送网络数据!)

You may find it easier to use the netpoll API for UDP. Take a look at netconsole for an example of how it's used. The APIs you're using are more intended for userspace (you should never have to play with segment descriptors to send network data!)

这篇关于在 Linux 内核中发送 UDP 数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆