Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * It is possible to use SO_REUSEPORT to open multiple sockets bound to
0004  * equivalent local addresses using AF_INET and AF_INET6 at the same time.  If
0005  * the AF_INET6 socket has IPV6_V6ONLY set, it's clear which socket should
0006  * receive a given incoming packet.  However, when it is not set, incoming v4
0007  * packets should prefer the AF_INET socket(s).  This behavior was defined with
0008  * the original SO_REUSEPORT implementation, but broke with
0009  * e32ea7e74727 ("soreuseport: fast reuseport UDP socket selection")
0010  * This test creates these mixed AF_INET/AF_INET6 sockets and asserts the
0011  * AF_INET preference for v4 packets.
0012  */
0013 
0014 #define _GNU_SOURCE
0015 
0016 #include <arpa/inet.h>
0017 #include <errno.h>
0018 #include <error.h>
0019 #include <linux/in.h>
0020 #include <linux/unistd.h>
0021 #include <stdio.h>
0022 #include <stdlib.h>
0023 #include <string.h>
0024 #include <sys/epoll.h>
0025 #include <sys/types.h>
0026 #include <sys/socket.h>
0027 #include <unistd.h>
0028 
0029 static const int PORT = 8888;
0030 
0031 static void build_rcv_fd(int family, int proto, int *rcv_fds, int count)
0032 {
0033     struct sockaddr_storage addr;
0034     struct sockaddr_in  *addr4;
0035     struct sockaddr_in6 *addr6;
0036     int opt, i;
0037 
0038     switch (family) {
0039     case AF_INET:
0040         addr4 = (struct sockaddr_in *)&addr;
0041         addr4->sin_family = AF_INET;
0042         addr4->sin_addr.s_addr = htonl(INADDR_ANY);
0043         addr4->sin_port = htons(PORT);
0044         break;
0045     case AF_INET6:
0046         addr6 = (struct sockaddr_in6 *)&addr;
0047         addr6->sin6_family = AF_INET6;
0048         addr6->sin6_addr = in6addr_any;
0049         addr6->sin6_port = htons(PORT);
0050         break;
0051     default:
0052         error(1, 0, "Unsupported family %d", family);
0053     }
0054 
0055     for (i = 0; i < count; ++i) {
0056         rcv_fds[i] = socket(family, proto, 0);
0057         if (rcv_fds[i] < 0)
0058             error(1, errno, "failed to create receive socket");
0059 
0060         opt = 1;
0061         if (setsockopt(rcv_fds[i], SOL_SOCKET, SO_REUSEPORT, &opt,
0062                    sizeof(opt)))
0063             error(1, errno, "failed to set SO_REUSEPORT");
0064 
0065         if (bind(rcv_fds[i], (struct sockaddr *)&addr, sizeof(addr)))
0066             error(1, errno, "failed to bind receive socket");
0067 
0068         if (proto == SOCK_STREAM && listen(rcv_fds[i], 10))
0069             error(1, errno, "failed to listen on receive port");
0070     }
0071 }
0072 
0073 static void send_from_v4(int proto)
0074 {
0075     struct sockaddr_in  saddr, daddr;
0076     int fd;
0077 
0078     saddr.sin_family = AF_INET;
0079     saddr.sin_addr.s_addr = htonl(INADDR_ANY);
0080     saddr.sin_port = 0;
0081 
0082     daddr.sin_family = AF_INET;
0083     daddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
0084     daddr.sin_port = htons(PORT);
0085 
0086     fd = socket(AF_INET, proto, 0);
0087     if (fd < 0)
0088         error(1, errno, "failed to create send socket");
0089 
0090     if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)))
0091         error(1, errno, "failed to bind send socket");
0092 
0093     if (connect(fd, (struct sockaddr *)&daddr, sizeof(daddr)))
0094         error(1, errno, "failed to connect send socket");
0095 
0096     if (send(fd, "a", 1, 0) < 0)
0097         error(1, errno, "failed to send message");
0098 
0099     close(fd);
0100 }
0101 
0102 static int receive_once(int epfd, int proto)
0103 {
0104     struct epoll_event ev;
0105     int i, fd;
0106     char buf[8];
0107 
0108     i = epoll_wait(epfd, &ev, 1, -1);
0109     if (i < 0)
0110         error(1, errno, "epoll_wait failed");
0111 
0112     if (proto == SOCK_STREAM) {
0113         fd = accept(ev.data.fd, NULL, NULL);
0114         if (fd < 0)
0115             error(1, errno, "failed to accept");
0116         i = recv(fd, buf, sizeof(buf), 0);
0117         close(fd);
0118     } else {
0119         i = recv(ev.data.fd, buf, sizeof(buf), 0);
0120     }
0121 
0122     if (i < 0)
0123         error(1, errno, "failed to recv");
0124 
0125     return ev.data.fd;
0126 }
0127 
0128 static void test(int *rcv_fds, int count, int proto)
0129 {
0130     struct epoll_event ev;
0131     int epfd, i, test_fd;
0132     int test_family;
0133     socklen_t len;
0134 
0135     epfd = epoll_create(1);
0136     if (epfd < 0)
0137         error(1, errno, "failed to create epoll");
0138 
0139     ev.events = EPOLLIN;
0140     for (i = 0; i < count; ++i) {
0141         ev.data.fd = rcv_fds[i];
0142         if (epoll_ctl(epfd, EPOLL_CTL_ADD, rcv_fds[i], &ev))
0143             error(1, errno, "failed to register sock epoll");
0144     }
0145 
0146     send_from_v4(proto);
0147 
0148     test_fd = receive_once(epfd, proto);
0149     len = sizeof(test_family);
0150     if (getsockopt(test_fd, SOL_SOCKET, SO_DOMAIN, &test_family, &len))
0151         error(1, errno, "failed to read socket domain");
0152     if (test_family != AF_INET)
0153         error(1, 0, "expected to receive on v4 socket but got v6 (%d)",
0154               test_family);
0155 
0156     close(epfd);
0157 }
0158 
0159 int main(void)
0160 {
0161     int rcv_fds[32], i;
0162 
0163     fprintf(stderr, "---- UDP IPv4 created before IPv6 ----\n");
0164     build_rcv_fd(AF_INET, SOCK_DGRAM, rcv_fds, 5);
0165     build_rcv_fd(AF_INET6, SOCK_DGRAM, &(rcv_fds[5]), 5);
0166     test(rcv_fds, 10, SOCK_DGRAM);
0167     for (i = 0; i < 10; ++i)
0168         close(rcv_fds[i]);
0169 
0170     fprintf(stderr, "---- UDP IPv6 created before IPv4 ----\n");
0171     build_rcv_fd(AF_INET6, SOCK_DGRAM, rcv_fds, 5);
0172     build_rcv_fd(AF_INET, SOCK_DGRAM, &(rcv_fds[5]), 5);
0173     test(rcv_fds, 10, SOCK_DGRAM);
0174     for (i = 0; i < 10; ++i)
0175         close(rcv_fds[i]);
0176 
0177     /* NOTE: UDP socket lookups traverse a different code path when there
0178      * are > 10 sockets in a group.
0179      */
0180     fprintf(stderr, "---- UDP IPv4 created before IPv6 (large) ----\n");
0181     build_rcv_fd(AF_INET, SOCK_DGRAM, rcv_fds, 16);
0182     build_rcv_fd(AF_INET6, SOCK_DGRAM, &(rcv_fds[16]), 16);
0183     test(rcv_fds, 32, SOCK_DGRAM);
0184     for (i = 0; i < 32; ++i)
0185         close(rcv_fds[i]);
0186 
0187     fprintf(stderr, "---- UDP IPv6 created before IPv4 (large) ----\n");
0188     build_rcv_fd(AF_INET6, SOCK_DGRAM, rcv_fds, 16);
0189     build_rcv_fd(AF_INET, SOCK_DGRAM, &(rcv_fds[16]), 16);
0190     test(rcv_fds, 32, SOCK_DGRAM);
0191     for (i = 0; i < 32; ++i)
0192         close(rcv_fds[i]);
0193 
0194     fprintf(stderr, "---- TCP IPv4 created before IPv6 ----\n");
0195     build_rcv_fd(AF_INET, SOCK_STREAM, rcv_fds, 5);
0196     build_rcv_fd(AF_INET6, SOCK_STREAM, &(rcv_fds[5]), 5);
0197     test(rcv_fds, 10, SOCK_STREAM);
0198     for (i = 0; i < 10; ++i)
0199         close(rcv_fds[i]);
0200 
0201     fprintf(stderr, "---- TCP IPv6 created before IPv4 ----\n");
0202     build_rcv_fd(AF_INET6, SOCK_STREAM, rcv_fds, 5);
0203     build_rcv_fd(AF_INET, SOCK_STREAM, &(rcv_fds[5]), 5);
0204     test(rcv_fds, 10, SOCK_STREAM);
0205     for (i = 0; i < 10; ++i)
0206         close(rcv_fds[i]);
0207 
0208     fprintf(stderr, "SUCCESS\n");
0209     return 0;
0210 }