Skip to content

Instantly share code, notes, and snippets.

@alekswn
Created April 15, 2022 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alekswn/94e68b2feb5ddaa214efefdf7e1e534b to your computer and use it in GitHub Desktop.
Save alekswn/94e68b2feb5ddaa214efefdf7e1e534b to your computer and use it in GitHub Desktop.
#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