问题
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).
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);
}
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
回答1:
I think that it limits my packet according to Ethernet MTU, but it should send packets <= 65,535 bytes (IPv4 MTU).
Since PMTU is on by default it will only send packets fitting in the MTU. Your packet doesn't. From raw(7):
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.
来源:https://stackoverflow.com/questions/57214403/emsgsize-when-trying-to-send-data-on-raw-ip-packet