summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c139
1 files changed, 119 insertions, 20 deletions
diff --git a/packet.c b/packet.c
index f82a63c47..8abd43eb4 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.148 2007/06/07 19:37:34 pvalchev Exp $ */ 1/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 markus 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
@@ -136,12 +136,18 @@ static int server_side = 0;
136/* Set to true if we are authenticated. */ 136/* Set to true if we are authenticated. */
137static int after_authentication = 0; 137static int after_authentication = 0;
138 138
139int keep_alive_timeouts = 0;
140
141/* Set to the maximum time that we will wait to send or receive a packet */
142static int packet_timeout_ms = -1;
143
139/* Session key information for Encryption and MAC */ 144/* Session key information for Encryption and MAC */
140Newkeys *newkeys[MODE_MAX]; 145Newkeys *newkeys[MODE_MAX];
141static struct packet_state { 146static struct packet_state {
142 u_int32_t seqnr; 147 u_int32_t seqnr;
143 u_int32_t packets; 148 u_int32_t packets;
144 u_int64_t blocks; 149 u_int64_t blocks;
150 u_int64_t bytes;
145} p_read, p_send; 151} p_read, p_send;
146 152
147static u_int64_t max_blocks_in, max_blocks_out; 153static u_int64_t max_blocks_in, max_blocks_out;
@@ -186,7 +192,21 @@ packet_set_connection(int fd_in, int fd_out)
186 buffer_init(&outgoing_packet); 192 buffer_init(&outgoing_packet);
187 buffer_init(&incoming_packet); 193 buffer_init(&incoming_packet);
188 TAILQ_INIT(&outgoing); 194 TAILQ_INIT(&outgoing);
195 p_send.packets = p_read.packets = 0;
196 }
197}
198
199void
200packet_set_timeout(int timeout, int count)
201{
202 if (timeout == 0 || count == 0) {
203 packet_timeout_ms = -1;
204 return;
189 } 205 }
206 if ((INT_MAX / 1000) / count < timeout)
207 packet_timeout_ms = INT_MAX;
208 else
209 packet_timeout_ms = timeout * count * 1000;
190} 210}
191 211
192/* Returns 1 if remote host is connected via socket, 0 if not. */ 212/* Returns 1 if remote host is connected via socket, 0 if not. */
@@ -293,18 +313,25 @@ packet_get_ssh1_cipher(void)
293} 313}
294 314
295void 315void
296packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets) 316packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets,
317 u_int64_t *bytes)
297{ 318{
298 struct packet_state *state; 319 struct packet_state *state;
299 320
300 state = (mode == MODE_IN) ? &p_read : &p_send; 321 state = (mode == MODE_IN) ? &p_read : &p_send;
301 *seqnr = state->seqnr; 322 if (seqnr)
302 *blocks = state->blocks; 323 *seqnr = state->seqnr;
303 *packets = state->packets; 324 if (blocks)
325 *blocks = state->blocks;
326 if (packets)
327 *packets = state->packets;
328 if (bytes)
329 *bytes = state->bytes;
304} 330}
305 331
306void 332void
307packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets) 333packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets,
334 u_int64_t bytes)
308{ 335{
309 struct packet_state *state; 336 struct packet_state *state;
310 337
@@ -312,6 +339,7 @@ packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
312 state->seqnr = seqnr; 339 state->seqnr = seqnr;
313 state->blocks = blocks; 340 state->blocks = blocks;
314 state->packets = packets; 341 state->packets = packets;
342 state->bytes = bytes;
315} 343}
316 344
317/* returns 1 if connection is via ipv4 */ 345/* returns 1 if connection is via ipv4 */
@@ -590,7 +618,8 @@ packet_send1(void)
590 fprintf(stderr, "encrypted: "); 618 fprintf(stderr, "encrypted: ");
591 buffer_dump(&output); 619 buffer_dump(&output);
592#endif 620#endif
593 621 p_send.packets++;
622 p_send.bytes += len + buffer_len(&outgoing_packet);
594 buffer_clear(&outgoing_packet); 623 buffer_clear(&outgoing_packet);
595 624
596 /* 625 /*
@@ -816,6 +845,7 @@ packet_send2_wrapped(void)
816 if (!(datafellows & SSH_BUG_NOREKEY)) 845 if (!(datafellows & SSH_BUG_NOREKEY))
817 fatal("XXX too many packets with same key"); 846 fatal("XXX too many packets with same key");
818 p_send.blocks += (packet_length + 4) / block_size; 847 p_send.blocks += (packet_length + 4) / block_size;
848 p_send.bytes += packet_length + 4;
819 buffer_clear(&outgoing_packet); 849 buffer_clear(&outgoing_packet);
820 850
821 if (type == SSH2_MSG_NEWKEYS) 851 if (type == SSH2_MSG_NEWKEYS)
@@ -889,9 +919,11 @@ packet_send(void)
889int 919int
890packet_read_seqnr(u_int32_t *seqnr_p) 920packet_read_seqnr(u_int32_t *seqnr_p)
891{ 921{
892 int type, len; 922 int type, len, ret, ms_remain;
893 fd_set *setp; 923 fd_set *setp;
894 char buf[8192]; 924 char buf[8192];
925 struct timeval timeout, start, *timeoutp = NULL;
926
895 DBG(debug("packet_read()")); 927 DBG(debug("packet_read()"));
896 928
897 setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS), 929 setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS),
@@ -923,11 +955,35 @@ packet_read_seqnr(u_int32_t *seqnr_p)
923 sizeof(fd_mask)); 955 sizeof(fd_mask));
924 FD_SET(connection_in, setp); 956 FD_SET(connection_in, setp);
925 957
958 if (packet_timeout_ms > 0) {
959 ms_remain = packet_timeout_ms;
960 timeoutp = &timeout;
961 }
926 /* Wait for some data to arrive. */ 962 /* Wait for some data to arrive. */
927 while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && 963 for (;;) {
928 (errno == EAGAIN || errno == EINTR)) 964 if (packet_timeout_ms != -1) {
929 ; 965 ms_to_timeval(&timeout, ms_remain);
930 966 gettimeofday(&start, NULL);
967 }
968 if ((ret = select(connection_in + 1, setp, NULL,
969 NULL, timeoutp)) >= 0)
970 break;
971 if (errno != EAGAIN && errno != EINTR &&
972 errno != EWOULDBLOCK)
973 break;
974 if (packet_timeout_ms == -1)
975 continue;
976 ms_subtract_diff(&start, &ms_remain);
977 if (ms_remain <= 0) {
978 ret = 0;
979 break;
980 }
981 }
982 if (ret == 0) {
983 logit("Connection to %.200s timed out while "
984 "waiting to read", get_remote_ipaddr());
985 cleanup_exit(255);
986 }
931 /* Read data from the socket. */ 987 /* Read data from the socket. */
932 len = read(connection_in, buf, sizeof(buf)); 988 len = read(connection_in, buf, sizeof(buf));
933 if (len == 0) { 989 if (len == 0) {
@@ -1052,6 +1108,8 @@ packet_read_poll1(void)
1052 buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 1108 buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
1053 buffer_len(&compression_buffer)); 1109 buffer_len(&compression_buffer));
1054 } 1110 }
1111 p_read.packets++;
1112 p_read.bytes += padded_len + 4;
1055 type = buffer_get_char(&incoming_packet); 1113 type = buffer_get_char(&incoming_packet);
1056 if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) 1114 if (type < SSH_MSG_MIN || type > SSH_MSG_MAX)
1057 packet_disconnect("Invalid ssh1 packet type: %d", type); 1115 packet_disconnect("Invalid ssh1 packet type: %d", type);
@@ -1140,6 +1198,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
1140 if (!(datafellows & SSH_BUG_NOREKEY)) 1198 if (!(datafellows & SSH_BUG_NOREKEY))
1141 fatal("XXX too many packets with same key"); 1199 fatal("XXX too many packets with same key");
1142 p_read.blocks += (packet_length + 4) / block_size; 1200 p_read.blocks += (packet_length + 4) / block_size;
1201 p_read.bytes += packet_length + 4;
1143 1202
1144 /* get padlen */ 1203 /* get padlen */
1145 cp = buffer_ptr(&incoming_packet); 1204 cp = buffer_ptr(&incoming_packet);
@@ -1192,10 +1251,13 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
1192 for (;;) { 1251 for (;;) {
1193 if (compat20) { 1252 if (compat20) {
1194 type = packet_read_poll2(seqnr_p); 1253 type = packet_read_poll2(seqnr_p);
1195 if (type) 1254 if (type) {
1255 keep_alive_timeouts = 0;
1196 DBG(debug("received packet type %d", type)); 1256 DBG(debug("received packet type %d", type));
1257 }
1197 switch (type) { 1258 switch (type) {
1198 case SSH2_MSG_IGNORE: 1259 case SSH2_MSG_IGNORE:
1260 debug3("Received SSH2_MSG_IGNORE");
1199 break; 1261 break;
1200 case SSH2_MSG_DEBUG: 1262 case SSH2_MSG_DEBUG:
1201 packet_get_char(); 1263 packet_get_char();
@@ -1328,6 +1390,12 @@ packet_get_string(u_int *length_ptr)
1328 return buffer_get_string(&incoming_packet, length_ptr); 1390 return buffer_get_string(&incoming_packet, length_ptr);
1329} 1391}
1330 1392
1393void *
1394packet_get_string_ptr(u_int *length_ptr)
1395{
1396 return buffer_get_string_ptr(&incoming_packet, length_ptr);
1397}
1398
1331/* 1399/*
1332 * Sends a diagnostic message from the server to the client. This message 1400 * Sends a diagnostic message from the server to the client. This message
1333 * can be sent at any time (but not while constructing another message). The 1401 * can be sent at any time (but not while constructing another message). The
@@ -1422,16 +1490,19 @@ packet_write_poll(void)
1422 1490
1423 if (len > 0) { 1491 if (len > 0) {
1424 len = write(connection_out, buffer_ptr(&output), len); 1492 len = write(connection_out, buffer_ptr(&output), len);
1425 if (len <= 0) { 1493 if (len == -1) {
1426 if (errno == EAGAIN) 1494 if (errno == EINTR || errno == EAGAIN ||
1495 errno == EWOULDBLOCK)
1427 return; 1496 return;
1428 else 1497 fatal("Write failed: %.100s", strerror(errno));
1429 fatal("Write failed: %.100s", strerror(errno));
1430 } 1498 }
1499 if (len == 0)
1500 fatal("Write connection closed");
1431 buffer_consume(&output, len); 1501 buffer_consume(&output, len);
1432 } 1502 }
1433} 1503}
1434 1504
1505
1435/* 1506/*
1436 * Calls packet_write_poll repeatedly until all pending output data has been 1507 * Calls packet_write_poll repeatedly until all pending output data has been
1437 * written. 1508 * written.
@@ -1441,6 +1512,8 @@ void
1441packet_write_wait(void) 1512packet_write_wait(void)
1442{ 1513{
1443 fd_set *setp; 1514 fd_set *setp;
1515 int ret, ms_remain;
1516 struct timeval start, timeout, *timeoutp = NULL;
1444 1517
1445 setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), 1518 setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS),
1446 sizeof(fd_mask)); 1519 sizeof(fd_mask));
@@ -1449,9 +1522,35 @@ packet_write_wait(void)
1449 memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 1522 memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
1450 sizeof(fd_mask)); 1523 sizeof(fd_mask));
1451 FD_SET(connection_out, setp); 1524 FD_SET(connection_out, setp);
1452 while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 1525
1453 (errno == EAGAIN || errno == EINTR)) 1526 if (packet_timeout_ms > 0) {
1454 ; 1527 ms_remain = packet_timeout_ms;
1528 timeoutp = &timeout;
1529 }
1530 for (;;) {
1531 if (packet_timeout_ms != -1) {
1532 ms_to_timeval(&timeout, ms_remain);
1533 gettimeofday(&start, NULL);
1534 }
1535 if ((ret = select(connection_out + 1, NULL, setp,
1536 NULL, timeoutp)) >= 0)
1537 break;
1538 if (errno != EAGAIN && errno != EINTR &&
1539 errno != EWOULDBLOCK)
1540 break;
1541 if (packet_timeout_ms == -1)
1542 continue;
1543 ms_subtract_diff(&start, &ms_remain);
1544 if (ms_remain <= 0) {
1545 ret = 0;
1546 break;
1547 }
1548 }
1549 if (ret == 0) {
1550 logit("Connection to %.200s timed out while "
1551 "waiting to write", get_remote_ipaddr());
1552 cleanup_exit(255);
1553 }
1455 packet_write_poll(); 1554 packet_write_poll();
1456 } 1555 }
1457 xfree(setp); 1556 xfree(setp);