0001
0002
0003
0004
0005
0006
0007 #define _GNU_SOURCE
0008
0009 #include <arpa/inet.h>
0010 #include <errno.h>
0011 #include <error.h>
0012 #include <linux/dccp.h>
0013 #include <linux/in.h>
0014 #include <linux/unistd.h>
0015 #include <stdbool.h>
0016 #include <stdio.h>
0017 #include <stdlib.h>
0018 #include <string.h>
0019 #include <sys/epoll.h>
0020 #include <sys/types.h>
0021 #include <sys/socket.h>
0022 #include <unistd.h>
0023
0024 #ifndef SOL_DCCP
0025 #define SOL_DCCP 269
0026 #endif
0027
0028 static const char *IP4_ADDR = "127.0.0.1";
0029 static const char *IP6_ADDR = "::1";
0030 static const char *IP4_MAPPED6 = "::ffff:127.0.0.1";
0031
0032 static const int PORT = 8888;
0033
0034 static void build_rcv_fd(int family, int proto, int *rcv_fds, int count,
0035 const char *addr_str)
0036 {
0037 struct sockaddr_in addr4 = {0};
0038 struct sockaddr_in6 addr6 = {0};
0039 struct sockaddr *addr;
0040 int opt, i, sz;
0041
0042 memset(&addr, 0, sizeof(addr));
0043
0044 switch (family) {
0045 case AF_INET:
0046 addr4.sin_family = family;
0047 if (!addr_str)
0048 addr4.sin_addr.s_addr = htonl(INADDR_ANY);
0049 else if (!inet_pton(family, addr_str, &addr4.sin_addr.s_addr))
0050 error(1, errno, "inet_pton failed: %s", addr_str);
0051 addr4.sin_port = htons(PORT);
0052 sz = sizeof(addr4);
0053 addr = (struct sockaddr *)&addr4;
0054 break;
0055 case AF_INET6:
0056 addr6.sin6_family = AF_INET6;
0057 if (!addr_str)
0058 addr6.sin6_addr = in6addr_any;
0059 else if (!inet_pton(family, addr_str, &addr6.sin6_addr))
0060 error(1, errno, "inet_pton failed: %s", addr_str);
0061 addr6.sin6_port = htons(PORT);
0062 sz = sizeof(addr6);
0063 addr = (struct sockaddr *)&addr6;
0064 break;
0065 default:
0066 error(1, 0, "Unsupported family %d", family);
0067
0068
0069
0070
0071 return;
0072 }
0073
0074 for (i = 0; i < count; ++i) {
0075 rcv_fds[i] = socket(family, proto, 0);
0076 if (rcv_fds[i] < 0)
0077 error(1, errno, "failed to create receive socket");
0078
0079 opt = 1;
0080 if (setsockopt(rcv_fds[i], SOL_SOCKET, SO_REUSEPORT, &opt,
0081 sizeof(opt)))
0082 error(1, errno, "failed to set SO_REUSEPORT");
0083
0084 if (bind(rcv_fds[i], addr, sz))
0085 error(1, errno, "failed to bind receive socket");
0086
0087 if (proto == SOCK_STREAM && listen(rcv_fds[i], 10))
0088 error(1, errno, "tcp: failed to listen on receive port");
0089 else if (proto == SOCK_DCCP) {
0090 if (setsockopt(rcv_fds[i], SOL_DCCP,
0091 DCCP_SOCKOPT_SERVICE,
0092 &(int) {htonl(42)}, sizeof(int)))
0093 error(1, errno, "failed to setsockopt");
0094
0095 if (listen(rcv_fds[i], 10))
0096 error(1, errno, "dccp: failed to listen on receive port");
0097 }
0098 }
0099 }
0100
0101 static int connect_and_send(int family, int proto)
0102 {
0103 struct sockaddr_in saddr4 = {0};
0104 struct sockaddr_in daddr4 = {0};
0105 struct sockaddr_in6 saddr6 = {0};
0106 struct sockaddr_in6 daddr6 = {0};
0107 struct sockaddr *saddr, *daddr;
0108 int fd, sz;
0109
0110 switch (family) {
0111 case AF_INET:
0112 saddr4.sin_family = AF_INET;
0113 saddr4.sin_addr.s_addr = htonl(INADDR_ANY);
0114 saddr4.sin_port = 0;
0115
0116 daddr4.sin_family = AF_INET;
0117 if (!inet_pton(family, IP4_ADDR, &daddr4.sin_addr.s_addr))
0118 error(1, errno, "inet_pton failed: %s", IP4_ADDR);
0119 daddr4.sin_port = htons(PORT);
0120
0121 sz = sizeof(saddr4);
0122 saddr = (struct sockaddr *)&saddr4;
0123 daddr = (struct sockaddr *)&daddr4;
0124 break;
0125 case AF_INET6:
0126 saddr6.sin6_family = AF_INET6;
0127 saddr6.sin6_addr = in6addr_any;
0128
0129 daddr6.sin6_family = AF_INET6;
0130 if (!inet_pton(family, IP6_ADDR, &daddr6.sin6_addr))
0131 error(1, errno, "inet_pton failed: %s", IP6_ADDR);
0132 daddr6.sin6_port = htons(PORT);
0133
0134 sz = sizeof(saddr6);
0135 saddr = (struct sockaddr *)&saddr6;
0136 daddr = (struct sockaddr *)&daddr6;
0137 break;
0138 default:
0139 error(1, 0, "Unsupported family %d", family);
0140
0141
0142
0143
0144 return -1;
0145 }
0146
0147 fd = socket(family, proto, 0);
0148 if (fd < 0)
0149 error(1, errno, "failed to create send socket");
0150
0151 if (proto == SOCK_DCCP &&
0152 setsockopt(fd, SOL_DCCP, DCCP_SOCKOPT_SERVICE,
0153 &(int){htonl(42)}, sizeof(int)))
0154 error(1, errno, "failed to setsockopt");
0155
0156 if (bind(fd, saddr, sz))
0157 error(1, errno, "failed to bind send socket");
0158
0159 if (connect(fd, daddr, sz))
0160 error(1, errno, "failed to connect send socket");
0161
0162 if (send(fd, "a", 1, 0) < 0)
0163 error(1, errno, "failed to send message");
0164
0165 return fd;
0166 }
0167
0168 static int receive_once(int epfd, int proto)
0169 {
0170 struct epoll_event ev;
0171 int i, fd;
0172 char buf[8];
0173
0174 i = epoll_wait(epfd, &ev, 1, 3);
0175 if (i < 0)
0176 error(1, errno, "epoll_wait failed");
0177
0178 if (proto == SOCK_STREAM || proto == SOCK_DCCP) {
0179 fd = accept(ev.data.fd, NULL, NULL);
0180 if (fd < 0)
0181 error(1, errno, "failed to accept");
0182 i = recv(fd, buf, sizeof(buf), 0);
0183 close(fd);
0184 } else {
0185 i = recv(ev.data.fd, buf, sizeof(buf), 0);
0186 }
0187
0188 if (i < 0)
0189 error(1, errno, "failed to recv");
0190
0191 return ev.data.fd;
0192 }
0193
0194 static void test(int *rcv_fds, int count, int family, int proto, int fd)
0195 {
0196 struct epoll_event ev;
0197 int epfd, i, send_fd, recv_fd;
0198
0199 epfd = epoll_create(1);
0200 if (epfd < 0)
0201 error(1, errno, "failed to create epoll");
0202
0203 ev.events = EPOLLIN;
0204 for (i = 0; i < count; ++i) {
0205 ev.data.fd = rcv_fds[i];
0206 if (epoll_ctl(epfd, EPOLL_CTL_ADD, rcv_fds[i], &ev))
0207 error(1, errno, "failed to register sock epoll");
0208 }
0209
0210 send_fd = connect_and_send(family, proto);
0211
0212 recv_fd = receive_once(epfd, proto);
0213 if (recv_fd != fd)
0214 error(1, 0, "received on an unexpected socket");
0215
0216 close(send_fd);
0217 close(epfd);
0218 }
0219
0220
0221 static void run_one_test(int fam_send, int fam_rcv, int proto,
0222 const char *addr_str)
0223 {
0224
0225
0226
0227
0228
0229
0230
0231 int rcv_fds[10], i;
0232
0233 build_rcv_fd(AF_INET, proto, rcv_fds, 2, NULL);
0234 build_rcv_fd(AF_INET6, proto, rcv_fds + 2, 2, NULL);
0235 build_rcv_fd(fam_rcv, proto, rcv_fds + 4, 1, addr_str);
0236 build_rcv_fd(AF_INET, proto, rcv_fds + 5, 2, NULL);
0237 build_rcv_fd(AF_INET6, proto, rcv_fds + 7, 2, NULL);
0238 test(rcv_fds, 9, fam_send, proto, rcv_fds[4]);
0239 for (i = 0; i < 9; ++i)
0240 close(rcv_fds[i]);
0241 fprintf(stderr, "pass\n");
0242 }
0243
0244 static void test_proto(int proto, const char *proto_str)
0245 {
0246 if (proto == SOCK_DCCP) {
0247 int test_fd;
0248
0249 test_fd = socket(AF_INET, proto, 0);
0250 if (test_fd < 0) {
0251 if (errno == ESOCKTNOSUPPORT) {
0252 fprintf(stderr, "DCCP not supported: skipping DCCP tests\n");
0253 return;
0254 } else
0255 error(1, errno, "failed to create a DCCP socket");
0256 }
0257 close(test_fd);
0258 }
0259
0260 fprintf(stderr, "%s IPv4 ... ", proto_str);
0261 run_one_test(AF_INET, AF_INET, proto, IP4_ADDR);
0262
0263 fprintf(stderr, "%s IPv6 ... ", proto_str);
0264 run_one_test(AF_INET6, AF_INET6, proto, IP6_ADDR);
0265
0266 fprintf(stderr, "%s IPv4 mapped to IPv6 ... ", proto_str);
0267 run_one_test(AF_INET, AF_INET6, proto, IP4_MAPPED6);
0268 }
0269
0270 int main(void)
0271 {
0272 test_proto(SOCK_DGRAM, "UDP");
0273 test_proto(SOCK_STREAM, "TCP");
0274 test_proto(SOCK_DCCP, "DCCP");
0275
0276 fprintf(stderr, "SUCCESS\n");
0277 return 0;
0278 }