|
Lines 323-336
check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs,
Link Here
|
| 323 |
|
323 |
|
| 324 |
/* |
324 |
/* |
| 325 |
* Creates a (possibly privileged) socket for use as the ssh connection. |
325 |
* Creates a (possibly privileged) socket for use as the ssh connection. |
|
|
326 |
* Returns socket on success. |
| 327 |
* On failure, returns -1 and either logs the error or sets errno. |
| 326 |
*/ |
328 |
*/ |
| 327 |
static int |
329 |
static int |
| 328 |
ssh_create_socket(int privileged, struct addrinfo *ai) |
330 |
ssh_create_socket(int privileged, struct addrinfo *ai) |
| 329 |
{ |
331 |
{ |
| 330 |
int sock, r, oerrno; |
332 |
int sock, r, oerrno, fail_errno = 0; |
| 331 |
struct sockaddr_storage bindaddr; |
333 |
struct sockaddr_storage bindaddr; |
| 332 |
socklen_t bindaddrlen = 0; |
334 |
socklen_t bindaddrlen = 0; |
| 333 |
struct addrinfo hints, *res = NULL; |
335 |
struct addrinfo hints, *res = NULL, *bind_ai; |
| 334 |
struct ifaddrs *ifaddrs = NULL; |
336 |
struct ifaddrs *ifaddrs = NULL; |
| 335 |
char ntop[NI_MAXHOST]; |
337 |
char ntop[NI_MAXHOST]; |
| 336 |
|
338 |
|
|
Lines 348-354
ssh_create_socket(int privileged, struct addrinfo *ai)
Link Here
|
| 348 |
|
350 |
|
| 349 |
if (options.bind_address != NULL) { |
351 |
if (options.bind_address != NULL) { |
| 350 |
memset(&hints, 0, sizeof(hints)); |
352 |
memset(&hints, 0, sizeof(hints)); |
| 351 |
hints.ai_family = ai->ai_family; |
353 |
hints.ai_family = AF_UNSPEC; |
| 352 |
hints.ai_socktype = ai->ai_socktype; |
354 |
hints.ai_socktype = ai->ai_socktype; |
| 353 |
hints.ai_protocol = ai->ai_protocol; |
355 |
hints.ai_protocol = ai->ai_protocol; |
| 354 |
hints.ai_flags = AI_PASSIVE; |
356 |
hints.ai_flags = AI_PASSIVE; |
|
Lines 358-384
ssh_create_socket(int privileged, struct addrinfo *ai)
Link Here
|
| 358 |
ssh_gai_strerror(r)); |
360 |
ssh_gai_strerror(r)); |
| 359 |
goto fail; |
361 |
goto fail; |
| 360 |
} |
362 |
} |
| 361 |
if (res == NULL) { |
363 |
for (bind_ai = res; bind_ai != NULL; |
| 362 |
error("getaddrinfo: no addrs"); |
364 |
bind_ai = bind_ai->ai_next) { |
|
|
365 |
if (bind_ai->ai_family == ai->ai_family) |
| 366 |
break; |
| 367 |
} |
| 368 |
if (bind_ai == NULL) { |
| 369 |
debug("%s: no suitable bind address", __func__); |
| 370 |
fail_errno = EADDRNOTAVAIL; |
| 363 |
goto fail; |
371 |
goto fail; |
| 364 |
} |
372 |
} |
| 365 |
if (res->ai_addrlen > sizeof(bindaddr)) { |
373 |
if (bind_ai->ai_addrlen > sizeof(bindaddr)) { |
| 366 |
error("%s: addr doesn't fit", __func__); |
374 |
error("%s: bind address doesn't fit", __func__); |
| 367 |
goto fail; |
375 |
goto fail; |
| 368 |
} |
376 |
} |
| 369 |
memcpy(&bindaddr, res->ai_addr, res->ai_addrlen); |
377 |
memcpy(&bindaddr, bind_ai->ai_addr, bind_ai->ai_addrlen); |
| 370 |
bindaddrlen = res->ai_addrlen; |
378 |
bindaddrlen = bind_ai->ai_addrlen; |
| 371 |
} else if (options.bind_interface != NULL) { |
379 |
} else if (options.bind_interface != NULL) { |
| 372 |
if ((r = getifaddrs(&ifaddrs)) != 0) { |
380 |
if ((r = getifaddrs(&ifaddrs)) != 0) { |
| 373 |
error("getifaddrs: %s: %s", options.bind_interface, |
381 |
error("%s: BindInterface getifaddrs: %s: %s", |
| 374 |
strerror(errno)); |
382 |
__func__, options.bind_interface, strerror(errno)); |
| 375 |
goto fail; |
383 |
goto fail; |
| 376 |
} |
384 |
} |
| 377 |
bindaddrlen = sizeof(bindaddr); |
385 |
bindaddrlen = sizeof(bindaddr); |
| 378 |
if (check_ifaddrs(options.bind_interface, ai->ai_family, |
386 |
if (check_ifaddrs(options.bind_interface, ai->ai_family, |
| 379 |
ifaddrs, &bindaddr, &bindaddrlen) != 0) { |
387 |
ifaddrs, &bindaddr, &bindaddrlen) != 0) { |
| 380 |
logit("getifaddrs: %s: no suitable addresses", |
388 |
debug("%s: no suitable addresses from BindInterface %s", |
| 381 |
options.bind_interface); |
389 |
__func__, options.bind_interface); |
|
|
390 |
fail_errno = EADDRNOTAVAIL; |
| 382 |
goto fail; |
391 |
goto fail; |
| 383 |
} |
392 |
} |
| 384 |
} |
393 |
} |
|
Lines 399-406
ssh_create_socket(int privileged, struct addrinfo *ai)
Link Here
|
| 399 |
oerrno = errno; |
408 |
oerrno = errno; |
| 400 |
PRIV_END; |
409 |
PRIV_END; |
| 401 |
if (r < 0) { |
410 |
if (r < 0) { |
| 402 |
error("bindresvport_sa %s: %s", ntop, |
411 |
error("bindresvport_sa %s: %s", ntop, strerror(oerrno)); |
| 403 |
strerror(oerrno)); |
|
|
| 404 |
goto fail; |
412 |
goto fail; |
| 405 |
} |
413 |
} |
| 406 |
} else if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) { |
414 |
} else if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) { |
|
Lines 418-423
fail:
Link Here
|
| 418 |
freeaddrinfo(res); |
426 |
freeaddrinfo(res); |
| 419 |
if (ifaddrs != NULL) |
427 |
if (ifaddrs != NULL) |
| 420 |
freeifaddrs(ifaddrs); |
428 |
freeifaddrs(ifaddrs); |
|
|
429 |
errno = fail_errno; |
| 421 |
return sock; |
430 |
return sock; |
| 422 |
} |
431 |
} |
| 423 |
|
432 |
|
|
Lines 541-552
ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop,
Link Here
|
| 541 |
host, ntop, strport); |
550 |
host, ntop, strport); |
| 542 |
|
551 |
|
| 543 |
/* Create a socket for connecting. */ |
552 |
/* Create a socket for connecting. */ |
| 544 |
sock = ssh_create_socket(needpriv, ai); |
553 |
if ((sock = ssh_create_socket(needpriv, ai)) < 0) |
| 545 |
if (sock < 0) { |
|
|
| 546 |
/* Any error is already output */ |
| 547 |
errno = 0; |
| 548 |
continue; |
554 |
continue; |
| 549 |
} |
|
|
| 550 |
|
555 |
|
| 551 |
if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, |
556 |
if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, |
| 552 |
timeout_ms) >= 0) { |
557 |
timeout_ms) >= 0) { |