diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 67 |
1 files changed, 58 insertions, 9 deletions
diff --git a/channels.c b/channels.c index f6e9b4d8c..7791febd7 100644 --- a/channels.c +++ b/channels.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.315 2011/09/23 07:45:05 markus Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.318 2012/04/23 08:18:17 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 |
@@ -311,6 +311,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, | |||
311 | c->istate = CHAN_INPUT_OPEN; | 311 | c->istate = CHAN_INPUT_OPEN; |
312 | c->flags = 0; | 312 | c->flags = 0; |
313 | channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0); | 313 | channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0); |
314 | c->notbefore = 0; | ||
314 | c->self = found; | 315 | c->self = found; |
315 | c->type = type; | 316 | c->type = type; |
316 | c->ctype = ctype; | 317 | c->ctype = ctype; |
@@ -1339,6 +1340,8 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1339 | } | 1340 | } |
1340 | if (newsock < 0) { | 1341 | if (newsock < 0) { |
1341 | error("accept: %.100s", strerror(errno)); | 1342 | error("accept: %.100s", strerror(errno)); |
1343 | if (errno == EMFILE || errno == ENFILE) | ||
1344 | c->notbefore = time(NULL) + 1; | ||
1342 | return; | 1345 | return; |
1343 | } | 1346 | } |
1344 | set_nodelay(newsock); | 1347 | set_nodelay(newsock); |
@@ -1482,6 +1485,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1482 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | 1485 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); |
1483 | if (newsock < 0) { | 1486 | if (newsock < 0) { |
1484 | error("accept: %.100s", strerror(errno)); | 1487 | error("accept: %.100s", strerror(errno)); |
1488 | if (errno == EMFILE || errno == ENFILE) | ||
1489 | c->notbefore = time(NULL) + 1; | ||
1485 | return; | 1490 | return; |
1486 | } | 1491 | } |
1487 | set_nodelay(newsock); | 1492 | set_nodelay(newsock); |
@@ -1514,7 +1519,10 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1514 | addrlen = sizeof(addr); | 1519 | addrlen = sizeof(addr); |
1515 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | 1520 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); |
1516 | if (newsock < 0) { | 1521 | if (newsock < 0) { |
1517 | error("accept from auth socket: %.100s", strerror(errno)); | 1522 | error("accept from auth socket: %.100s", |
1523 | strerror(errno)); | ||
1524 | if (errno == EMFILE || errno == ENFILE) | ||
1525 | c->notbefore = time(NULL) + 1; | ||
1518 | return; | 1526 | return; |
1519 | } | 1527 | } |
1520 | nc = channel_new("accepted auth socket", | 1528 | nc = channel_new("accepted auth socket", |
@@ -1917,6 +1925,8 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1917 | if ((newsock = accept(c->sock, (struct sockaddr*)&addr, | 1925 | if ((newsock = accept(c->sock, (struct sockaddr*)&addr, |
1918 | &addrlen)) == -1) { | 1926 | &addrlen)) == -1) { |
1919 | error("%s accept: %s", __func__, strerror(errno)); | 1927 | error("%s accept: %s", __func__, strerror(errno)); |
1928 | if (errno == EMFILE || errno == ENFILE) | ||
1929 | c->notbefore = time(NULL) + 1; | ||
1920 | return; | 1930 | return; |
1921 | } | 1931 | } |
1922 | 1932 | ||
@@ -2067,16 +2077,21 @@ channel_garbage_collect(Channel *c) | |||
2067 | } | 2077 | } |
2068 | 2078 | ||
2069 | static void | 2079 | static void |
2070 | channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset) | 2080 | channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset, |
2081 | time_t *unpause_secs) | ||
2071 | { | 2082 | { |
2072 | static int did_init = 0; | 2083 | static int did_init = 0; |
2073 | u_int i, oalloc; | 2084 | u_int i, oalloc; |
2074 | Channel *c; | 2085 | Channel *c; |
2086 | time_t now; | ||
2075 | 2087 | ||
2076 | if (!did_init) { | 2088 | if (!did_init) { |
2077 | channel_handler_init(); | 2089 | channel_handler_init(); |
2078 | did_init = 1; | 2090 | did_init = 1; |
2079 | } | 2091 | } |
2092 | now = time(NULL); | ||
2093 | if (unpause_secs != NULL) | ||
2094 | *unpause_secs = 0; | ||
2080 | for (i = 0, oalloc = channels_alloc; i < oalloc; i++) { | 2095 | for (i = 0, oalloc = channels_alloc; i < oalloc; i++) { |
2081 | c = channels[i]; | 2096 | c = channels[i]; |
2082 | if (c == NULL) | 2097 | if (c == NULL) |
@@ -2087,10 +2102,30 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset) | |||
2087 | else | 2102 | else |
2088 | continue; | 2103 | continue; |
2089 | } | 2104 | } |
2090 | if (ftab[c->type] != NULL) | 2105 | if (ftab[c->type] != NULL) { |
2091 | (*ftab[c->type])(c, readset, writeset); | 2106 | /* |
2107 | * Run handlers that are not paused. | ||
2108 | */ | ||
2109 | if (c->notbefore <= now) | ||
2110 | (*ftab[c->type])(c, readset, writeset); | ||
2111 | else if (unpause_secs != NULL) { | ||
2112 | /* | ||
2113 | * Collect the time that the earliest | ||
2114 | * channel comes off pause. | ||
2115 | */ | ||
2116 | debug3("%s: chan %d: skip for %d more seconds", | ||
2117 | __func__, c->self, | ||
2118 | (int)(c->notbefore - now)); | ||
2119 | if (*unpause_secs == 0 || | ||
2120 | (c->notbefore - now) < *unpause_secs) | ||
2121 | *unpause_secs = c->notbefore - now; | ||
2122 | } | ||
2123 | } | ||
2092 | channel_garbage_collect(c); | 2124 | channel_garbage_collect(c); |
2093 | } | 2125 | } |
2126 | if (unpause_secs != NULL && *unpause_secs != 0) | ||
2127 | debug3("%s: first channel unpauses in %d seconds", | ||
2128 | __func__, (int)*unpause_secs); | ||
2094 | } | 2129 | } |
2095 | 2130 | ||
2096 | /* | 2131 | /* |
@@ -2099,7 +2134,7 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset) | |||
2099 | */ | 2134 | */ |
2100 | void | 2135 | void |
2101 | channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | 2136 | channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, |
2102 | u_int *nallocp, int rekeying) | 2137 | u_int *nallocp, time_t *minwait_secs, int rekeying) |
2103 | { | 2138 | { |
2104 | u_int n, sz, nfdset; | 2139 | u_int n, sz, nfdset; |
2105 | 2140 | ||
@@ -2122,7 +2157,8 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | |||
2122 | memset(*writesetp, 0, sz); | 2157 | memset(*writesetp, 0, sz); |
2123 | 2158 | ||
2124 | if (!rekeying) | 2159 | if (!rekeying) |
2125 | channel_handler(channel_pre, *readsetp, *writesetp); | 2160 | channel_handler(channel_pre, *readsetp, *writesetp, |
2161 | minwait_secs); | ||
2126 | } | 2162 | } |
2127 | 2163 | ||
2128 | /* | 2164 | /* |
@@ -2132,7 +2168,7 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | |||
2132 | void | 2168 | void |
2133 | channel_after_select(fd_set *readset, fd_set *writeset) | 2169 | channel_after_select(fd_set *readset, fd_set *writeset) |
2134 | { | 2170 | { |
2135 | channel_handler(channel_post, readset, writeset); | 2171 | channel_handler(channel_post, readset, writeset, NULL); |
2136 | } | 2172 | } |
2137 | 2173 | ||
2138 | 2174 | ||
@@ -3127,6 +3163,17 @@ channel_add_adm_permitted_opens(char *host, int port) | |||
3127 | } | 3163 | } |
3128 | 3164 | ||
3129 | void | 3165 | void |
3166 | channel_disable_adm_local_opens(void) | ||
3167 | { | ||
3168 | if (num_adm_permitted_opens == 0) { | ||
3169 | permitted_adm_opens = xmalloc(sizeof(*permitted_adm_opens)); | ||
3170 | permitted_adm_opens[num_adm_permitted_opens].host_to_connect | ||
3171 | = NULL; | ||
3172 | num_adm_permitted_opens = 1; | ||
3173 | } | ||
3174 | } | ||
3175 | |||
3176 | void | ||
3130 | channel_clear_permitted_opens(void) | 3177 | channel_clear_permitted_opens(void) |
3131 | { | 3178 | { |
3132 | int i; | 3179 | int i; |
@@ -3167,7 +3214,9 @@ channel_print_adm_permitted_opens(void) | |||
3167 | return; | 3214 | return; |
3168 | } | 3215 | } |
3169 | for (i = 0; i < num_adm_permitted_opens; i++) | 3216 | for (i = 0; i < num_adm_permitted_opens; i++) |
3170 | if (permitted_adm_opens[i].host_to_connect != NULL) | 3217 | if (permitted_adm_opens[i].host_to_connect == NULL) |
3218 | printf(" none"); | ||
3219 | else | ||
3171 | printf(" %s:%d", permitted_adm_opens[i].host_to_connect, | 3220 | printf(" %s:%d", permitted_adm_opens[i].host_to_connect, |
3172 | permitted_adm_opens[i].port_to_connect); | 3221 | permitted_adm_opens[i].port_to_connect); |
3173 | printf("\n"); | 3222 | printf("\n"); |