Develop and Download Open Source Software

Browse Subversion Repository

Diff of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2938 by maya, Tue Nov 28 13:20:52 2006 UTC revision 2940 by maya, Thu Nov 30 09:56:43 2006 UTC
# Line 491  static int buffer_packet_data(PTInstVar Line 491  static int buffer_packet_data(PTInstVar
491                                  pvar->ssh_state.payloadlen = cur_decompressed_bytes;                                  pvar->ssh_state.payloadlen = cur_decompressed_bytes;
492                                  return cur_decompressed_bytes;                                  return cur_decompressed_bytes;
493                          default:                          default:
494    #ifdef I18N
495    #else
496                                  notify_fatal_error(pvar,                                  notify_fatal_error(pvar,
497                                                                     "Invalid compressed data in received packet");                                                                     "Invalid compressed data in received packet");
498    #endif
499                                  return -1;                                  return -1;
500                          }                          }
501                  }                  }
# Line 520  static BOOL grab_payload(PTInstVar pvar, Line 523  static BOOL grab_payload(PTInstVar pvar,
523                  pvar->ssh_state.payload_grabbed += num_bytes;                  pvar->ssh_state.payload_grabbed += num_bytes;
524                  if (pvar->ssh_state.payload_grabbed > in_buffer) {                  if (pvar->ssh_state.payload_grabbed > in_buffer) {
525                          char buf[128];                          char buf[128];
526    #ifdef I18N
527    #else
528                          _snprintf(buf, sizeof(buf), "Received truncated packet (%ld > %d) @ grab_payload()",                          _snprintf(buf, sizeof(buf), "Received truncated packet (%ld > %d) @ grab_payload()",
529                                  pvar->ssh_state.payload_grabbed, in_buffer);                                  pvar->ssh_state.payload_grabbed, in_buffer);
530    #endif
531                          notify_fatal_error(pvar, buf);                          notify_fatal_error(pvar, buf);
532                          return FALSE;                          return FALSE;
533                  } else {                  } else {
# Line 542  static BOOL grab_payload_limited(PTInstV Line 548  static BOOL grab_payload_limited(PTInstV
548          } else {          } else {
549                  if (pvar->ssh_state.payload_grabbed > in_buffer) {                  if (pvar->ssh_state.payload_grabbed > in_buffer) {
550                          char buf[128];                          char buf[128];
551    #ifdef I18N
552    #else
553                          _snprintf(buf, sizeof(buf), "Received truncated packet (%ld > %d) @ grab_payload_limited()",                          _snprintf(buf, sizeof(buf), "Received truncated packet (%ld > %d) @ grab_payload_limited()",
554                                  pvar->ssh_state.payload_grabbed, in_buffer);                                  pvar->ssh_state.payload_grabbed, in_buffer);
555    #endif
556                          notify_fatal_error(pvar, buf);                          notify_fatal_error(pvar, buf);
557                          return FALSE;                          return FALSE;
558                  } else {                  } else {
# Line 574  static int prep_packet(PTInstVar pvar, c Line 583  static int prep_packet(PTInstVar pvar, c
583    
584          if (SSHv1(pvar)) {          if (SSHv1(pvar)) {
585                  if (CRYPT_detect_attack(pvar, pvar->ssh_state.payload, len)) {                  if (CRYPT_detect_attack(pvar, pvar->ssh_state.payload, len)) {
586    #ifdef I18N
587    #else
588                          notify_fatal_error(pvar,                          notify_fatal_error(pvar,
589                                                             "'CORE insertion attack' detected.  Aborting connection.");                                                             "'CORE insertion attack' detected.  Aborting connection.");
590                          return SSH_MSG_NONE;                          return SSH_MSG_NONE;
591    #endif
592                  }                  }
593    
594                  CRYPT_decrypt(pvar, pvar->ssh_state.payload, len);                  CRYPT_decrypt(pvar, pvar->ssh_state.payload, len);
595                  /* PKT guarantees that the data is always 4-byte aligned */                  /* PKT guarantees that the data is always 4-byte aligned */
596                  if (do_crc(pvar->ssh_state.payload, len - 4) !=                  if (do_crc(pvar->ssh_state.payload, len - 4) !=
597                          get_uint32_MSBfirst(pvar->ssh_state.payload + len - 4)) {                          get_uint32_MSBfirst(pvar->ssh_state.payload + len - 4)) {
598    #ifdef I18N
599    #else
600                          notify_fatal_error(pvar,                          notify_fatal_error(pvar,
601                                                             "Detected corrupted data; connection terminating.");                                                             "Detected corrupted data; connection terminating.");
602    #endif
603                          return SSH_MSG_NONE;                          return SSH_MSG_NONE;
604                  }                  }
605    
# Line 604  static int prep_packet(PTInstVar pvar, c Line 619  static int prep_packet(PTInstVar pvar, c
619                  if (!CRYPT_verify_receiver_MAC                  if (!CRYPT_verify_receiver_MAC
620                          (pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4,                          (pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4,
621                           data + len + 4)) {                           data + len + 4)) {
622    #ifdef I18N
623    #else
624                          notify_fatal_error(pvar,                          notify_fatal_error(pvar,
625                                                             "Detected corrupted data; connection terminating.");                                                             "Detected corrupted data; connection terminating.");
626    #endif
627                          return SSH_MSG_NONE;                          return SSH_MSG_NONE;
628                  }                  }
629    
# Line 618  static int prep_packet(PTInstVar pvar, c Line 636  static int prep_packet(PTInstVar pvar, c
636          if (SSHv1(pvar)) {          if (SSHv1(pvar)) {
637                  if (pvar->ssh_state.decompressing) {                  if (pvar->ssh_state.decompressing) {
638                          if (pvar->ssh_state.decompress_stream.avail_in != 0) {                          if (pvar->ssh_state.decompress_stream.avail_in != 0) {
639    #ifdef I18N
640    #else
641                                  notify_nonfatal_error(pvar,                                  notify_nonfatal_error(pvar,
642                                                                          "Internal error: a packet was not fully decompressed.\n"                                                                          "Internal error: a packet was not fully decompressed.\n"
643                                                                          "This is a bug, please report it.");                                                                          "This is a bug, please report it.");
644    #endif
645                          }                          }
646    
647                          pvar->ssh_state.decompress_stream.next_in =                          pvar->ssh_state.decompress_stream.next_in =
# Line 725  static BOOL send_packet_blocking(PTInstV Line 746  static BOOL send_packet_blocking(PTInstV
746                                                                          pvar->notification_msg,                                                                          pvar->notification_msg,
747                                                                          pvar->notification_events) ==                                                                          pvar->notification_events) ==
748                  SOCKET_ERROR) {                  SOCKET_ERROR) {
749    #ifdef I18N
750    #else
751                  notify_fatal_error(pvar,                  notify_fatal_error(pvar,
752                                                     "A communications error occurred while sending an SSH packet.\n"                                                     "A communications error occurred while sending an SSH packet.\n"
753                                                     "The connection will close.");                                                     "The connection will close.");
754    #endif
755                  return FALSE;                  return FALSE;
756          } else {          } else {
757                  return TRUE;                  return TRUE;
# Line 759  static void finish_send_packet_special(P Line 783  static void finish_send_packet_special(P
783    
784                          if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=                          if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
785                                  Z_OK) {                                  Z_OK) {
786    #ifdef I18N
787    #else
788                                  notify_fatal_error(pvar,                                  notify_fatal_error(pvar,
789                                                                     "An error occurred while compressing packet data.\n"                                                                     "An error occurred while compressing packet data.\n"
790                                                                     "The connection will close.");                                                                     "The connection will close.");
791    #endif
792                                  return;                                  return;
793                          }                          }
794                  }                  }
# Line 823  static void finish_send_packet_special(P Line 850  static void finish_send_packet_special(P
850                          // 圧縮対象はヘッダを除くペイロードのみ。                          // 圧縮対象はヘッダを除くペイロードのみ。
851                          buffer_append(msg, "\0\0\0\0\0", 5);  // 5 = packet-length(4) + padding(1)                          buffer_append(msg, "\0\0\0\0\0", 5);  // 5 = packet-length(4) + padding(1)
852                          if (buffer_compress(&pvar->ssh_state.compress_stream, pvar->ssh_state.outbuf + 12, len, msg) == -1) {                          if (buffer_compress(&pvar->ssh_state.compress_stream, pvar->ssh_state.outbuf + 12, len, msg) == -1) {
853    #ifdef I18N
854    #else
855                                  notify_fatal_error(pvar,                                  notify_fatal_error(pvar,
856                                                                     "An error occurred while compressing packet data.\n"                                                                     "An error occurred while compressing packet data.\n"
857                                                                     "The connection will close.");                                                                     "The connection will close.");
858    #endif
859                                  return;                                  return;
860                          }                          }
861                          data = buffer_ptr(msg);                          data = buffer_ptr(msg);
# Line 1162  static BOOL handle_disconnect(PTInstVar Line 1192  static BOOL handle_disconnect(PTInstVar
1192          }          }
1193    
1194          if (get_handler(pvar, SSH_SMSG_FAILURE) == handle_forwarding_failure) {          if (get_handler(pvar, SSH_SMSG_FAILURE) == handle_forwarding_failure) {
1195    #ifdef I18N
1196    #else
1197                  explanation =                  explanation =
1198                          "\nIt may have disconnected because it was unable to forward a port you requested to be forwarded from the server.\n"                          "\nIt may have disconnected because it was unable to forward a port you requested to be forwarded from the server.\n"
1199                          "This often happens when someone is already forwarding that port from the server.";                          "This often happens when someone is already forwarding that port from the server.";
1200    #endif
1201          }          }
1202    
1203          if (description != NULL) {          if (description != NULL) {
1204    #ifdef I18N
1205    #else
1206                  _snprintf(buf, sizeof(buf),                  _snprintf(buf, sizeof(buf),
1207                                    "Server disconnected with message '%s'.%s", description,                                    "Server disconnected with message '%s'.%s", description,
1208                                    explanation);                                    explanation);
1209    #endif
1210          } else {          } else {
1211    #ifdef I18N
1212    #else
1213                  _snprintf(buf, sizeof(buf),                  _snprintf(buf, sizeof(buf),
1214                                    "Server disconnected (no reason given).%s", explanation);                                    "Server disconnected (no reason given).%s", explanation);
1215    #endif
1216          }          }
1217          buf[sizeof(buf) - 1] = 0;          buf[sizeof(buf) - 1] = 0;
1218          notify_fatal_error(pvar, buf);          notify_fatal_error(pvar, buf);
# Line 1454  BOOL SSH_handle_server_ID(PTInstVar pvar Line 1493  BOOL SSH_handle_server_ID(PTInstVar pvar
1493                          pvar->ssh_state.server_ID = _strdup(ID);                          pvar->ssh_state.server_ID = _strdup(ID);
1494    
1495                          if (!parse_protocol_ID(pvar, ID) || !negotiate_protocol(pvar)) {                          if (!parse_protocol_ID(pvar, ID) || !negotiate_protocol(pvar)) {
1496    #ifdef I18N
1497    #else
1498                                  notify_fatal_error(pvar,                                  notify_fatal_error(pvar,
1499                                                                     "This program does not understand the server's version of the protocol.");                                                                     "This program does not understand the server's version of the protocol.");
1500    #else
1501                          } else {                          } else {
1502                                  char TTSSH_ID[1024];                                  char TTSSH_ID[1024];
1503                                  int TTSSH_ID_len;                                  int TTSSH_ID_len;
# Line 1478  BOOL SSH_handle_server_ID(PTInstVar pvar Line 1520  BOOL SSH_handle_server_ID(PTInstVar pvar
1520    
1521                                  if ((pvar->Psend) (pvar->socket, TTSSH_ID, TTSSH_ID_len,                                  if ((pvar->Psend) (pvar->socket, TTSSH_ID, TTSSH_ID_len,
1522                                                                     0) != TTSSH_ID_len) {                                                                     0) != TTSSH_ID_len) {
1523    #ifdef I18N
1524    #else
1525                                          notify_fatal_error(pvar,                                          notify_fatal_error(pvar,
1526                                                                             "An error occurred while sending the SSH ID string.\n"                                                                             "An error occurred while sending the SSH ID string.\n"
1527                                                                             "The connection will close.");                                                                             "The connection will close.");
1528    #endif
1529                                  } else {                                  } else {
1530                                          // 改行コードの除去 (2004.8.4 yutaka)                                          // 改行コードの除去 (2004.8.4 yutaka)
1531                                          pvar->client_version_string[--TTSSH_ID_len] = 0;                                          pvar->client_version_string[--TTSSH_ID_len] = 0;
# Line 1706  void SSH_handle_packet(PTInstVar pvar, c Line 1751  void SSH_handle_packet(PTInstVar pvar, c
1751                          if (!SSH2_dispatch_enabled_check(message) || handler == NULL) {                          if (!SSH2_dispatch_enabled_check(message) || handler == NULL) {
1752                                  char buf[1024];                                  char buf[1024];
1753    
1754    #ifdef I18N
1755    #else
1756                                  _snprintf(buf, sizeof(buf),                                  _snprintf(buf, sizeof(buf),
1757                                          "Unexpected SSH2 message(%d) on current stage(%d)", message, handle_message_stage);                                          "Unexpected SSH2 message(%d) on current stage(%d)", message, handle_message_stage);
1758    #endif
1759                                  notify_fatal_error(pvar, buf);                                  notify_fatal_error(pvar, buf);
1760                                  // abort                                  // abort
1761                          }                          }
# Line 1717  void SSH_handle_packet(PTInstVar pvar, c Line 1765  void SSH_handle_packet(PTInstVar pvar, c
1765                          if (SSHv1(pvar)) {                          if (SSHv1(pvar)) {
1766                                  char buf[1024];                                  char buf[1024];
1767    
1768    #ifdef I18N
1769    #else
1770                                  _snprintf(buf, sizeof(buf),                                  _snprintf(buf, sizeof(buf),
1771                                                    "Unexpected packet type received: %d", message);                                                    "Unexpected packet type received: %d", message);
1772    #endif
1773                                  buf[sizeof(buf) - 1] = 0;                                  buf[sizeof(buf) - 1] = 0;
1774                                  notify_fatal_error(pvar, buf);                                  notify_fatal_error(pvar, buf);
1775                          } else {                          } else {
# Line 1756  static BOOL handle_pty_success(PTInstVar Line 1807  static BOOL handle_pty_success(PTInstVar
1807    
1808  static BOOL handle_pty_failure(PTInstVar pvar)  static BOOL handle_pty_failure(PTInstVar pvar)
1809  {  {
1810    #ifdef I18N
1811    #else
1812          notify_nonfatal_error(pvar,          notify_nonfatal_error(pvar,
1813                                                    "The server cannot allocate a pseudo-terminal. "                                                    "The server cannot allocate a pseudo-terminal. "
1814                                                    "You may encounter some problems with the terminal.");                                                    "You may encounter some problems with the terminal.");
1815    #endif
1816          return handle_pty_success(pvar);          return handle_pty_success(pvar);
1817  }  }
1818    
# Line 1812  static void enable_send_compression(PTIn Line 1866  static void enable_send_compression(PTIn
1866          if (deflateInit          if (deflateInit
1867                  (&pvar->ssh_state.compress_stream,                  (&pvar->ssh_state.compress_stream,
1868                   pvar->ssh_state.compression_level) != Z_OK) {                   pvar->ssh_state.compression_level) != Z_OK) {
1869    #ifdef I18N
1870    #else
1871                  notify_fatal_error(pvar,                  notify_fatal_error(pvar,
1872                                                     "An error occurred while setting up compression.\n"                                                     "An error occurred while setting up compression.\n"
1873                                                     "The connection will close.");                                                     "The connection will close.");
1874    #endif
1875                  return;                  return;
1876          } else {          } else {
1877                  // SSH2では圧縮・展開処理をSSH1とは別に行うので、下記フラグは落としておく。(2005.7.9 yutaka)                  // SSH2では圧縮・展開処理をSSH1とは別に行うので、下記フラグは落としておく。(2005.7.9 yutaka)
# Line 1840  static void enable_recv_compression(PTIn Line 1897  static void enable_recv_compression(PTIn
1897          pvar->ssh_state.decompress_stream.opaque = NULL;          pvar->ssh_state.decompress_stream.opaque = NULL;
1898          if (inflateInit(&pvar->ssh_state.decompress_stream) != Z_OK) {          if (inflateInit(&pvar->ssh_state.decompress_stream) != Z_OK) {
1899                  deflateEnd(&pvar->ssh_state.compress_stream);                  deflateEnd(&pvar->ssh_state.compress_stream);
1900    #ifdef I18N
1901    #else
1902                  notify_fatal_error(pvar,                  notify_fatal_error(pvar,
1903                                                     "An error occurred while setting up compression.\n"                                                     "An error occurred while setting up compression.\n"
1904                                                     "The connection will close.");                                                     "The connection will close.");
1905    #endif
1906                  return;                  return;
1907          } else {          } else {
1908                  // SSH2では圧縮・展開処理をSSH1とは別に行うので、下記フラグは落としておく。(2005.7.9 yutaka)                  // SSH2では圧縮・展開処理をSSH1とは別に行うので、下記フラグは落としておく。(2005.7.9 yutaka)
# Line 1948  static BOOL handle_rsa_challenge(PTInstV Line 2008  static BOOL handle_rsa_challenge(PTInstV
2008    
2009                          enque_simple_auth_handlers(pvar);                          enque_simple_auth_handlers(pvar);
2010                  } else {                  } else {
2011    #ifdef I18N
2012    #else
2013                          notify_fatal_error(pvar,                          notify_fatal_error(pvar,
2014                                                             "An error occurred while decrypting the RSA challenge.\n"                                                             "An error occurred while decrypting the RSA challenge.\n"
2015                                                             "Perhaps the key file is corrupted.");                                                             "Perhaps the key file is corrupted.");
2016    #endif
2017                  }                  }
2018          }          }
2019    
# Line 2096  static void try_send_credentials(PTInstV Line 2159  static void try_send_credentials(PTInstV
2159                                  break;                                  break;
2160                          }                          }
2161                  default:                  default:
2162    #ifdef I18N
2163    #else
2164                          notify_fatal_error(pvar,                          notify_fatal_error(pvar,
2165                                                             "Internal error: unsupported authentication method");                                                             "Internal error: unsupported authentication method");
2166    #endif
2167                          return;                          return;
2168                  }                  }
2169    
# Line 2410  void SSH_send(PTInstVar pvar, unsigned c Line 2476  void SSH_send(PTInstVar pvar, unsigned c
2476    
2477                                  if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) !=                                  if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) !=
2478                                          Z_OK) {                                          Z_OK) {
2479    #ifdef I18N
2480    #else
2481                                          notify_fatal_error(pvar, "Error compressing packet data");                                          notify_fatal_error(pvar, "Error compressing packet data");
2482    #endif
2483                                          return;                                          return;
2484                                  }                                  }
2485    
# Line 2420  void SSH_send(PTInstVar pvar, unsigned c Line 2489  void SSH_send(PTInstVar pvar, unsigned c
2489    
2490                                  if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=                                  if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2491                                          Z_OK) {                                          Z_OK) {
2492    #ifdef I18N
2493    #else
2494                                          notify_fatal_error(pvar, "Error compressing packet data");                                          notify_fatal_error(pvar, "Error compressing packet data");
2495    #endif
2496                                          return;                                          return;
2497                                  }                                  }
2498                          } else {                          } else {
# Line 2492  int SSH_extract_payload(PTInstVar pvar, Line 2564  int SSH_extract_payload(PTInstVar pvar,
2564    
2565                  if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) !=                  if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) !=
2566                          Z_OK) {                          Z_OK) {
2567    #ifdef I18N
2568    #else
2569                          notify_fatal_error(pvar,                          notify_fatal_error(pvar,
2570                                                             "Invalid compressed data in received packet");                                                             "Invalid compressed data in received packet");
2571    #endif
2572                          return 0;                          return 0;
2573                  }                  }
2574          }          }
# Line 2694  void SSH_channel_send(PTInstVar pvar, in Line 2769  void SSH_channel_send(PTInstVar pvar, in
2769                                  pvar->ssh_state.outbuflen - 12;                                  pvar->ssh_state.outbuflen - 12;
2770    
2771                          if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) != Z_OK) {                          if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) != Z_OK) {
2772    #ifdef I18N
2773    #else
2774                                  notify_fatal_error(pvar, "Error compressing packet data");                                  notify_fatal_error(pvar, "Error compressing packet data");
2775    #endif
2776                                  return;                                  return;
2777                          }                          }
2778    
# Line 2704  void SSH_channel_send(PTInstVar pvar, in Line 2782  void SSH_channel_send(PTInstVar pvar, in
2782    
2783                          if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=                          if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2784                                  Z_OK) {                                  Z_OK) {
2785    #ifdef I18N
2786    #else
2787                                  notify_fatal_error(pvar, "Error compressing packet data");                                  notify_fatal_error(pvar, "Error compressing packet data");
2788    #endif
2789                                  return;                                  return;
2790                          }                          }
2791                  } else {                  } else {
# Line 6164  static BOOL handle_SSH2_userauth_failure Line 6245  static BOOL handle_SSH2_userauth_failure
6245    
6246          if (pvar->ssh2_autologin == 1) {          if (pvar->ssh2_autologin == 1) {
6247                  // SSH2自動ログインが有効の場合は、リトライは行わない。(2004.12.4 yutaka)                  // SSH2自動ログインが有効の場合は、リトライは行わない。(2004.12.4 yutaka)
6248    #ifdef I18N
6249    #else
6250                  notify_fatal_error(pvar,                  notify_fatal_error(pvar,
6251                          "SSH2 autologin error: user authentication was failure");                          "SSH2 autologin error: user authentication was failure");
6252    #endif
6253                  return TRUE;                  return TRUE;
6254          }          }
6255    
# Line 6451  static BOOL handle_SSH2_open_failure(PTI Line 6535  static BOOL handle_SSH2_open_failure(PTI
6535    
6536          cstring = buffer_get_string(&data, NULL);          cstring = buffer_get_string(&data, NULL);
6537    
6538    #ifdef I18N
6539    #else
6540          _snprintf(tmpbuf, sizeof(tmpbuf),          _snprintf(tmpbuf, sizeof(tmpbuf),
6541                  "SSH2_MSG_CHANNEL_OPEN_FAILURE was received.\r\nchannel [%d]: reason: %s(%d) message: %s",                  "SSH2_MSG_CHANNEL_OPEN_FAILURE was received.\r\nchannel [%d]: reason: %s(%d) message: %s",
6542                  id, rmsg, reason, cstring);                  id, rmsg, reason, cstring);
6543    #endif
6544          notify_nonfatal_error(pvar, tmpbuf);          notify_nonfatal_error(pvar, tmpbuf);
6545    
6546          free(cstring);          free(cstring);
# Line 6982  static BOOL handle_SSH2_window_adjust(PT Line 7069  static BOOL handle_SSH2_window_adjust(PT
7069    
7070  /*  /*
7071   * $Log: not supported by cvs2svn $   * $Log: not supported by cvs2svn $
7072     * Revision 1.64  2006/11/28 13:20:52  maya
7073     * Cisco ルータの送信する SSH2_MSG_IGNORE のデータが不正なようなので、何も処理しないようにした。
7074     *
7075   * Revision 1.63  2006/11/19 14:23:30  maya   * Revision 1.63  2006/11/19 14:23:30  maya
7076   * RSAの場合はworkaroundが不要なようなので削除した。   * RSAの場合はworkaroundが不要なようなので削除した。
7077   *   *

Legend:
Removed from v.2938  
changed lines
  Added in v.2940

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26