【发布时间】:2019-12-04 11:11:03
【问题描述】:
我的代码向12.12.12.12 发送了一个原始IP 数据包,但由于EMSGSIZE 而失败。我认为它根据以太网 MTU 限制了我的数据包,但它应该发送数据包
我尝试向127.0.0.1 发送数据包,效果很好,但是当我向非本地 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 解决代码问题:
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
【问题讨论】:
-
assert中的所有内容都在发布版本中被删除。整个assert和表达式有效地变成了空格。你应该做类似ssize_t result = send(fd, ...); assert(result == sizeof(buffer));的事情。在发布版本中,send将继续存在。另见Is assert(false) ignored in release mode? -
如果你执行
ssize_t result = send(fd, ...);那么你可以检查result。根据send(2)man page:“成功时,这些调用返回发送的字符数。出错时,返回-1,并正确设置errno。”您应该可以检查@987654336 @ 对于类似EMSGSIZE的东西,在手册页中有记录:“如果消息太长而无法原子地通过底层协议,则返回错误 EMSGSIZE,并且不会传输消息。”我> -
我使用
gcc test.c编译代码,而NDEBUG没有定义,所以断言运行良好(正如我们在strace消息中看到的那样)。 -
使用 gcc 在 linux 上编译时,没有编译错误。执行链接步骤时,没有错误。但是,当尝试运行发布的代码时,第一次调用
assert()会导致代码中止。强烈建议删除/替换对assert()的调用,例如:if( (fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror( "socket failed" ); } -
使用对
perror()的建议调用会导致:socket failed: Operation not permitted。这提示socket()的参数组合无效
标签: c linux sockets networking raw-sockets