diff options
author | Damien Miller <djm@mindrot.org> | 2009-02-14 16:28:21 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2009-02-14 16:28:21 +1100 |
commit | 4bf648f7766ba764d7a78b1dbb26df4f0d42a8c9 (patch) | |
tree | cc576e28218cb3ad9617a12eabe68c21a7e09614 /channels.c | |
parent | fdd66fc750228b5d040c45bc36565299374b72c8 (diff) |
- djm@cvs.openbsd.org 2009/02/12 03:00:56
[canohost.c canohost.h channels.c channels.h clientloop.c readconf.c]
[readconf.h serverloop.c ssh.c]
support remote port forwarding with a zero listen port (-R0:...) to
dyamically allocate a listen port at runtime (this is actually
specified in rfc4254); bz#1003 ok markus@
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/channels.c b/channels.c index 0b1c34c83..dea60ba24 100644 --- a/channels.c +++ b/channels.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.294 2009/01/22 09:49:57 djm Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.295 2009/02/12 03:00:56 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -2460,7 +2460,8 @@ channel_set_af(int af) | |||
2460 | } | 2460 | } |
2461 | 2461 | ||
2462 | static int | 2462 | static int |
2463 | channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port, | 2463 | channel_setup_fwd_listener(int type, const char *listen_addr, |
2464 | u_short listen_port, int *allocated_listen_port, | ||
2464 | const char *host_to_connect, u_short port_to_connect, int gateway_ports) | 2465 | const char *host_to_connect, u_short port_to_connect, int gateway_ports) |
2465 | { | 2466 | { |
2466 | Channel *c; | 2467 | Channel *c; |
@@ -2468,6 +2469,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por | |||
2468 | struct addrinfo hints, *ai, *aitop; | 2469 | struct addrinfo hints, *ai, *aitop; |
2469 | const char *host, *addr; | 2470 | const char *host, *addr; |
2470 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 2471 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
2472 | in_port_t *lport_p; | ||
2471 | 2473 | ||
2472 | host = (type == SSH_CHANNEL_RPORT_LISTENER) ? | 2474 | host = (type == SSH_CHANNEL_RPORT_LISTENER) ? |
2473 | listen_addr : host_to_connect; | 2475 | listen_addr : host_to_connect; |
@@ -2536,10 +2538,29 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por | |||
2536 | } | 2538 | } |
2537 | return 0; | 2539 | return 0; |
2538 | } | 2540 | } |
2539 | 2541 | if (allocated_listen_port != NULL) | |
2542 | *allocated_listen_port = 0; | ||
2540 | for (ai = aitop; ai; ai = ai->ai_next) { | 2543 | for (ai = aitop; ai; ai = ai->ai_next) { |
2541 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | 2544 | switch (ai->ai_family) { |
2545 | case AF_INET: | ||
2546 | lport_p = &((struct sockaddr_in *)ai->ai_addr)-> | ||
2547 | sin_port; | ||
2548 | break; | ||
2549 | case AF_INET6: | ||
2550 | lport_p = &((struct sockaddr_in6 *)ai->ai_addr)-> | ||
2551 | sin6_port; | ||
2552 | break; | ||
2553 | default: | ||
2542 | continue; | 2554 | continue; |
2555 | } | ||
2556 | /* | ||
2557 | * If allocating a port for -R forwards, then use the | ||
2558 | * same port for all address families. | ||
2559 | */ | ||
2560 | if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && | ||
2561 | allocated_listen_port != NULL && *allocated_listen_port > 0) | ||
2562 | *lport_p = htons(*allocated_listen_port); | ||
2563 | |||
2543 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), | 2564 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), |
2544 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | 2565 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { |
2545 | error("channel_setup_fwd_listener: getnameinfo failed"); | 2566 | error("channel_setup_fwd_listener: getnameinfo failed"); |
@@ -2555,7 +2576,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por | |||
2555 | 2576 | ||
2556 | channel_set_reuseaddr(sock); | 2577 | channel_set_reuseaddr(sock); |
2557 | 2578 | ||
2558 | debug("Local forwarding listening on %s port %s.", ntop, strport); | 2579 | debug("Local forwarding listening on %s port %s.", |
2580 | ntop, strport); | ||
2559 | 2581 | ||
2560 | /* Bind the socket to the address. */ | 2582 | /* Bind the socket to the address. */ |
2561 | if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { | 2583 | if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
@@ -2574,6 +2596,19 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por | |||
2574 | close(sock); | 2596 | close(sock); |
2575 | continue; | 2597 | continue; |
2576 | } | 2598 | } |
2599 | |||
2600 | /* | ||
2601 | * listen_port == 0 requests a dynamically allocated port - | ||
2602 | * record what we got. | ||
2603 | */ | ||
2604 | if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && | ||
2605 | allocated_listen_port != NULL && | ||
2606 | *allocated_listen_port == 0) { | ||
2607 | *allocated_listen_port = get_sock_port(sock, 1); | ||
2608 | debug("Allocated listen port %d", | ||
2609 | *allocated_listen_port); | ||
2610 | } | ||
2611 | |||
2577 | /* Allocate a channel number for the socket. */ | 2612 | /* Allocate a channel number for the socket. */ |
2578 | c = channel_new("port listener", type, sock, sock, -1, | 2613 | c = channel_new("port listener", type, sock, sock, -1, |
2579 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | 2614 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
@@ -2616,17 +2651,18 @@ channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, | |||
2616 | const char *host_to_connect, u_short port_to_connect, int gateway_ports) | 2651 | const char *host_to_connect, u_short port_to_connect, int gateway_ports) |
2617 | { | 2652 | { |
2618 | return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, | 2653 | return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, |
2619 | listen_host, listen_port, host_to_connect, port_to_connect, | 2654 | listen_host, listen_port, NULL, host_to_connect, port_to_connect, |
2620 | gateway_ports); | 2655 | gateway_ports); |
2621 | } | 2656 | } |
2622 | 2657 | ||
2623 | /* protocol v2 remote port fwd, used by sshd */ | 2658 | /* protocol v2 remote port fwd, used by sshd */ |
2624 | int | 2659 | int |
2625 | channel_setup_remote_fwd_listener(const char *listen_address, | 2660 | channel_setup_remote_fwd_listener(const char *listen_address, |
2626 | u_short listen_port, int gateway_ports) | 2661 | u_short listen_port, int *allocated_listen_port, int gateway_ports) |
2627 | { | 2662 | { |
2628 | return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, | 2663 | return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, |
2629 | listen_address, listen_port, NULL, 0, gateway_ports); | 2664 | listen_address, listen_port, allocated_listen_port, |
2665 | NULL, 0, gateway_ports); | ||
2630 | } | 2666 | } |
2631 | 2667 | ||
2632 | /* | 2668 | /* |