尝试在原始IP数据包上发送数据时的EMSGSIZE [英] EMSGSIZE when trying to send data on raw IP packet

查看:135
本文介绍了尝试在原始IP数据包上发送数据时的EMSGSIZE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码将原始IP数据包发送到 12.12.12.12 ,但由于 EMSGSIZE 而失败.我认为它根据以太网MTU限制了我的数据包,但它应该发送的数据包< = 65,535字节(IPv4 MTU).

My code sends a raw IP packet to 12.12.12.12 and fails because of EMSGSIZE. I think that it limits my packet according to Ethernet MTU, but it should send packets <= 65,535 bytes (IPv4 MTU).

我尝试将数据包发送到 127.0.0.1 ,并且效果很好,但是当我将数据包发送到非本地IP时出现错误.

I've tried to send a packet to 127.0.0.1 and this worked well, but the error occurs when I send a packet to a non-local IP.

#include <assert.h>
#include <string.h>

#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void) {
    int fd;
    assert((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1);

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(1818);
    assert(inet_aton("12.12.12.12", &addr.sin_addr) != -1);
    assert(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != -1);

    char buffer[2000];
    memset(buffer, '\0', sizeof(buffer));
    assert(send(fd, buffer, sizeof(buffer), 0) == sizeof(buffer));

    assert(close(fd) != -1);
}

我希望代码能够正常工作,因为我发送的数据包小于IP MTU.使用 strace 对代码进行故障排除:

I expect that the code will work without any errors because I send a packet that is less than IP MTU. Troubleshoot the code with strace:

socket(AF_INET, SOCK_RAW, IPPROTO_RAW)  = 3
connect(3, {sa_family=AF_INET, sin_port=htons(1818), sin_addr=inet_addr("12.12.12.12")}, 16) = 0
sendto(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 2000, 0, NULL, 0) = -1 EMSGSIZE (Message too long)
a.out: compile.c:22: main: Assertion `send(fd, buffer, sizeof(buffer), 0) == sizeof(buffer)' failed.
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=8814, si_uid=0} ---
+++ killed by SIGABRT (core dumped) +++
Aborted

推荐答案

我认为它根据以太网MTU限制了我的数据包,但它应该发送的数据包< = 65,535字节(IPv4 MTU).

I think that it limits my packet according to Ethernet MTU, but it should send packets <= 65,535 bytes (IPv4 MTU).

由于默认情况下PMTU处于打开状态,因此它将仅发送适合MTU的数据包.您的包裹没有.来自 raw(7):

Since PMTU is on by default it will only send packets fitting in the MTU. Your packet doesn't. From raw(7):

默认情况下,原始套接字执行路径MTU (最大传输单位)发现.这意味着内核将跟踪MTU到特定目标IP地址,并在原始数据包时返回EMSGSIZE写入次数超过了.发生这种情况时,应用程序应减少数据包大小.
也可以使用关闭路径MTU发现IP_MTU_DISCOVER套接字选项或/proc/sys/net/ipv4/ip_no_pmtu_disc文件,有关详细信息,请参见ip(7).什么时候关闭后,原始套接字将对超出以下限制的传出数据包进行分段接口MTU.但是,不建议将其禁用性能和可靠性的原因.

By default, raw sockets do path MTU (Maximum Transmission Unit) discovery. This means the kernel will keep track of the MTU to a specific target IP address and return EMSGSIZE when a raw packet write exceeds it. When this happens, the application should decrease the packet size.
Path MTU discovery can be also turned off using the IP_MTU_DISCOVER socket option or the /proc/sys/net/ipv4/ip_no_pmtu_disc file, see ip(7) for details. When turned off, raw sockets will fragment outgoing packets that exceed the interface MTU. However, disabling it is not recommended for performance and reliability reasons.

这篇关于尝试在原始IP数据包上发送数据时的EMSGSIZE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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