| 1 | diff --git a/connect.c b/connect.c |
| 2 | --- a/connect.c |
| 3 | +++ b/connect.c |
| 4 | @@ -96,42 +96,57 @@ static enum protocol get_protocol(const |
| 5 | die("I don't handle protocol '%s'", name); |
| 6 | } |
| 7 | |
| 8 | -static void lookup_host(const char *host, struct sockaddr *in) |
| 9 | -{ |
| 10 | - struct addrinfo *res; |
| 11 | - int ret; |
| 12 | - |
| 13 | - ret = getaddrinfo(host, NULL, NULL, &res); |
| 14 | - if (ret) |
| 15 | - die("Unable to look up %s (%s)", host, gai_strerror(ret)); |
| 16 | - *in = *res->ai_addr; |
| 17 | - freeaddrinfo(res); |
| 18 | -} |
| 19 | +#define STR_(s) # s |
| 20 | +#define STR(s) STR_(s) |
| 21 | |
| 22 | static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) |
| 23 | { |
| 24 | - struct sockaddr addr; |
| 25 | - int port = DEFAULT_GIT_PORT, sockfd; |
| 26 | - char *colon; |
| 27 | - |
| 28 | - colon = strchr(host, ':'); |
| 29 | - if (colon) { |
| 30 | - char *end; |
| 31 | - unsigned long n = strtoul(colon+1, &end, 0); |
| 32 | - if (colon[1] && !*end) { |
| 33 | - *colon = 0; |
| 34 | - port = n; |
| 35 | + int sockfd = -1; |
| 36 | + char *colon, *end; |
| 37 | + char *port = STR(DEFAULT_GIT_PORT); |
| 38 | + struct addrinfo hints, *ai0, *ai; |
| 39 | + int gai; |
| 40 | + |
| 41 | + if (host[0] == '[') { |
| 42 | + end = strchr(host + 1, ']'); |
| 43 | + if (end) { |
| 44 | + *end = 0; |
| 45 | + end++; |
| 46 | + host++; |
| 47 | + } else |
| 48 | + end = host; |
| 49 | + } else |
| 50 | + end = host; |
| 51 | + colon = strchr(end, ':'); |
| 52 | + |
| 53 | + if (colon) |
| 54 | + port = colon + 1; |
| 55 | + |
| 56 | + memset(&hints, 0, sizeof(hints)); |
| 57 | + hints.ai_socktype = SOCK_STREAM; |
| 58 | + hints.ai_protocol = IPPROTO_TCP; |
| 59 | + |
| 60 | + gai = getaddrinfo(host, port, &hints, &ai); |
| 61 | + if (gai) |
| 62 | + die("Unable to look up %s (%s)", host, gai_strerror(gai)); |
| 63 | + |
| 64 | + for (ai0 = ai; ai; ai = ai->ai_next) { |
| 65 | + sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
| 66 | + if (sockfd < 0) |
| 67 | + continue; |
| 68 | + if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { |
| 69 | + close(sockfd); |
| 70 | + sockfd = -1; |
| 71 | + continue; |
| 72 | } |
| 73 | + break; |
| 74 | } |
| 75 | |
| 76 | - lookup_host(host, &addr); |
| 77 | - ((struct sockaddr_in *)&addr)->sin_port = htons(port); |
| 78 | + freeaddrinfo(ai0); |
| 79 | |
| 80 | - sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP); |
| 81 | if (sockfd < 0) |
| 82 | die("unable to create socket (%s)", strerror(errno)); |
| 83 | - if (connect(sockfd, (void *)&addr, sizeof(addr)) < 0) |
| 84 | - die("unable to connect (%s)", strerror(errno)); |
| 85 | + |
| 86 | fd[0] = sockfd; |
| 87 | fd[1] = sockfd; |
| 88 | packet_write(sockfd, "%s %s\n", prog, path); |
| 89 | |
| 90 | -- |
| 91 | YOSHIFUJI Hideaki @ USAGI Project <yoshfuji@linux-ipv6.org> |
| 92 | GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA |
| 93 |