Created
April 15, 2022 11:09
-
-
Save alekswn/94e68b2feb5ddaa214efefdf7e1e534b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <arpa/inet.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <linux/errqueue.h> | |
#define max_mtu_size_bytes (9001) | |
#define header_length_bytes (28) | |
#define max_payload_size_bytes (max_mtu_size_bytes - header_length_bytes) | |
int main(int argc, char* argv[]) | |
{ | |
assert(argc == 2); | |
int s = socket(AF_INET, SOCK_DGRAM, 0); | |
assert(s > 0); | |
const int pmtu_option = IP_PMTUDISC_DO; | |
assert(setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu_option, sizeof pmtu_option) == 0); | |
const int one = 1; | |
assert(setsockopt(s, IPPROTO_IP, IP_RECVERR, &one, sizeof one) == 0); | |
struct in_addr ip_addr; | |
assert(inet_pton(AF_INET, argv[1], (void*)&ip_addr) == 1); | |
const unsigned short echo_port = 7; | |
struct sockaddr_in addr = { | |
.sin_family = AF_INET, | |
.sin_port = htons(echo_port), | |
.sin_addr = ip_addr, | |
}; | |
assert(connect(s, (const struct sockaddr *)&addr, sizeof addr) == 0); | |
const char* payload[max_payload_size_bytes] = {0}; | |
size_t payload_size_bytes = max_payload_size_bytes; | |
for(int i = 0; i < 10; i++) | |
{ | |
ssize_t rc = send(s, payload, payload_size_bytes, 0); | |
if (rc == payload_size_bytes) { | |
return payload_size_bytes; | |
} else { | |
#if 0 | |
char cbuf[512]; | |
struct msghdr msg = { | |
.msg_control = cbuf, | |
.msg_controllen = sizeof cbuf, | |
0, | |
}; | |
while(recvmsg(s, &msg, MSG_ERRQUEUE) >= 0) { | |
for (struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { | |
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) { | |
struct sock_extended_err *e = (struct sock_extended_err *)CMSG_DATA(cmsg); | |
if (e->ee_errno == EMSGSIZE) { | |
payload_size_bytes = e->ee_info - header_length_bytes; | |
} | |
} | |
} | |
} | |
#else | |
socklen_t option_len = sizeof payload_size_bytes; | |
assert(getsockopt(s, IPPROTO_IP, IP_MTU, &payload_size_bytes, &option_len) == 0); | |
payload_size_bytes -= header_length_bytes; | |
#endif | |
} | |
sleep(1); | |
} | |
return -1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment