#include #include #include #include #include #include #include #include #include #include int do_connect(int s, const char* destaddr, unsigned short destport) { struct sockaddr_in6 sa; socklen_t len; int rc; len = sizeof(struct sockaddr_in6); memset(&sa, 0, len); sa.sin6_family = AF_INET6; if (inet_pton(AF_INET6, destaddr, &sa.sin6_addr) <= 0) { printf("inet_pton failed\n"); exit(1); } sa.sin6_port = htons(destport); rc = connect(s, (struct sockaddr*)&sa, len); if (rc == -1 && errno == EINPROGRESS) { fd_set fds; FD_ZERO(&fds); FD_SET(s, &fds); do { rc = select(s+1, NULL, &fds, NULL, NULL); } while (rc == -1 && errno == EINTR); if (rc != 1) { printf("select failed\n"); exit(1); } len = sizeof(rc); if (getsockopt(s, SOL_SOCKET, SO_ERROR, &rc, &len) != 0) { printf("get SO_ERROR failed\n"); exit(1); } printf("async connect to %s returned %s\n", destaddr, strerror(rc)); return rc; } printf("sync connect to %s returned %s\n", destaddr, strerror(errno)); return errno; } int main(int argc, char** argv) { int s; int rc; int tmp; if (argc != 5) { printf("usage: %s \n", argv[0]); exit(1); } s = socket(AF_INET6, SOCK_STREAM, 0); if (s == -1) { perror("socket"); exit(1); } tmp = atoi(argv[4]); ioctl(s, FIONBIO, &tmp); /* attempt v6 connect, verify EHOSTUNREACH */ rc = do_connect(s, argv[1], atoi(argv[3])); if (rc == 0) { exit(1); } /* attempt v4 connect, 2.6.x returns ECONNABORTED */ rc = do_connect(s, argv[2], atoi(argv[3])); if (rc == 0) { exit(1); } /* retry, verify success */ rc = do_connect(s, argv[2], atoi(argv[3])); if (rc == 0) { exit(1); } close(s); return 0; }