version 1.81, 2010/09/03 03:49:37 |
version 1.82, 2012/04/30 13:41:26 |
|
|
{ |
{ |
int s, tos, error; |
int s, tos, error; |
static char hostnamebuf[MAXHOSTNAMELEN]; |
static char hostnamebuf[MAXHOSTNAMELEN]; |
struct addrinfo hints, *res, *res0; |
struct addrinfo hints, *res, *res0, *ares; |
char hbuf[NI_MAXHOST]; |
char hbuf[NI_MAXHOST]; |
char *cause = "unknown"; |
char *cause = "unknown"; |
socklen_t namelen; |
socklen_t namelen; |
|
|
else |
else |
strlcpy(hostnamebuf, host, sizeof(hostnamebuf)); |
strlcpy(hostnamebuf, host, sizeof(hostnamebuf)); |
hostname = hostnamebuf; |
hostname = hostnamebuf; |
|
|
|
#ifndef SMALL |
|
if (srcaddr) { |
|
struct addrinfo ahints; |
|
|
|
memset(&ahints, 0, sizeof(ahints)); |
|
ahints.ai_family = family; |
|
ahints.ai_socktype = SOCK_STREAM; |
|
ahints.ai_flags |= AI_NUMERICHOST; |
|
ahints.ai_protocol = 0; |
|
|
|
error = getaddrinfo(srcaddr, NULL, &ahints, &ares); |
|
if (error) { |
|
warnx("%s: %s", gai_strerror(error), srcaddr); |
|
code = -1; |
|
return (0); |
|
} |
|
} |
|
#endif /* !SMALL */ |
|
|
s = -1; |
s = -1; |
for (res = res0; res; res = res->ai_next) { |
for (res = res0; res; res = res->ai_next) { |
|
|
cause = "socket"; |
cause = "socket"; |
continue; |
continue; |
} |
} |
|
#ifndef SMALL |
|
if (srcaddr) { |
|
if (ares->ai_family != res->ai_family) { |
|
close(s); |
|
s = -1; |
|
errno = EINVAL; |
|
cause = "bind"; |
|
continue; |
|
} |
|
if (bind(s, ares->ai_addr, ares->ai_addrlen) < 0) { |
|
cause = "bind"; |
|
error = errno; |
|
close(s); |
|
errno = error; |
|
s = -1; |
|
continue; |
|
} |
|
} |
|
#endif /* !SMALL */ |
while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0 |
while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0 |
&& errno == EINTR) { |
&& errno == EINTR) { |
; |
; |
|
|
namelen = res->ai_addrlen; |
namelen = res->ai_addrlen; |
freeaddrinfo(res0); |
freeaddrinfo(res0); |
res0 = res = NULL; |
res0 = res = NULL; |
|
#ifndef SMALL |
|
if (srcaddr) { |
|
freeaddrinfo(ares); |
|
ares = NULL; |
|
} |
|
#endif /* !SMALL */ |
if (getsockname(s, (struct sockaddr *)&myctladdr, &namelen) < 0) { |
if (getsockname(s, (struct sockaddr *)&myctladdr, &namelen) < 0) { |
warn("getsockname"); |
warn("getsockname"); |
code = -1; |
code = -1; |
|
|
u_int af, hal, pal; |
u_int af, hal, pal; |
char *pasvcmd = NULL; |
char *pasvcmd = NULL; |
socklen_t namelen; |
socklen_t namelen; |
|
struct addrinfo *ares; |
|
|
if (myctladdr.su_family == AF_INET6 |
if (myctladdr.su_family == AF_INET6 |
&& (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr) |
&& (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr) |
|| IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) { |
|| IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) { |
warnx("use of scoped address can be troublesome"); |
warnx("use of scoped address can be troublesome"); |
} |
} |
|
#ifndef SMALL |
|
if (srcaddr) { |
|
struct addrinfo ahints; |
|
|
|
memset(&ahints, 0, sizeof(ahints)); |
|
ahints.ai_family = family; |
|
ahints.ai_socktype = SOCK_STREAM; |
|
ahints.ai_flags |= AI_NUMERICHOST; |
|
ahints.ai_protocol = 0; |
|
|
|
error = getaddrinfo(srcaddr, NULL, &ahints, &ares); |
|
if (error) { |
|
warnx("%s: %s", gai_strerror(error), srcaddr); |
|
code = -1; |
|
return (0); |
|
} |
|
} |
|
#endif /* !SMALL */ |
reinit: |
reinit: |
if (passivemode) { |
if (passivemode) { |
data_addr = myctladdr; |
data_addr = myctladdr; |
|
|
return (1); |
return (1); |
} |
} |
#ifndef SMALL |
#ifndef SMALL |
|
if (srcaddr) { |
|
if (bind(data, ares->ai_addr, ares->ai_addrlen) < 0) { |
|
warn("bind"); |
|
close(data); |
|
return (1); |
|
} |
|
} |
if ((options & SO_DEBUG) && |
if ((options & SO_DEBUG) && |
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, |
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, |
sizeof(on)) < 0) |
sizeof(on)) < 0) |