|
Lines 42-47
Link Here
|
| 42 |
#include <string.h> |
42 |
#include <string.h> |
| 43 |
#include <unistd.h> |
43 |
#include <unistd.h> |
| 44 |
|
44 |
|
|
|
45 |
#ifdef HAVE_LINUX_IN6_H |
| 46 |
#include <linux/in6.h> |
| 47 |
#endif |
| 48 |
|
| 45 |
#include "xmalloc.h" |
49 |
#include "xmalloc.h" |
| 46 |
#include "key.h" |
50 |
#include "key.h" |
| 47 |
#include "hostfile.h" |
51 |
#include "hostfile.h" |
|
Lines 267-272
ssh_kill_proxy_command(void)
Link Here
|
| 267 |
kill(proxy_command_pid, SIGHUP); |
271 |
kill(proxy_command_pid, SIGHUP); |
| 268 |
} |
272 |
} |
| 269 |
|
273 |
|
|
|
274 |
static int |
| 275 |
set_v6_bindpref(int sock, const char *op) |
| 276 |
{ |
| 277 |
#if defined(IPV6_ADDR_PREFERENCES) && defined(IPV6_PREFER_SRC_PUBLIC) && \ |
| 278 |
defined(IPV6_PREFER_SRC_TMP) && defined(IPV6_PREFER_SRC_PUBTMP_DEFAULT) |
| 279 |
int val, add, del; |
| 280 |
socklen_t len = sizeof(val); |
| 281 |
|
| 282 |
if (strcasecmp(op, "%public") == 0 || |
| 283 |
strcasecmp(op, "%pub") == 0) { |
| 284 |
add = IPV6_PREFER_SRC_PUBLIC; |
| 285 |
del = IPV6_PREFER_SRC_TMP|IPV6_PREFER_SRC_PUBTMP_DEFAULT; |
| 286 |
} else if (strcasecmp(op, "%temporary") == 0 || |
| 287 |
strcasecmp(op, "%temp") == 0 || |
| 288 |
strcasecmp(op, "%tmp") == 0) { |
| 289 |
add = IPV6_PREFER_SRC_TMP; |
| 290 |
del = IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_PUBTMP_DEFAULT; |
| 291 |
} else |
| 292 |
return 0; |
| 293 |
|
| 294 |
debug("%s: setting IPV6_ADDR_PREFERENCES to %s", __func__, op+1); |
| 295 |
|
| 296 |
if (getsockopt(sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, |
| 297 |
&val, &len) != 0) { |
| 298 |
debug("%s: getsockopt: %s", __func__, strerror(errno)); |
| 299 |
return -1; |
| 300 |
} |
| 301 |
val = (val & ~del) | add; |
| 302 |
if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, |
| 303 |
&val, len) != 0) { |
| 304 |
debug("%s: getsockopt: %s", __func__, strerror(errno)); |
| 305 |
return -1; |
| 306 |
} |
| 307 |
return 1; |
| 308 |
#else |
| 309 |
/* Silently eat operations on hosts that lack support */ |
| 310 |
if (strcasecmp(op, "%public") == 0 || |
| 311 |
strcasecmp(op, "%pub") == 0 || |
| 312 |
strcasecmp(op, "%temporary") == 0 || |
| 313 |
strcasecmp(op, "%temp") == 0 || |
| 314 |
strcasecmp(op, "%tmp") == 0) |
| 315 |
return 1; |
| 316 |
return 0; |
| 317 |
#endif |
| 318 |
} |
| 319 |
|
| 270 |
/* |
320 |
/* |
| 271 |
* Creates a (possibly privileged) socket for use as the ssh connection. |
321 |
* Creates a (possibly privileged) socket for use as the ssh connection. |
| 272 |
*/ |
322 |
*/ |
|
Lines 275-280
ssh_create_socket(int privileged, struct addrinfo *ai)
Link Here
|
| 275 |
{ |
325 |
{ |
| 276 |
int sock, r, gaierr; |
326 |
int sock, r, gaierr; |
| 277 |
struct addrinfo hints, *res = NULL; |
327 |
struct addrinfo hints, *res = NULL; |
|
|
328 |
const char *bind_address = options.bind_address; |
| 278 |
|
329 |
|
| 279 |
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
330 |
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
| 280 |
if (sock < 0) { |
331 |
if (sock < 0) { |
|
Lines 283-301
ssh_create_socket(int privileged, struct addrinfo *ai)
Link Here
|
| 283 |
} |
334 |
} |
| 284 |
fcntl(sock, F_SETFD, FD_CLOEXEC); |
335 |
fcntl(sock, F_SETFD, FD_CLOEXEC); |
| 285 |
|
336 |
|
|
|
337 |
/* Support for IPV6_ADDR_PREFERENCES if present */ |
| 338 |
if (ai->ai_family == AF_INET6 && bind_address != NULL) { |
| 339 |
if (set_v6_bindpref(sock, bind_address) != 0) { |
| 340 |
/* Skip explicit bind(2) below */ |
| 341 |
bind_address = NULL; |
| 342 |
} |
| 343 |
} |
| 344 |
|
| 286 |
/* Bind the socket to an alternative local IP address */ |
345 |
/* Bind the socket to an alternative local IP address */ |
| 287 |
if (options.bind_address == NULL && !privileged) |
346 |
if (bind_address == NULL && !privileged) |
| 288 |
return sock; |
347 |
return sock; |
| 289 |
|
348 |
|
| 290 |
if (options.bind_address) { |
349 |
if (bind_address) { |
| 291 |
memset(&hints, 0, sizeof(hints)); |
350 |
memset(&hints, 0, sizeof(hints)); |
| 292 |
hints.ai_family = ai->ai_family; |
351 |
hints.ai_family = ai->ai_family; |
| 293 |
hints.ai_socktype = ai->ai_socktype; |
352 |
hints.ai_socktype = ai->ai_socktype; |
| 294 |
hints.ai_protocol = ai->ai_protocol; |
353 |
hints.ai_protocol = ai->ai_protocol; |
| 295 |
hints.ai_flags = AI_PASSIVE; |
354 |
hints.ai_flags = AI_PASSIVE; |
| 296 |
gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res); |
355 |
gaierr = getaddrinfo(bind_address, NULL, &hints, &res); |
| 297 |
if (gaierr) { |
356 |
if (gaierr) { |
| 298 |
error("getaddrinfo: %s: %s", options.bind_address, |
357 |
error("getaddrinfo: %s: %s", bind_address, |
| 299 |
ssh_gai_strerror(gaierr)); |
358 |
ssh_gai_strerror(gaierr)); |
| 300 |
close(sock); |
359 |
close(sock); |
| 301 |
return -1; |
360 |
return -1; |
|
Lines 316-323
ssh_create_socket(int privileged, struct addrinfo *ai)
Link Here
|
| 316 |
} |
375 |
} |
| 317 |
} else { |
376 |
} else { |
| 318 |
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { |
377 |
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { |
| 319 |
error("bind: %s: %s", options.bind_address, |
378 |
error("bind: %s: %s", bind_address, strerror(errno)); |
| 320 |
strerror(errno)); |
|
|
| 321 |
fail: |
379 |
fail: |
| 322 |
close(sock); |
380 |
close(sock); |
| 323 |
freeaddrinfo(res); |
381 |
freeaddrinfo(res); |