/* * 6.12.y backports commit: * - a18dfa9925b9ef6107ea3aa5814ca3c704d34a8a "ipv6: save dontfrag in cork" * but does not backport: * - 54580ccdd8a9c6821fd6f72171d435480867e4c3 "ipv6: remove leftover ip6 cookie initializer" * - 096208592b09c2f5fc0c1a174694efa41c04209d "ipv6: replace ipcm6_init calls with ipcm6_init_sk" * * This causes a regression when sending IPv6 UDP packets by preventing * fragmentation and instead returning EMSGSIZE. This program demonstrates the * issue. sendmsg returns correctly (8192) on a working kernel, and returns -1 * (EMSGSIZE) when the regression is present. * * The regression is not present in the mainline kernel. * * Applying the missing commits to 6.12.y fixes the regression. */ #include #include #include #define LARGER_THAN_MTU 8192 int main(void) { /* address doesn't matter, use an IPv6 multicast address for simplicity */ struct in6_addr addr = { .s6_addr[0] = 0xff, /* multicast */ .s6_addr[1] = 0x12, /* set flags (T, link-local) */ }; struct sockaddr_in6 sa = { .sin6_family = AF_INET6, .sin6_addr = addr, .sin6_port = 4242 }; char buf[LARGER_THAN_MTU] = {0}; struct iovec iov = { .iov_base = buf, .iov_len = sizeof buf}; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_name = (struct sockaddr *)&sa, .msg_namelen = sizeof sa, }; ssize_t rc; int s = socket(AF_INET6, SOCK_DGRAM, 0); msg.msg_name = (struct sockaddr *)&sa; msg.msg_namelen = sizeof sa; rc = sendmsg(s, &msg, 0); if (rc == -1) { perror("send"); return 1; } printf("send() returned %zi\n", rc); return 0; }