1 // SPDX-License-Identifier: GPL-2.0 2 3 #define _GNU_SOURCE 4 5 #include <assert.h> 6 #include <errno.h> 7 #include <fcntl.h> 8 #include <limits.h> 9 #include <string.h> 10 #include <stdarg.h> 11 #include <stdbool.h> 12 #include <stdint.h> 13 #include <inttypes.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <strings.h> 17 #include <time.h> 18 #include <unistd.h> 19 20 #include <sys/socket.h> 21 #include <sys/types.h> 22 #include <sys/wait.h> 23 24 #include <netdb.h> 25 #include <netinet/in.h> 26 27 #include <linux/tcp.h> 28 29 static int pf = AF_INET; 30 31 #ifndef IPPROTO_MPTCP 32 #define IPPROTO_MPTCP 262 33 #endif 34 #ifndef SOL_MPTCP 35 #define SOL_MPTCP 284 36 #endif 37 38 #ifndef MPTCP_INFO 39 struct mptcp_info { 40 __u8 mptcpi_subflows; 41 __u8 mptcpi_add_addr_signal; 42 __u8 mptcpi_add_addr_accepted; 43 __u8 mptcpi_subflows_max; 44 __u8 mptcpi_add_addr_signal_max; 45 __u8 mptcpi_add_addr_accepted_max; 46 __u32 mptcpi_flags; 47 __u32 mptcpi_token; 48 __u64 mptcpi_write_seq; 49 __u64 mptcpi_snd_una; 50 __u64 mptcpi_rcv_nxt; 51 __u8 mptcpi_local_addr_used; 52 __u8 mptcpi_local_addr_max; 53 __u8 mptcpi_csum_enabled; 54 __u32 mptcpi_retransmits; 55 __u64 mptcpi_bytes_retrans; 56 __u64 mptcpi_bytes_sent; 57 __u64 mptcpi_bytes_received; 58 __u64 mptcpi_bytes_acked; 59 }; 60 61 struct mptcp_subflow_data { 62 __u32 size_subflow_data; /* size of this structure in userspace */ 63 __u32 num_subflows; /* must be 0, set by kernel */ 64 __u32 size_kernel; /* must be 0, set by kernel */ 65 __u32 size_user; /* size of one element in data[] */ 66 } __attribute__((aligned(8))); 67 68 struct mptcp_subflow_addrs { 69 union { 70 __kernel_sa_family_t sa_family; 71 struct sockaddr sa_local; 72 struct sockaddr_in sin_local; 73 struct sockaddr_in6 sin6_local; 74 struct __kernel_sockaddr_storage ss_local; 75 }; 76 union { 77 struct sockaddr sa_remote; 78 struct sockaddr_in sin_remote; 79 struct sockaddr_in6 sin6_remote; 80 struct __kernel_sockaddr_storage ss_remote; 81 }; 82 }; 83 84 #define MPTCP_INFO 1 85 #define MPTCP_TCPINFO 2 86 #define MPTCP_SUBFLOW_ADDRS 3 87 #endif 88 89 #ifndef MPTCP_FULL_INFO 90 struct mptcp_subflow_info { 91 __u32 id; 92 struct mptcp_subflow_addrs addrs; 93 }; 94 95 struct mptcp_full_info { 96 __u32 size_tcpinfo_kernel; /* must be 0, set by kernel */ 97 __u32 size_tcpinfo_user; 98 __u32 size_sfinfo_kernel; /* must be 0, set by kernel */ 99 __u32 size_sfinfo_user; 100 __u32 num_subflows; /* must be 0, set by kernel (real subflow count) */ 101 __u32 size_arrays_user; /* max subflows that userspace is interested in; 102 * the buffers at subflow_info/tcp_info 103 * are respectively at least: 104 * size_arrays * size_sfinfo_user 105 * size_arrays * size_tcpinfo_user 106 * bytes wide 107 */ 108 __aligned_u64 subflow_info; 109 __aligned_u64 tcp_info; 110 struct mptcp_info mptcp_info; 111 }; 112 113 #define MPTCP_FULL_INFO 4 114 #endif 115 116 struct so_state { 117 struct mptcp_info mi; 118 struct mptcp_info last_sample; 119 struct tcp_info tcp_info; 120 struct mptcp_subflow_addrs addrs; 121 uint64_t mptcpi_rcv_delta; 122 uint64_t tcpi_rcv_delta; 123 bool pkt_stats_avail; 124 }; 125 126 #ifndef MIN 127 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 128 #endif 129 130 static void die_perror(const char *msg) 131 { 132 perror(msg); 133 exit(1); 134 } 135 136 static void die_usage(int r) 137 { 138 fprintf(stderr, "Usage: mptcp_sockopt [-6]\n"); 139 exit(r); 140 } 141 142 static void xerror(const char *fmt, ...) 143 { 144 va_list ap; 145 146 va_start(ap, fmt); 147 vfprintf(stderr, fmt, ap); 148 va_end(ap); 149 fputc('\n', stderr); 150 exit(1); 151 } 152 153 static const char *getxinfo_strerr(int err) 154 { 155 if (err == EAI_SYSTEM) 156 return strerror(errno); 157 158 return gai_strerror(err); 159 } 160 161 static void xgetaddrinfo(const char *node, const char *service, 162 struct addrinfo *hints, 163 struct addrinfo **res) 164 { 165 again: 166 int err = getaddrinfo(node, service, hints, res); 167 168 if (err) { 169 const char *errstr; 170 171 if (err == EAI_SOCKTYPE) { 172 hints->ai_protocol = IPPROTO_TCP; 173 goto again; 174 } 175 176 errstr = getxinfo_strerr(err); 177 178 fprintf(stderr, "Fatal: getaddrinfo(%s:%s): %s\n", 179 node ? node : "", service ? service : "", errstr); 180 exit(1); 181 } 182 } 183 184 static int sock_listen_mptcp(const char * const listenaddr, 185 const char * const port) 186 { 187 int sock = -1; 188 struct addrinfo hints = { 189 .ai_protocol = IPPROTO_MPTCP, 190 .ai_socktype = SOCK_STREAM, 191 .ai_flags = AI_PASSIVE | AI_NUMERICHOST 192 }; 193 194 hints.ai_family = pf; 195 196 struct addrinfo *a, *addr; 197 int one = 1; 198 199 xgetaddrinfo(listenaddr, port, &hints, &addr); 200 hints.ai_family = pf; 201 202 for (a = addr; a; a = a->ai_next) { 203 sock = socket(a->ai_family, a->ai_socktype, IPPROTO_MPTCP); 204 if (sock < 0) 205 continue; 206 207 if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, 208 sizeof(one))) 209 perror("setsockopt"); 210 211 if (bind(sock, a->ai_addr, a->ai_addrlen) == 0) 212 break; /* success */ 213 214 perror("bind"); 215 close(sock); 216 sock = -1; 217 } 218 219 freeaddrinfo(addr); 220 221 if (sock < 0) 222 xerror("could not create listen socket"); 223 224 if (listen(sock, 20)) 225 die_perror("listen"); 226 227 return sock; 228 } 229 230 static int sock_connect_mptcp(const char * const remoteaddr, 231 const char * const port, int proto) 232 { 233 struct addrinfo hints = { 234 .ai_protocol = IPPROTO_MPTCP, 235 .ai_socktype = SOCK_STREAM, 236 }; 237 struct addrinfo *a, *addr; 238 int sock = -1; 239 240 hints.ai_family = pf; 241 242 xgetaddrinfo(remoteaddr, port, &hints, &addr); 243 for (a = addr; a; a = a->ai_next) { 244 sock = socket(a->ai_family, a->ai_socktype, proto); 245 if (sock < 0) 246 continue; 247 248 if (connect(sock, a->ai_addr, a->ai_addrlen) == 0) 249 break; /* success */ 250 251 die_perror("connect"); 252 } 253 254 if (sock < 0) 255 xerror("could not create connect socket"); 256 257 freeaddrinfo(addr); 258 return sock; 259 } 260 261 static void parse_opts(int argc, char **argv) 262 { 263 int c; 264 265 while ((c = getopt(argc, argv, "h6")) != -1) { 266 switch (c) { 267 case 'h': 268 die_usage(0); 269 break; 270 case '6': 271 pf = AF_INET6; 272 break; 273 default: 274 die_usage(1); 275 break; 276 } 277 } 278 } 279 280 static void do_getsockopt_bogus_sf_data(int fd, int optname) 281 { 282 struct mptcp_subflow_data good_data; 283 struct bogus_data { 284 struct mptcp_subflow_data d; 285 char buf[2]; 286 } bd; 287 socklen_t olen, _olen; 288 int ret; 289 290 memset(&bd, 0, sizeof(bd)); 291 memset(&good_data, 0, sizeof(good_data)); 292 293 olen = sizeof(good_data); 294 good_data.size_subflow_data = olen; 295 296 ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); 297 assert(ret < 0); /* 0 size_subflow_data */ 298 assert(olen == sizeof(good_data)); 299 300 bd.d = good_data; 301 302 ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); 303 assert(ret == 0); 304 assert(olen == sizeof(good_data)); 305 assert(bd.d.num_subflows == 1); 306 assert(bd.d.size_kernel > 0); 307 assert(bd.d.size_user == 0); 308 309 bd.d = good_data; 310 _olen = rand() % olen; 311 olen = _olen; 312 ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); 313 assert(ret < 0); /* bogus olen */ 314 assert(olen == _olen); /* must be unchanged */ 315 316 bd.d = good_data; 317 olen = sizeof(good_data); 318 bd.d.size_kernel = 1; 319 ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); 320 assert(ret < 0); /* size_kernel not 0 */ 321 322 bd.d = good_data; 323 olen = sizeof(good_data); 324 bd.d.num_subflows = 1; 325 ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); 326 assert(ret < 0); /* num_subflows not 0 */ 327 328 /* forward compat check: larger struct mptcp_subflow_data on 'old' kernel */ 329 bd.d = good_data; 330 olen = sizeof(bd); 331 bd.d.size_subflow_data = sizeof(bd); 332 333 ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); 334 assert(ret == 0); 335 336 /* olen must be truncated to real data size filled by kernel: */ 337 assert(olen == sizeof(good_data)); 338 339 assert(bd.d.size_subflow_data == sizeof(bd)); 340 341 bd.d = good_data; 342 bd.d.size_subflow_data += 1; 343 bd.d.size_user = 1; 344 olen = bd.d.size_subflow_data + 1; 345 _olen = olen; 346 347 ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &_olen); 348 assert(ret == 0); 349 350 /* no truncation, kernel should have filled 1 byte of optname payload in buf[1]: */ 351 assert(olen == _olen); 352 353 assert(bd.d.size_subflow_data == sizeof(good_data) + 1); 354 assert(bd.buf[0] == 0); 355 } 356 357 static void do_getsockopt_mptcp_info(struct so_state *s, int fd, size_t w) 358 { 359 struct mptcp_info i; 360 socklen_t olen; 361 int ret; 362 363 olen = sizeof(i); 364 ret = getsockopt(fd, SOL_MPTCP, MPTCP_INFO, &i, &olen); 365 366 if (ret < 0) 367 die_perror("getsockopt MPTCP_INFO"); 368 369 s->pkt_stats_avail = olen >= sizeof(i); 370 371 s->last_sample = i; 372 if (s->mi.mptcpi_write_seq == 0) 373 s->mi = i; 374 375 assert(s->mi.mptcpi_write_seq + w == i.mptcpi_write_seq); 376 377 s->mptcpi_rcv_delta = i.mptcpi_rcv_nxt - s->mi.mptcpi_rcv_nxt; 378 } 379 380 static void do_getsockopt_tcp_info(struct so_state *s, int fd, size_t r, size_t w) 381 { 382 struct my_tcp_info { 383 struct mptcp_subflow_data d; 384 struct tcp_info ti[2]; 385 } ti; 386 int ret, tries = 5; 387 socklen_t olen; 388 389 do { 390 memset(&ti, 0, sizeof(ti)); 391 392 ti.d.size_subflow_data = sizeof(struct mptcp_subflow_data); 393 ti.d.size_user = sizeof(struct tcp_info); 394 olen = sizeof(ti); 395 396 ret = getsockopt(fd, SOL_MPTCP, MPTCP_TCPINFO, &ti, &olen); 397 if (ret < 0) 398 xerror("getsockopt MPTCP_TCPINFO (tries %d, %m)"); 399 400 assert(olen <= sizeof(ti)); 401 assert(ti.d.size_kernel > 0); 402 assert(ti.d.size_user == 403 MIN(ti.d.size_kernel, sizeof(struct tcp_info))); 404 assert(ti.d.num_subflows == 1); 405 406 assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data)); 407 olen -= sizeof(struct mptcp_subflow_data); 408 assert(olen == ti.d.size_user); 409 410 s->tcp_info = ti.ti[0]; 411 412 if (ti.ti[0].tcpi_bytes_sent == w && 413 ti.ti[0].tcpi_bytes_received == r) 414 goto done; 415 416 if (r == 0 && ti.ti[0].tcpi_bytes_sent == w && 417 ti.ti[0].tcpi_bytes_received) { 418 s->tcpi_rcv_delta = ti.ti[0].tcpi_bytes_received; 419 goto done; 420 } 421 422 /* wait and repeat, might be that tx is still ongoing */ 423 sleep(1); 424 } while (tries-- > 0); 425 426 xerror("tcpi_bytes_sent %" PRIu64 ", want %zu. tcpi_bytes_received %" PRIu64 ", want %zu", 427 ti.ti[0].tcpi_bytes_sent, w, ti.ti[0].tcpi_bytes_received, r); 428 429 done: 430 do_getsockopt_bogus_sf_data(fd, MPTCP_TCPINFO); 431 } 432 433 static void do_getsockopt_subflow_addrs(struct so_state *s, int fd) 434 { 435 struct sockaddr_storage remote, local; 436 socklen_t olen, rlen, llen; 437 int ret; 438 struct my_addrs { 439 struct mptcp_subflow_data d; 440 struct mptcp_subflow_addrs addr[2]; 441 } addrs; 442 443 memset(&addrs, 0, sizeof(addrs)); 444 memset(&local, 0, sizeof(local)); 445 memset(&remote, 0, sizeof(remote)); 446 447 addrs.d.size_subflow_data = sizeof(struct mptcp_subflow_data); 448 addrs.d.size_user = sizeof(struct mptcp_subflow_addrs); 449 olen = sizeof(addrs); 450 451 ret = getsockopt(fd, SOL_MPTCP, MPTCP_SUBFLOW_ADDRS, &addrs, &olen); 452 if (ret < 0) 453 die_perror("getsockopt MPTCP_SUBFLOW_ADDRS"); 454 455 assert(olen <= sizeof(addrs)); 456 assert(addrs.d.size_kernel > 0); 457 assert(addrs.d.size_user == 458 MIN(addrs.d.size_kernel, sizeof(struct mptcp_subflow_addrs))); 459 assert(addrs.d.num_subflows == 1); 460 461 assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data)); 462 olen -= sizeof(struct mptcp_subflow_data); 463 assert(olen == addrs.d.size_user); 464 465 llen = sizeof(local); 466 ret = getsockname(fd, (struct sockaddr *)&local, &llen); 467 if (ret < 0) 468 die_perror("getsockname"); 469 rlen = sizeof(remote); 470 ret = getpeername(fd, (struct sockaddr *)&remote, &rlen); 471 if (ret < 0) 472 die_perror("getpeername"); 473 474 assert(rlen > 0); 475 assert(rlen == llen); 476 477 assert(remote.ss_family == local.ss_family); 478 479 assert(memcmp(&local, &addrs.addr[0].ss_local, sizeof(local)) == 0); 480 assert(memcmp(&remote, &addrs.addr[0].ss_remote, sizeof(remote)) == 0); 481 s->addrs = addrs.addr[0]; 482 483 memset(&addrs, 0, sizeof(addrs)); 484 485 addrs.d.size_subflow_data = sizeof(struct mptcp_subflow_data); 486 addrs.d.size_user = sizeof(sa_family_t); 487 olen = sizeof(addrs.d) + sizeof(sa_family_t); 488 489 ret = getsockopt(fd, SOL_MPTCP, MPTCP_SUBFLOW_ADDRS, &addrs, &olen); 490 assert(ret == 0); 491 assert(olen == sizeof(addrs.d) + sizeof(sa_family_t)); 492 493 assert(addrs.addr[0].sa_family == pf); 494 assert(addrs.addr[0].sa_family == local.ss_family); 495 496 assert(memcmp(&local, &addrs.addr[0].ss_local, sizeof(local)) != 0); 497 assert(memcmp(&remote, &addrs.addr[0].ss_remote, sizeof(remote)) != 0); 498 499 do_getsockopt_bogus_sf_data(fd, MPTCP_SUBFLOW_ADDRS); 500 } 501 502 static void do_getsockopt_mptcp_full_info(struct so_state *s, int fd) 503 { 504 size_t data_size = sizeof(struct mptcp_full_info); 505 struct mptcp_subflow_info sfinfo[2]; 506 struct tcp_info tcp_info[2]; 507 struct mptcp_full_info mfi; 508 socklen_t olen; 509 int ret; 510 511 memset(&mfi, 0, data_size); 512 memset(tcp_info, 0, sizeof(tcp_info)); 513 memset(sfinfo, 0, sizeof(sfinfo)); 514 515 mfi.size_tcpinfo_user = sizeof(struct tcp_info); 516 mfi.size_sfinfo_user = sizeof(struct mptcp_subflow_info); 517 mfi.size_arrays_user = 2; 518 mfi.subflow_info = (unsigned long)&sfinfo[0]; 519 mfi.tcp_info = (unsigned long)&tcp_info[0]; 520 olen = data_size; 521 522 ret = getsockopt(fd, SOL_MPTCP, MPTCP_FULL_INFO, &mfi, &olen); 523 if (ret < 0) { 524 if (errno == EOPNOTSUPP) { 525 perror("MPTCP_FULL_INFO test skipped"); 526 return; 527 } 528 xerror("getsockopt MPTCP_FULL_INFO"); 529 } 530 531 assert(olen <= data_size); 532 assert(mfi.size_tcpinfo_kernel > 0); 533 assert(mfi.size_tcpinfo_user == 534 MIN(mfi.size_tcpinfo_kernel, sizeof(struct tcp_info))); 535 assert(mfi.size_sfinfo_kernel > 0); 536 assert(mfi.size_sfinfo_user == 537 MIN(mfi.size_sfinfo_kernel, sizeof(struct mptcp_subflow_info))); 538 assert(mfi.num_subflows == 1); 539 540 /* Tolerate future extension to mptcp_info struct and running newer 541 * test on top of older kernel. 542 * Anyway any kernel supporting MPTCP_FULL_INFO must at least include 543 * the following in mptcp_info. 544 */ 545 assert(olen > (socklen_t)__builtin_offsetof(struct mptcp_full_info, tcp_info)); 546 assert(mfi.mptcp_info.mptcpi_subflows == 0); 547 assert(mfi.mptcp_info.mptcpi_bytes_sent == s->last_sample.mptcpi_bytes_sent); 548 assert(mfi.mptcp_info.mptcpi_bytes_received == s->last_sample.mptcpi_bytes_received); 549 550 assert(sfinfo[0].id == 1); 551 assert(tcp_info[0].tcpi_bytes_sent == s->tcp_info.tcpi_bytes_sent); 552 assert(tcp_info[0].tcpi_bytes_received == s->tcp_info.tcpi_bytes_received); 553 assert(!memcmp(&sfinfo->addrs, &s->addrs, sizeof(struct mptcp_subflow_addrs))); 554 } 555 556 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w) 557 { 558 do_getsockopt_mptcp_info(s, fd, w); 559 560 do_getsockopt_tcp_info(s, fd, r, w); 561 562 do_getsockopt_subflow_addrs(s, fd); 563 564 if (r) 565 do_getsockopt_mptcp_full_info(s, fd); 566 } 567 568 static void connect_one_server(int fd, int pipefd) 569 { 570 char buf[4096], buf2[4096]; 571 size_t len, i, total; 572 struct so_state s; 573 bool eof = false; 574 ssize_t ret; 575 576 memset(&s, 0, sizeof(s)); 577 578 len = rand() % (sizeof(buf) - 1); 579 580 if (len < 128) 581 len = 128; 582 583 for (i = 0; i < len ; i++) { 584 buf[i] = rand() % 26; 585 buf[i] += 'A'; 586 } 587 588 buf[i] = '\n'; 589 590 do_getsockopts(&s, fd, 0, 0); 591 592 /* un-block server */ 593 ret = read(pipefd, buf2, 4); 594 assert(ret == 4); 595 close(pipefd); 596 597 assert(strncmp(buf2, "xmit", 4) == 0); 598 599 ret = write(fd, buf, len); 600 if (ret < 0) 601 die_perror("write"); 602 603 if (ret != (ssize_t)len) 604 xerror("short write"); 605 606 total = 0; 607 do { 608 ret = read(fd, buf2 + total, sizeof(buf2) - total); 609 if (ret < 0) 610 die_perror("read"); 611 if (ret == 0) { 612 eof = true; 613 break; 614 } 615 616 total += ret; 617 } while (total < len); 618 619 if (total != len) 620 xerror("total %lu, len %lu eof %d\n", total, len, eof); 621 622 if (memcmp(buf, buf2, len)) 623 xerror("data corruption"); 624 625 if (s.tcpi_rcv_delta) 626 assert(s.tcpi_rcv_delta <= total); 627 628 do_getsockopts(&s, fd, ret, ret); 629 630 if (eof) 631 total += 1; /* sequence advances due to FIN */ 632 633 assert(s.mptcpi_rcv_delta == (uint64_t)total); 634 close(fd); 635 } 636 637 static void process_one_client(int fd, int pipefd) 638 { 639 ssize_t ret, ret2, ret3; 640 struct so_state s; 641 char buf[4096]; 642 643 memset(&s, 0, sizeof(s)); 644 do_getsockopts(&s, fd, 0, 0); 645 646 ret = write(pipefd, "xmit", 4); 647 assert(ret == 4); 648 649 ret = read(fd, buf, sizeof(buf)); 650 if (ret < 0) 651 die_perror("read"); 652 653 assert(s.mptcpi_rcv_delta <= (uint64_t)ret); 654 655 if (s.tcpi_rcv_delta) 656 assert(s.tcpi_rcv_delta == (uint64_t)ret); 657 658 ret2 = write(fd, buf, ret); 659 if (ret2 < 0) 660 die_perror("write"); 661 662 /* wait for hangup */ 663 ret3 = read(fd, buf, 1); 664 if (ret3 != 0) 665 xerror("expected EOF, got %lu", ret3); 666 667 do_getsockopts(&s, fd, ret, ret2); 668 if (s.mptcpi_rcv_delta != (uint64_t)ret + 1) 669 xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64, s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - ret); 670 671 /* be nice when running on top of older kernel */ 672 if (s.pkt_stats_avail) { 673 if (s.last_sample.mptcpi_bytes_sent != ret2) 674 xerror("mptcpi_bytes_sent %" PRIu64 ", expect %" PRIu64, 675 s.last_sample.mptcpi_bytes_sent, ret2, 676 s.last_sample.mptcpi_bytes_sent - ret2); 677 if (s.last_sample.mptcpi_bytes_received != ret) 678 xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64, 679 s.last_sample.mptcpi_bytes_received, ret, 680 s.last_sample.mptcpi_bytes_received - ret); 681 if (s.last_sample.mptcpi_bytes_acked != ret) 682 xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64, 683 s.last_sample.mptcpi_bytes_acked, ret2, 684 s.last_sample.mptcpi_bytes_acked - ret2); 685 } 686 687 close(fd); 688 } 689 690 static int xaccept(int s) 691 { 692 int fd = accept(s, NULL, 0); 693 694 if (fd < 0) 695 die_perror("accept"); 696 697 return fd; 698 } 699 700 static int server(int pipefd) 701 { 702 int fd = -1, r; 703 704 switch (pf) { 705 case AF_INET: 706 fd = sock_listen_mptcp("127.0.0.1", "15432"); 707 break; 708 case AF_INET6: 709 fd = sock_listen_mptcp("::1", "15432"); 710 break; 711 default: 712 xerror("Unknown pf %d\n", pf); 713 break; 714 } 715 716 r = write(pipefd, "conn", 4); 717 assert(r == 4); 718 719 alarm(15); 720 r = xaccept(fd); 721 722 process_one_client(r, pipefd); 723 724 return 0; 725 } 726 727 static void test_ip_tos_sockopt(int fd) 728 { 729 uint8_t tos_in, tos_out; 730 socklen_t s; 731 int r; 732 733 tos_in = rand() & 0xfc; 734 r = setsockopt(fd, SOL_IP, IP_TOS, &tos_in, sizeof(tos_out)); 735 if (r != 0) 736 die_perror("setsockopt IP_TOS"); 737 738 tos_out = 0; 739 s = sizeof(tos_out); 740 r = getsockopt(fd, SOL_IP, IP_TOS, &tos_out, &s); 741 if (r != 0) 742 die_perror("getsockopt IP_TOS"); 743 744 if (tos_in != tos_out) 745 xerror("tos %x != %x socklen_t %d\n", tos_in, tos_out, s); 746 747 if (s != 1) 748 xerror("tos should be 1 byte"); 749 750 s = 0; 751 r = getsockopt(fd, SOL_IP, IP_TOS, &tos_out, &s); 752 if (r != 0) 753 die_perror("getsockopt IP_TOS 0"); 754 if (s != 0) 755 xerror("expect socklen_t == 0"); 756 757 s = -1; 758 r = getsockopt(fd, SOL_IP, IP_TOS, &tos_out, &s); 759 if (r != -1 && errno != EINVAL) 760 die_perror("getsockopt IP_TOS did not indicate -EINVAL"); 761 if (s != -1) 762 xerror("expect socklen_t == -1"); 763 } 764 765 static int client(int pipefd) 766 { 767 int fd = -1; 768 769 alarm(15); 770 771 switch (pf) { 772 case AF_INET: 773 fd = sock_connect_mptcp("127.0.0.1", "15432", IPPROTO_MPTCP); 774 break; 775 case AF_INET6: 776 fd = sock_connect_mptcp("::1", "15432", IPPROTO_MPTCP); 777 break; 778 default: 779 xerror("Unknown pf %d\n", pf); 780 } 781 782 test_ip_tos_sockopt(fd); 783 784 connect_one_server(fd, pipefd); 785 786 return 0; 787 } 788 789 static pid_t xfork(void) 790 { 791 pid_t p = fork(); 792 793 if (p < 0) 794 die_perror("fork"); 795 796 return p; 797 } 798 799 static int rcheck(int wstatus, const char *what) 800 { 801 if (WIFEXITED(wstatus)) { 802 if (WEXITSTATUS(wstatus) == 0) 803 return 0; 804 fprintf(stderr, "%s exited, status=%d\n", what, WEXITSTATUS(wstatus)); 805 return WEXITSTATUS(wstatus); 806 } else if (WIFSIGNALED(wstatus)) { 807 xerror("%s killed by signal %d\n", what, WTERMSIG(wstatus)); 808 } else if (WIFSTOPPED(wstatus)) { 809 xerror("%s stopped by signal %d\n", what, WSTOPSIG(wstatus)); 810 } 811 812 return 111; 813 } 814 815 static void init_rng(void) 816 { 817 int fd = open("/dev/urandom", O_RDONLY); 818 819 if (fd >= 0) { 820 unsigned int foo; 821 ssize_t ret; 822 823 /* can't fail */ 824 ret = read(fd, &foo, sizeof(foo)); 825 assert(ret == sizeof(foo)); 826 827 close(fd); 828 srand(foo); 829 } else { 830 srand(time(NULL)); 831 } 832 } 833 834 int main(int argc, char *argv[]) 835 { 836 int e1, e2, wstatus; 837 pid_t s, c, ret; 838 int pipefds[2]; 839 840 parse_opts(argc, argv); 841 842 init_rng(); 843 844 e1 = pipe(pipefds); 845 if (e1 < 0) 846 die_perror("pipe"); 847 848 s = xfork(); 849 if (s == 0) 850 return server(pipefds[1]); 851 852 close(pipefds[1]); 853 854 /* wait until server bound a socket */ 855 e1 = read(pipefds[0], &e1, 4); 856 assert(e1 == 4); 857 858 c = xfork(); 859 if (c == 0) 860 return client(pipefds[0]); 861 862 close(pipefds[0]); 863 864 ret = waitpid(s, &wstatus, 0); 865 if (ret == -1) 866 die_perror("waitpid"); 867 e1 = rcheck(wstatus, "server"); 868 ret = waitpid(c, &wstatus, 0); 869 if (ret == -1) 870 die_perror("waitpid"); 871 e2 = rcheck(wstatus, "client"); 872 873 return e1 ? e1 : e2; 874 } 875