diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/xconnect.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/libbb/xconnect.c b/libbb/xconnect.c index f018ca9d9..81a2b048f 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c | |||
@@ -161,6 +161,7 @@ static len_and_sockaddr* str2sockaddr( | |||
161 | IF_FEATURE_IPV6(sa_family_t af,) | 161 | IF_FEATURE_IPV6(sa_family_t af,) |
162 | int ai_flags) | 162 | int ai_flags) |
163 | { | 163 | { |
164 | IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;) | ||
164 | int rc; | 165 | int rc; |
165 | len_and_sockaddr *r; | 166 | len_and_sockaddr *r; |
166 | struct addrinfo *result = NULL; | 167 | struct addrinfo *result = NULL; |
@@ -221,12 +222,40 @@ IF_FEATURE_IPV6(sa_family_t af,) | |||
221 | skip: ; | 222 | skip: ; |
222 | } | 223 | } |
223 | 224 | ||
225 | /* Next two if blocks allow to skip getaddrinfo() | ||
226 | * in case host is a numeric IP(v6) address, | ||
227 | * getaddrinfo() initializes DNS resolution machinery, | ||
228 | * scans network config and such - tens of syscalls. | ||
229 | */ | ||
230 | /* If we were not asked specifically for IPv6, | ||
231 | * check whether this is a numeric IPv4 */ | ||
232 | IF_FEATURE_IPV6(if(af != AF_INET6)) { | ||
233 | struct in_addr in4; | ||
234 | if (inet_aton(host, &in4) != 0) { | ||
235 | r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_in)); | ||
236 | r->len = sizeof(struct sockaddr_in); | ||
237 | r->u.sa.sa_family = AF_INET; | ||
238 | r->u.sin.sin_addr = in4; | ||
239 | goto set_port; | ||
240 | } | ||
241 | } | ||
242 | #if ENABLE_FEATURE_IPV6 | ||
243 | /* If we were not asked specifically for IPv4, | ||
244 | * check whether this is a numeric IPv6 */ | ||
245 | if (af != AF_INET) { | ||
246 | struct in6_addr in6; | ||
247 | if (inet_pton(AF_INET6, host, &in6) > 0) { | ||
248 | r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_in6)); | ||
249 | r->len = sizeof(struct sockaddr_in6); | ||
250 | r->u.sa.sa_family = AF_INET6; | ||
251 | r->u.sin6.sin6_addr = in6; | ||
252 | goto set_port; | ||
253 | } | ||
254 | } | ||
255 | #endif | ||
256 | |||
224 | memset(&hint, 0 , sizeof(hint)); | 257 | memset(&hint, 0 , sizeof(hint)); |
225 | #if !ENABLE_FEATURE_IPV6 | ||
226 | hint.ai_family = AF_INET; /* do not try to find IPv6 */ | ||
227 | #else | ||
228 | hint.ai_family = af; | 258 | hint.ai_family = af; |
229 | #endif | ||
230 | /* Needed. Or else we will get each address thrice (or more) | 259 | /* Needed. Or else we will get each address thrice (or more) |
231 | * for each possible socket type (tcp,udp,raw...): */ | 260 | * for each possible socket type (tcp,udp,raw...): */ |
232 | hint.ai_socktype = SOCK_STREAM; | 261 | hint.ai_socktype = SOCK_STREAM; |
@@ -250,9 +279,11 @@ IF_FEATURE_IPV6(sa_family_t af,) | |||
250 | } | 279 | } |
251 | } | 280 | } |
252 | #endif | 281 | #endif |
253 | r = xmalloc(offsetof(len_and_sockaddr, u.sa) + used_res->ai_addrlen); | 282 | r = xmalloc(LSA_LEN_SIZE + used_res->ai_addrlen); |
254 | r->len = used_res->ai_addrlen; | 283 | r->len = used_res->ai_addrlen; |
255 | memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen); | 284 | memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen); |
285 | |||
286 | IF_FEATURE_IPV6(set_port:) | ||
256 | set_nport(r, htons(port)); | 287 | set_nport(r, htons(port)); |
257 | ret: | 288 | ret: |
258 | freeaddrinfo(result); | 289 | freeaddrinfo(result); |