diff options
author | Bill Meier <wmeier@newsguy.com> | 2014-10-06 12:42:42 -0400 |
---|---|---|
committer | Bill Meier <wmeier@newsguy.com> | 2014-10-06 17:10:35 +0000 |
commit | 2005fc6e780e2df78382a3c04dbdd574054eb6a5 (patch) | |
tree | 3d2f7165d21677ada41bde77cc065a545808a991 | |
parent | 3377eca702cc0e8fe7b3f3409437f16b5b0b9b79 (diff) |
Convert (what appear to be) "4 space tabs"; Adjust editor-modelines; Do some minor reformatting.
Change-Id: Ie078c826ed38a0d682f61fb3e95450b47a9d2c31
Reviewed-on: https://code.wireshark.org/review/4499
Reviewed-by: Bill Meier <wmeier@newsguy.com>
-rw-r--r-- | epan/dissectors/packet-icq.c | 2216 | ||||
-rw-r--r-- | epan/dissectors/packet-rtpproxy.c | 2552 | ||||
-rw-r--r-- | epan/dissectors/packet-ssh.c | 2234 |
3 files changed, 3505 insertions, 3497 deletions
diff --git a/epan/dissectors/packet-icq.c b/epan/dissectors/packet-icq.c index 12c178b1eb..f57360f9f9 100644 --- a/epan/dissectors/packet-icq.c +++ b/epan/dissectors/packet-icq.c @@ -65,7 +65,7 @@ static expert_field ei_icq_unknown_meta_subcmd = EI_INIT; static expert_field ei_icq_unknown_command = EI_INIT; /* This is not IANA registered */ -#define UDP_PORT_ICQ 4000 +#define UDP_PORT_ICQ 4000 #define ICQ5_SERVER 0 #define ICQ5_CLIENT 1 @@ -74,289 +74,289 @@ const true_false_string tfs_client_server = { "Client", "Server" }; static void dissect_icqv5Server(tvbuff_t *tvb, int offset, packet_info *pinfo, - proto_tree *tree, int pktsize); + proto_tree *tree, int pktsize); /* Offsets of fields in the ICQ headers */ /* Can be 0x0002 or 0x0005 */ -#define ICQ_VERSION 0x00 +#define ICQ_VERSION 0x00 /* Is either one (server) or four (client) bytes long */ /* Client header offsets */ -#define ICQ5_UNKNOWN 0x02 -#define ICQ5_CL_UIN 0x06 -#define ICQ5_CL_SESSIONID 0x0a -#define ICQ5_CL_CMD 0x0e -#define ICQ5_CL_SEQNUM1 0x10 -#define ICQ5_CL_SEQNUM2 0x12 -#define ICQ5_CL_CHECKCODE 0x14 -#define ICQ5_CL_PARAM 0x18 -#define ICQ5_CL_HDRSIZE 0x18 +#define ICQ5_UNKNOWN 0x02 +#define ICQ5_CL_UIN 0x06 +#define ICQ5_CL_SESSIONID 0x0a +#define ICQ5_CL_CMD 0x0e +#define ICQ5_CL_SEQNUM1 0x10 +#define ICQ5_CL_SEQNUM2 0x12 +#define ICQ5_CL_CHECKCODE 0x14 +#define ICQ5_CL_PARAM 0x18 +#define ICQ5_CL_HDRSIZE 0x18 /* Server header offsets */ -#define ICQ5_SRV_SESSIONID 0x03 -#define ICQ5_SRV_CMD 0x07 -#define ICQ5_SRV_SEQNUM1 0x09 -#define ICQ5_SRV_SEQNUM2 0x0b -#define ICQ5_SRV_UIN 0x0d -#define ICQ5_SRV_CHECKCODE 0x11 -#define ICQ5_SRV_PARAM 0x15 -#define ICQ5_SRV_HDRSIZE 0x15 +#define ICQ5_SRV_SESSIONID 0x03 +#define ICQ5_SRV_CMD 0x07 +#define ICQ5_SRV_SEQNUM1 0x09 +#define ICQ5_SRV_SEQNUM2 0x0b +#define ICQ5_SRV_UIN 0x0d +#define ICQ5_SRV_CHECKCODE 0x11 +#define ICQ5_SRV_PARAM 0x15 +#define ICQ5_SRV_HDRSIZE 0x15 -#define SRV_ACK 0x000a +#define SRV_ACK 0x000a -#define SRV_SILENT_TOO_LONG 0x001e +#define SRV_SILENT_TOO_LONG 0x001e -#define SRV_GO_AWAY 0x0028 +#define SRV_GO_AWAY 0x0028 -#define SRV_NEW_UIN 0x0046 +#define SRV_NEW_UIN 0x0046 /* LOGIN_REPLY is very scary. It has a lot of fields that are undocumented * Only the IP field makes sense */ -#define SRV_LOGIN_REPLY 0x005a -#define SRV_LOGIN_REPLY_IP 0x000c +#define SRV_LOGIN_REPLY 0x005a +#define SRV_LOGIN_REPLY_IP 0x000c -#define SRV_BAD_PASS 0x0064 +#define SRV_BAD_PASS 0x0064 -#define SRV_USER_ONLINE 0x006e -#define SRV_USER_ONL_UIN 0x0000 -#define SRV_USER_ONL_IP 0x0004 -#define SRV_USER_ONL_PORT 0x0008 -#define SRV_USER_ONL_REALIP 0x000c -#define SRV_USER_ONL_X1 0x0010 -#define SRV_USER_ONL_STATUS 0x0013 -#define SRV_USER_ONL_X2 0x0015 +#define SRV_USER_ONLINE 0x006e +#define SRV_USER_ONL_UIN 0x0000 +#define SRV_USER_ONL_IP 0x0004 +#define SRV_USER_ONL_PORT 0x0008 +#define SRV_USER_ONL_REALIP 0x000c +#define SRV_USER_ONL_X1 0x0010 +#define SRV_USER_ONL_STATUS 0x0013 +#define SRV_USER_ONL_X2 0x0015 -#define SRV_USER_OFFLINE 0x0078 -#define SRV_USER_OFFLINE_UIN 0x0000 +#define SRV_USER_OFFLINE 0x0078 +#define SRV_USER_OFFLINE_UIN 0x0000 -#define SRV_MULTI 0x0212 -#define SRV_MULTI_NUM 0x0000 +#define SRV_MULTI 0x0212 +#define SRV_MULTI_NUM 0x0000 -#define SRV_META_USER 0x03de -#define SRV_META_USER_SUBCMD 0x0000 -#define SRV_META_USER_RESULT 0x0002 -#define SRV_META_USER_DATA 0x0003 +#define SRV_META_USER 0x03de +#define SRV_META_USER_SUBCMD 0x0000 +#define SRV_META_USER_RESULT 0x0002 +#define SRV_META_USER_DATA 0x0003 -#define SRV_UPDATE_SUCCESS 0x01e0 +#define SRV_UPDATE_SUCCESS 0x01e0 -#define SRV_UPDATE_FAIL 0x01ea +#define SRV_UPDATE_FAIL 0x01ea /* * ICQv5 SRV_META_USER subcommands */ -#define META_EX_USER_FOUND 0x0190 -#define META_USER_FOUND 0x019a -#define META_ABOUT 0x00e6 -#define META_USER_INFO 0x00c8 - -#define SRV_RECV_MESSAGE 0x00dc -#define SRV_RECV_MSG_UIN 0x0000 -#define SRV_RECV_MSG_YEAR 0x0004 -#define SRV_RECV_MSG_MONTH 0x0006 -#define SRV_RECV_MSG_DAY 0x0007 -#define SRV_RECV_MSG_HOUR 0x0008 -#define SRV_RECV_MSG_MINUTE 0x0009 +#define META_EX_USER_FOUND 0x0190 +#define META_USER_FOUND 0x019a +#define META_ABOUT 0x00e6 +#define META_USER_INFO 0x00c8 + +#define SRV_RECV_MESSAGE 0x00dc +#define SRV_RECV_MSG_UIN 0x0000 +#define SRV_RECV_MSG_YEAR 0x0004 +#define SRV_RECV_MSG_MONTH 0x0006 +#define SRV_RECV_MSG_DAY 0x0007 +#define SRV_RECV_MSG_HOUR 0x0008 +#define SRV_RECV_MSG_MINUTE 0x0009 #define SRV_RECV_MSG_MSG_TYPE 0x000a -#define SRV_RAND_USER 0x024e -#define SRV_RAND_USER_UIN 0x0000 -#define SRV_RAND_USER_IP 0x0004 -#define SRV_RAND_USER_PORT 0x0008 +#define SRV_RAND_USER 0x024e +#define SRV_RAND_USER_UIN 0x0000 +#define SRV_RAND_USER_IP 0x0004 +#define SRV_RAND_USER_PORT 0x0008 #define SRV_RAND_USER_REAL_IP 0x000c -#define SRV_RAND_USER_CLASS 0x0010 -#define SRV_RAND_USER_X1 0x0011 -#define SRV_RAND_USER_STATUS 0x0015 +#define SRV_RAND_USER_CLASS 0x0010 +#define SRV_RAND_USER_X1 0x0011 +#define SRV_RAND_USER_STATUS 0x0015 #define SRV_RAND_USER_TCP_VER 0x0019 /* This message has the same structure as cmd_send_msg */ -#define SRV_SYS_DELIVERED_MESS 0x0104 +#define SRV_SYS_DELIVERED_MESS 0x0104 static const value_string serverMetaSubCmdCode[] = { - { META_USER_FOUND, "META_USER_FOUND" }, - { META_EX_USER_FOUND, "META_EX_USER_FOUND" }, - { META_ABOUT, "META_ABOUT" }, - { META_USER_INFO, "META_USER_INFO" }, - { 0, NULL } + { META_USER_FOUND, "META_USER_FOUND" }, + { META_EX_USER_FOUND, "META_EX_USER_FOUND" }, + { META_ABOUT, "META_ABOUT" }, + { META_USER_INFO, "META_USER_INFO" }, + { 0, NULL } }; static const value_string serverCmdCode[] = { - { SRV_ACK, "SRV_ACK" }, - { SRV_SILENT_TOO_LONG, "SRV_SILENT_TOO_LONG" }, - { SRV_GO_AWAY, "SRV_GO_AWAY" }, - { SRV_NEW_UIN, "SRV_NEW_UIN" }, - { SRV_LOGIN_REPLY, "SRV_LOGIN_REPLY" }, - { SRV_BAD_PASS, "SRV_BAD_PASS" }, - { SRV_USER_ONLINE, "SRV_USER_ONLINE" }, - { SRV_USER_OFFLINE, "SRV_USER_OFFLINE" }, - { 130, "SRV_QUERY" }, - { 140, "SRV_USER_FOUND" }, - { 160, "SRV_END_OF_SEARCH" }, - { 180, "SRV_NEW_USER" }, - { 200, "SRV_UPDATE_EXT" }, - { SRV_RECV_MESSAGE, "SRV_RECV_MESSAGE" }, - { 230, "SRV_END_OFFLINE_MESSAGES" }, - { 240, "SRV_NOT_CONNECTED" }, - { 250, "SRV_TRY_AGAIN" }, - { SRV_SYS_DELIVERED_MESS, "SRV_SYS_DELIVERED_MESS" }, - { 280, "SRV_INFO_REPLY" }, - { 290, "SRV_EXT_INFO_REPLY" }, - { 420, "SRV_STATUS_UPDATE" }, - { 450, "SRV_SYSTEM_MESSAGE" }, - { SRV_UPDATE_SUCCESS, "SRV_UPDATE_SUCCESS" }, - { SRV_UPDATE_FAIL, "SRV_UPDATE_FAIL" }, - { 500, "SRV_AUTH_UPDATE" }, - { SRV_MULTI, "SRV_MULTI_PACKET" }, - { 540, "SRV_END_CONTACTLIST_STATUS" }, - { SRV_RAND_USER, "SRV_RAND_USER" }, - { SRV_META_USER, "SRV_META_USER" }, - { 0, NULL } + { SRV_ACK, "SRV_ACK" }, + { SRV_SILENT_TOO_LONG, "SRV_SILENT_TOO_LONG" }, + { SRV_GO_AWAY, "SRV_GO_AWAY" }, + { SRV_NEW_UIN, "SRV_NEW_UIN" }, + { SRV_LOGIN_REPLY, "SRV_LOGIN_REPLY" }, + { SRV_BAD_PASS, "SRV_BAD_PASS" }, + { SRV_USER_ONLINE, "SRV_USER_ONLINE" }, + { SRV_USER_OFFLINE, "SRV_USER_OFFLINE" }, + { 130, "SRV_QUERY" }, + { 140, "SRV_USER_FOUND" }, + { 160, "SRV_END_OF_SEARCH" }, + { 180, "SRV_NEW_USER" }, + { 200, "SRV_UPDATE_EXT" }, + { SRV_RECV_MESSAGE, "SRV_RECV_MESSAGE" }, + { 230, "SRV_END_OFFLINE_MESSAGES" }, + { 240, "SRV_NOT_CONNECTED" }, + { 250, "SRV_TRY_AGAIN" }, + { SRV_SYS_DELIVERED_MESS, "SRV_SYS_DELIVERED_MESS" }, + { 280, "SRV_INFO_REPLY" }, + { 290, "SRV_EXT_INFO_REPLY" }, + { 420, "SRV_STATUS_UPDATE" }, + { 450, "SRV_SYSTEM_MESSAGE" }, + { SRV_UPDATE_SUCCESS, "SRV_UPDATE_SUCCESS" }, + { SRV_UPDATE_FAIL, "SRV_UPDATE_FAIL" }, + { 500, "SRV_AUTH_UPDATE" }, + { SRV_MULTI, "SRV_MULTI_PACKET" }, + { 540, "SRV_END_CONTACTLIST_STATUS" }, + { SRV_RAND_USER, "SRV_RAND_USER" }, + { SRV_META_USER, "SRV_META_USER" }, + { 0, NULL } }; -#define MSG_TEXT 0x0001 -#define MSG_URL 0x0004 -#define MSG_AUTH_REQ 0x0006 -#define MSG_AUTH 0x0008 -#define MSG_USER_ADDED 0x000c -#define MSG_EMAIL 0x000e -#define MSG_CONTACTS 0x0013 - -#define STATUS_ONLINE 0x00000000 -#define STATUS_AWAY 0x00000001 -#define STATUS_DND 0x00000013 -#define STATUS_INVISIBLE 0x00000100 -#define STATUS_OCCUPIED 0x00000010 -#define STATUS_NA 0x00000004 -#define STATUS_CHAT 0x00000020 +#define MSG_TEXT 0x0001 +#define MSG_URL 0x0004 +#define MSG_AUTH_REQ 0x0006 +#define MSG_AUTH 0x0008 +#define MSG_USER_ADDED 0x000c +#define MSG_EMAIL 0x000e +#define MSG_CONTACTS 0x0013 + +#define STATUS_ONLINE 0x00000000 +#define STATUS_AWAY 0x00000001 +#define STATUS_DND 0x00000013 +#define STATUS_INVISIBLE 0x00000100 +#define STATUS_OCCUPIED 0x00000010 +#define STATUS_NA 0x00000004 +#define STATUS_CHAT 0x00000020 /* Offsets for all packets measured from the start of the payload; i.e. * with the ICQ header removed */ -#define CMD_ACK 0x000a -#define CMD_ACK_RANDOM 0x0000 - -#define CMD_SEND_MSG 0x010E -#define CMD_SEND_MSG_RECV_UIN 0x0000 -#define CMD_SEND_MSG_MSG_TYPE 0x0004 -#define CMD_SEND_MSG_MSG_LEN 0x0006 -#define CMD_SEND_MSG_MSG_TEXT 0x0008 +#define CMD_ACK 0x000a +#define CMD_ACK_RANDOM 0x0000 + +#define CMD_SEND_MSG 0x010E +#define CMD_SEND_MSG_RECV_UIN 0x0000 +#define CMD_SEND_MSG_MSG_TYPE 0x0004 +#define CMD_SEND_MSG_MSG_LEN 0x0006 +#define CMD_SEND_MSG_MSG_TEXT 0x0008 /* The rest of the packet should be a null-term string */ -#define CMD_LOGIN 0x03E8 -#define CMD_LOGIN_TIME 0x0000 -#define CMD_LOGIN_PORT 0x0004 -#define CMD_LOGIN_PASSLEN 0x0008 -#define CMD_LOGIN_PASSWD 0x000A +#define CMD_LOGIN 0x03E8 +#define CMD_LOGIN_TIME 0x0000 +#define CMD_LOGIN_PORT 0x0004 +#define CMD_LOGIN_PASSLEN 0x0008 +#define CMD_LOGIN_PASSWD 0x000A /* The password is variable length; so when we've decoded the passwd, * the structure starts counting at 0 again. */ -#define CMD_LOGIN_IP 0x0004 -#define CMD_LOGIN_STATUS 0x0009 +#define CMD_LOGIN_IP 0x0004 +#define CMD_LOGIN_STATUS 0x0009 -#define CMD_CONTACT_LIST 0x0406 -#define CMD_CONTACT_LIST_NUM 0x0000 +#define CMD_CONTACT_LIST 0x0406 +#define CMD_CONTACT_LIST_NUM 0x0000 -#define CMD_USER_META 0x064a +#define CMD_USER_META 0x064a -#define CMD_REG_NEW_USER 0x03fc +#define CMD_REG_NEW_USER 0x03fc -#define CMD_ACK_MESSAGES 0x0442 -#define CMD_ACK_MESSAGES_RANDOM 0x0000 +#define CMD_ACK_MESSAGES 0x0442 +#define CMD_ACK_MESSAGES_RANDOM 0x0000 -#define CMD_KEEP_ALIVE 0x042e -#define CMD_KEEP_ALIVE_RANDOM 0x0000 +#define CMD_KEEP_ALIVE 0x042e +#define CMD_KEEP_ALIVE_RANDOM 0x0000 -#define CMD_SEND_TEXT_CODE 0x0438 -#define CMD_SEND_TEXT_CODE_LEN 0x0000 -#define CMD_SEND_TEXT_CODE_TEXT 0x0002 +#define CMD_SEND_TEXT_CODE 0x0438 +#define CMD_SEND_TEXT_CODE_LEN 0x0000 +#define CMD_SEND_TEXT_CODE_TEXT 0x0002 -#define CMD_MSG_TO_NEW_USER 0x0456 +#define CMD_MSG_TO_NEW_USER 0x0456 -#define CMD_QUERY_SERVERS 0x04ba +#define CMD_QUERY_SERVERS 0x04ba -#define CMD_QUERY_ADDONS 0x04c4 +#define CMD_QUERY_ADDONS 0x04c4 -#define CMD_STATUS_CHANGE 0x04d8 +#define CMD_STATUS_CHANGE 0x04d8 #define CMD_STATUS_CHANGE_STATUS 0x0000 -#define CMD_ADD_TO_LIST 0x053c -#define CMD_ADD_TO_LIST_UIN 0x0000 +#define CMD_ADD_TO_LIST 0x053c +#define CMD_ADD_TO_LIST_UIN 0x0000 -#define CMD_RAND_SEARCH 0x056e -#define CMD_RAND_SEARCH_GROUP 0x0000 +#define CMD_RAND_SEARCH 0x056e +#define CMD_RAND_SEARCH_GROUP 0x0000 -#define CMD_META_USER 0x064a +#define CMD_META_USER 0x064a static const value_string msgTypeCode[] = { - { MSG_TEXT, "MSG_TEXT" }, - { MSG_URL, "MSG_URL" }, - { MSG_AUTH_REQ, "MSG_AUTH_REQ" }, - { MSG_AUTH, "MSG_AUTH" }, - { MSG_USER_ADDED, "MSG_USER_ADDED" }, - { MSG_EMAIL, "MSG_EMAIL" }, - { MSG_CONTACTS, "MSG_CONTACTS" }, - { 0, NULL } + { MSG_TEXT, "MSG_TEXT" }, + { MSG_URL, "MSG_URL" }, + { MSG_AUTH_REQ, "MSG_AUTH_REQ" }, + { MSG_AUTH, "MSG_AUTH" }, + { MSG_USER_ADDED, "MSG_USER_ADDED" }, + { MSG_EMAIL, "MSG_EMAIL" }, + { MSG_CONTACTS, "MSG_CONTACTS" }, + { 0, NULL } }; static const value_string statusCode[] = { - { STATUS_ONLINE, "ONLINE" }, - { STATUS_AWAY, "AWAY" }, - { STATUS_DND, "DND" }, - { STATUS_INVISIBLE, "INVISIBLE" }, - { STATUS_OCCUPIED, "OCCUPIED" }, - { STATUS_NA, "NA" }, - { STATUS_CHAT, "Free for Chat" }, - { 0, NULL } + { STATUS_ONLINE, "ONLINE" }, + { STATUS_AWAY, "AWAY" }, + { STATUS_DND, "DND" }, + { STATUS_INVISIBLE, "INVISIBLE" }, + { STATUS_OCCUPIED, "OCCUPIED" }, + { STATUS_NA, "NA" }, + { STATUS_CHAT, "Free for Chat" }, + { 0, NULL } }; static const value_string clientCmdCode[] = { - { CMD_ACK, "CMD_ACK" }, - { CMD_SEND_MSG, "CMD_SEND_MESSAGE" }, - { CMD_LOGIN, "CMD_LOGIN" }, - { CMD_REG_NEW_USER, "CMD_REG_NEW_USER" }, - { 1030, "CMD_CONTACT_LIST" }, - { 1050, "CMD_SEARCH_UIN" }, - { 1060, "CMD_SEARCH_USER" }, - { 1070, "CMD_KEEP_ALIVE" }, - { CMD_SEND_TEXT_CODE, "CMD_SEND_TEXT_CODE" }, - { CMD_ACK_MESSAGES, "CMD_ACK_MESSAGES" }, - { 1100, "CMD_LOGIN_1" }, - { CMD_MSG_TO_NEW_USER, "CMD_MSG_TO_NEW_USER" }, - { 1120, "CMD_INFO_REQ" }, - { 1130, "CMD_EXT_INFO_REQ" }, - { 1180, "CMD_CHANGE_PW" }, - { 1190, "CMD_NEW_USER_INFO" }, - { 1200, "CMD_UPDATE_EXT_INFO" }, - { CMD_QUERY_SERVERS, "CMD_QUERY_SERVERS" }, - { CMD_QUERY_ADDONS, "CMD_QUERY_ADDONS" }, - { CMD_STATUS_CHANGE, "CMD_STATUS_CHANGE" }, - { 1260, "CMD_NEW_USER_1" }, - { 1290, "CMD_UPDATE_INFO" }, - { 1300, "CMD_AUTH_UPDATE" }, - { 1310, "CMD_KEEP_ALIVE2" }, - { 1320, "CMD_LOGIN_2" }, - { CMD_ADD_TO_LIST, "CMD_ADD_TO_LIST" }, - { 1380, "CMD_RAND_SET" }, - { CMD_RAND_SEARCH, "CMD_RAND_SEARCH" }, - { CMD_META_USER, "CMD_META_USER" }, - { 1700, "CMD_INVIS_LIST" }, - { 1710, "CMD_VIS_LIST" }, - { 1720, "CMD_UPDATE_LIST" }, - { 0, NULL } + { CMD_ACK, "CMD_ACK" }, + { CMD_SEND_MSG, "CMD_SEND_MESSAGE" }, + { CMD_LOGIN, "CMD_LOGIN" }, + { CMD_REG_NEW_USER, "CMD_REG_NEW_USER" }, + { 1030, "CMD_CONTACT_LIST" }, + { 1050, "CMD_SEARCH_UIN" }, + { 1060, "CMD_SEARCH_USER" }, + { 1070, "CMD_KEEP_ALIVE" }, + { CMD_SEND_TEXT_CODE, "CMD_SEND_TEXT_CODE" }, + { CMD_ACK_MESSAGES, "CMD_ACK_MESSAGES" }, + { 1100, "CMD_LOGIN_1" }, + { CMD_MSG_TO_NEW_USER, "CMD_MSG_TO_NEW_USER" }, + { 1120, "CMD_INFO_REQ" }, + { 1130, "CMD_EXT_INFO_REQ" }, + { 1180, "CMD_CHANGE_PW" }, + { 1190, "CMD_NEW_USER_INFO" }, + { 1200, "CMD_UPDATE_EXT_INFO" }, + { CMD_QUERY_SERVERS, "CMD_QUERY_SERVERS" }, + { CMD_QUERY_ADDONS, "CMD_QUERY_ADDONS" }, + { CMD_STATUS_CHANGE, "CMD_STATUS_CHANGE" }, + { 1260, "CMD_NEW_USER_1" }, + { 1290, "CMD_UPDATE_INFO" }, + { 1300, "CMD_AUTH_UPDATE" }, + { 1310, "CMD_KEEP_ALIVE2" }, + { 1320, "CMD_LOGIN_2" }, + { CMD_ADD_TO_LIST, "CMD_ADD_TO_LIST" }, + { 1380, "CMD_RAND_SET" }, + { CMD_RAND_SEARCH, "CMD_RAND_SEARCH" }, + { CMD_META_USER, "CMD_META_USER" }, + { 1700, "CMD_INVIS_LIST" }, + { 1710, "CMD_VIS_LIST" }, + { 1720, "CMD_UPDATE_LIST" }, + { 0, NULL } }; #if 0 static const value_string group_vals[] = { - { 1, "Name" }, - { 2, "General" }, - { 3, "Romance" }, - { 4, "Games" }, - { 5, "Students" }, - { 6, "20 Something" }, - { 7, "30 Something" }, - { 8, "40 Something" }, - { 9, "50 or worse" }, - { 10, "Man want women" }, - { 11, "Women want men" }, - { 0, NULL } + { 1, "Name" }, + { 2, "General" }, + { 3, "Romance" }, + { 4, "Games" }, + { 5, "Students" }, + { 6, "20 Something" }, + { 7, "30 Something" }, + { 8, "40 Something" }, + { 9, "50 or worse" }, + { 10, "Man want women" }, + { 11, "Women want men" }, + { 0, NULL } }; #endif @@ -365,65 +365,65 @@ static const value_string group_vals[] = { */ static const guchar table_v5 [] = { - 0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D, - 0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39, - 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69, 0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42, - 0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49, 0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48, - 0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53, 0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54, - 0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A, 0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36, - 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A, - 0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36, 0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35, - 0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66, 0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B, - 0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, - 0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E, 0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C, - 0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F, 0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E, - 0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E, 0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58, - 0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41, - 0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E, 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, - 0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00 }; + 0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D, + 0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39, + 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69, 0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42, + 0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49, 0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48, + 0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53, 0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54, + 0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A, 0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36, + 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A, + 0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36, 0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35, + 0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66, 0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B, + 0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, + 0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E, 0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C, + 0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F, 0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E, + 0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E, 0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58, + 0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41, + 0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E, 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, + 0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00 }; static guint32 get_v5key(guint32 code, int len) { - guint32 a1, a2, a3, a4, a5; - guint32 check, key; - - a1 = code & 0x0001f000; - a2 = code & 0x07c007c0; - a3 = code & 0x003e0001; - a4 = code & 0xf8000000; - a5 = code & 0x0000083e; - - a1 = a1 >> 0x0c; - a2 = a2 >> 0x01; - a3 = a3 << 0x0a; - a4 = a4 >> 0x10; - a5 = a5 << 0x0f; - - check = a5 + a1 + a2 + a3 + a4; - key = len * 0x68656C6C; - key += check; - return key; + guint32 a1, a2, a3, a4, a5; + guint32 check, key; + + a1 = code & 0x0001f000; + a2 = code & 0x07c007c0; + a3 = code & 0x003e0001; + a4 = code & 0xf8000000; + a5 = code & 0x0000083e; + + a1 = a1 >> 0x0c; + a2 = a2 >> 0x01; + a3 = a3 << 0x0a; + a4 = a4 >> 0x10; + a5 = a5 << 0x0f; + + check = a5 + a1 + a2 + a3 + a4; + key = len * 0x68656C6C; + key += check; + return key; } static void decrypt_v5(guchar *bfr, guint32 size,guint32 key) { - guint32 i; - guint32 k; - - for (i=ICQ5_CL_SESSIONID; i < size; i+=4 ) { - k = key+table_v5[i&0xff]; - if ( i != 0x16 ) { - bfr[i] ^= (guchar)(k & 0xff); - bfr[i+1] ^= (guchar)((k & 0xff00)>>8); - } - if ( i != 0x12 ) { - bfr[i+2] ^= (guchar)((k & 0xff0000)>>16); - bfr[i+3] ^= (guchar)((k & 0xff000000)>>24); - } - } + guint32 i; + guint32 k; + + for (i=ICQ5_CL_SESSIONID; i < size; i+=4 ) { + k = key+table_v5[i&0xff]; + if ( i != 0x16 ) { + bfr[i] ^= (guchar)(k & 0xff); + bfr[i+1] ^= (guchar)((k & 0xff00)>>8); + } + if ( i != 0x12 ) { + bfr[i+2] ^= (guchar)((k & 0xff0000)>>16); + bfr[i+3] ^= (guchar)((k & 0xff000000)>>24); + } + } } /* @@ -434,238 +434,238 @@ decrypt_v5(guchar *bfr, guint32 size,guint32 key) * length. Else, return the number of chars processed. */ static guint16 -proto_add_icq_attr(proto_tree* tree, /* The tree to add to */ - tvbuff_t *tvb, /* Tvbuff with packet */ - const int offset, /* Offset from the start of packet of field */ - const char* descr) /* The description to use in the tree */ +proto_add_icq_attr(proto_tree *tree, /* The tree to add to */ + tvbuff_t *tvb, /* Tvbuff with packet */ + const int offset, /* Offset from the start of packet of field */ + const char *descr) /* The description to use in the tree */ { - guint16 len; - - len = tvb_get_letohs(tvb, offset); - if (len > tvb_reported_length_remaining(tvb, offset)) - return -1; /* length goes past end of packet */ - proto_tree_add_text(tree, tvb, offset, len+2, - "%s[%u]: %.*s", descr, len, len, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 2, len, ENC_ASCII)); - return len + 2; + guint16 len; + + len = tvb_get_letohs(tvb, offset); + if (len > tvb_reported_length_remaining(tvb, offset)) + return -1; /* length goes past end of packet */ + proto_tree_add_text(tree, tvb, offset, len+2, + "%s[%u]: %.*s", descr, len, len, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 2, len, ENC_ASCII)); + return len + 2; } static void -icqv5_decode_msgType(proto_tree* tree, tvbuff_t *tvb, int offset, int size, - packet_info *pinfo) +icqv5_decode_msgType(proto_tree *tree, tvbuff_t *tvb, int offset, int size, + packet_info *pinfo) { - proto_item *msg_item; - proto_tree *subtree; - int left = size; - guint16 msgType; - gint sep_offset; - int sz; /* Size of the current element */ - unsigned int n; - static const char* url_field_descr[] = { - "Description", - "URL", - }; -#define N_URL_FIELDS (sizeof url_field_descr / sizeof url_field_descr[0]) - static const char* email_field_descr[] = { - "Nickname", - "First name", - "Last name", - "Email address", - "Unknown", - "Text" - }; -#define N_EMAIL_FIELDS (sizeof email_field_descr / sizeof email_field_descr[0]) - static const char* auth_req_field_descr[] = { - "Nickname", - "First name", - "Last name", - "Email address", - "Unknown", - "Reason" - }; -#define N_AUTH_REQ_FIELDS (sizeof auth_req_field_descr / sizeof auth_req_field_descr[0]) - static const char* user_added_field_descr[] = { - "Nickname", - "First name", - "Last name", - "Email address", - }; -#define N_USER_ADDED_FIELDS (sizeof user_added_field_descr / sizeof user_added_field_descr[0]) - - msgType = tvb_get_letohs(tvb, offset); - subtree = proto_tree_add_subtree_format(tree, tvb, offset, size, ett_icq_body_parts, NULL, - "%s Message", val_to_str_const(msgType, msgTypeCode, "Unknown")); - - msg_item = proto_tree_add_item(subtree, hf_icq_msg_type, tvb, offset, 2, ENC_LITTLE_ENDIAN); - offset += 2; - left -= 2; - if (msgType != MSG_AUTH) { - /* - * XXX - does a MSG_AUTH message really have 3 bytes of information - * rather than a length field? - */ - proto_tree_add_text(subtree, tvb, offset, 2, "Length: %u", - tvb_get_letohs(tvb, offset)); - offset += 2; - left -= 2; - } - - switch(msgType) { - case 0xffff: /* Field unknown */ - break; - default: - expert_add_info_format(pinfo, msg_item, &ei_icq_unknown_command, - "Unknown msgType: %u (0x%x)", msgType, msgType); - break; - case MSG_TEXT: - proto_tree_add_text(subtree, tvb, offset, left, "Msg: %.*s", left-1, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset, left, ENC_ASCII)); - break; - case MSG_URL: - for (n = 0; n < N_URL_FIELDS; n++) { - if (n != N_URL_FIELDS - 1) { - sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); - sz = sep_offset - offset + 1; - } else { - sz = left; - } - if (sz != 0) { - proto_tree_add_text(subtree, tvb, offset, sz, "%s: %.*s", - url_field_descr[n], - sz - 1, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz, ENC_ASCII)); - } else { - proto_tree_add_text(subtree, tvb, offset, 0, - "%s: %s", url_field_descr[n], "(empty)"); - } - offset += sz; - left -= sz; - } - break; - case MSG_EMAIL: - for (n = 0; n < N_EMAIL_FIELDS; n++) { - if (n != N_EMAIL_FIELDS - 1) { - sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); - sz = sep_offset - offset + 1; - } else { - sz = left; - } - if (sz != 0) { - proto_tree_add_text(subtree, tvb, offset, sz, "%s: %.*s", - email_field_descr[n], - sz - 1, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz, ENC_ASCII)); - } else { - proto_tree_add_text(subtree, tvb, offset, 0, "%s: %s", - email_field_descr[n], "(empty)"); - } - offset += sz; - left -= sz; - } - break; - - case MSG_AUTH: - { - /* Three bytes, first is a char signifying success */ - unsigned char auth_suc; - - auth_suc = tvb_get_guint8(tvb, offset); - proto_tree_add_text(subtree, tvb, offset, 1, - "Authorization: (%u) %s",auth_suc, - (auth_suc==0)?"Denied":"Allowed"); - offset++; - proto_tree_add_text(subtree, tvb, offset, 2, "x1: 0x%04x", - tvb_get_letohs(tvb, offset)); - break; - } - case MSG_AUTH_REQ: - for (n = 0; n < N_AUTH_REQ_FIELDS; n++) { - if (n != N_AUTH_REQ_FIELDS - 1) { - sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); - sz = sep_offset - offset + 1; - } else { - sz = left; - } - if (sz != 0) { - proto_tree_add_text(subtree, tvb, offset, sz, "%s: %.*s", - auth_req_field_descr[n], sz - 1, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz, ENC_ASCII)); - } else { - proto_tree_add_text(subtree, tvb, offset, 0, "%s: %s", - auth_req_field_descr[n], "(empty)"); - } - offset += sz; - left -= sz; - } - break; - case MSG_USER_ADDED: - for (n = 0; n < N_USER_ADDED_FIELDS; n++) { - if (n != N_USER_ADDED_FIELDS - 1) { - sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); - sz = sep_offset - offset + 1; - } else { - sz = left; - } - if (sz != 0) { - proto_tree_add_text(subtree, tvb, offset, sz, "%s: %.*s", - user_added_field_descr[n], sz - 1, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz, ENC_ASCII)); - } else { - proto_tree_add_text(subtree, tvb, offset, 0, "%s: %s", - user_added_field_descr[n], "(empty)"); - } - offset += sz; - left -= sz; - } - break; - case MSG_CONTACTS: - { - gint sep_offset_prev; - int sz_local = 0; /* Size of the current element */ - int n_local = 0; /* The nth element */ - gboolean last = FALSE; - - while (!last) { - sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); - if (sep_offset != -1) { - sz_local = sep_offset - offset + 1; - } - else { - sz_local = left; - last = TRUE; - } - - if (n_local == 0) { - /* The first element is the number of Nick/UIN pairs follow */ - proto_tree_add_text(subtree, tvb, offset, sz_local, - "Number of pairs: %.*s", sz_local - 1, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz_local, ENC_ASCII)); - n_local++; - } else if (!last) { - int svsz = sz_local; - - left -= sz_local; - sep_offset_prev = sep_offset; - sep_offset = tvb_find_guint8(tvb, sep_offset_prev, left, 0xfe); - if (sep_offset != -1) - sz_local = sep_offset - offset + 1; - else { - sz_local = left; - last = TRUE; - } - proto_tree_add_text(subtree, tvb, offset, sz_local + svsz, - "%.*s: %.*s", svsz - 1, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset, svsz, ENC_ASCII), sz_local - 1, - tvb_get_string_enc(wmem_packet_scope(), tvb, sep_offset_prev + 1, sz_local, ENC_ASCII)); - n_local += 2; - } - - left -= (sz_local+1); - offset = sep_offset + 1; - } - break; - } - } + proto_item *msg_item; + proto_tree *subtree; + int left = size; + guint16 msgType; + gint sep_offset; + int sz; /* Size of the current element */ + unsigned int n; + static const char *url_field_descr[] = { + "Description", + "URL", + }; +#define N_URL_FIELDS (sizeof url_field_descr / sizeof url_field_descr[0]) + static const char *email_field_descr[] = { + "Nickname", + "First name", + "Last name", + "Email address", + "Unknown", + "Text" + }; +#define N_EMAIL_FIELDS (sizeof email_field_descr / sizeof email_field_descr[0]) + static const char *auth_req_field_descr[] = { + "Nickname", + "First name", + "Last name", + "Email address", + "Unknown", + "Reason" + }; +#define N_AUTH_REQ_FIELDS (sizeof auth_req_field_descr / sizeof auth_req_field_descr[0]) + static const char *user_added_field_descr[] = { + "Nickname", + "First name", + "Last name", + "Email address", + }; +#define N_USER_ADDED_FIELDS (sizeof user_added_field_descr / sizeof user_added_field_descr[0]) + + msgType = tvb_get_letohs(tvb, offset); + subtree = proto_tree_add_subtree_format(tree, tvb, offset, size, ett_icq_body_parts, NULL, + "%s Message", val_to_str_const(msgType, msgTypeCode, "Unknown")); + + msg_item = proto_tree_add_item(subtree, hf_icq_msg_type, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + left -= 2; + if (msgType != MSG_AUTH) { + /* + * XXX - does a MSG_AUTH message really have 3 bytes of information + * rather than a length field? + */ + proto_tree_add_text(subtree, tvb, offset, 2, "Length: %u", + tvb_get_letohs(tvb, offset)); + offset += 2; + left -= 2; + } + + switch(msgType) { + case 0xffff: /* Field unknown */ + break; + default: + expert_add_info_format(pinfo, msg_item, &ei_icq_unknown_command, + "Unknown msgType: %u (0x%x)", msgType, msgType); + break; + case MSG_TEXT: + proto_tree_add_text(subtree, tvb, offset, left, "Msg: %.*s", left-1, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset, left, ENC_ASCII)); + break; + case MSG_URL: + for (n = 0; n < N_URL_FIELDS; n++) { + if (n != N_URL_FIELDS - 1) { + sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); + sz = sep_offset - offset + 1; + } else { + sz = left; + } + if (sz != 0) { + proto_tree_add_text(subtree, tvb, offset, sz, "%s: %.*s", + url_field_descr[n], + sz - 1, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz, ENC_ASCII)); + } else { + proto_tree_add_text(subtree, tvb, offset, 0, + "%s: %s", url_field_descr[n], "(empty)"); + } + offset += sz; + left -= sz; + } + break; + case MSG_EMAIL: + for (n = 0; n < N_EMAIL_FIELDS; n++) { + if (n != N_EMAIL_FIELDS - 1) { + sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); + sz = sep_offset - offset + 1; + } else { + sz = left; + } + if (sz != 0) { + proto_tree_add_text(subtree, tvb, offset, sz, "%s: %.*s", + email_field_descr[n], + sz - 1, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz, ENC_ASCII)); + } else { + proto_tree_add_text(subtree, tvb, offset, 0, "%s: %s", + email_field_descr[n], "(empty)"); + } + offset += sz; + left -= sz; + } + break; + + case MSG_AUTH: + { + /* Three bytes, first is a char signifying success */ + unsigned char auth_suc; + + auth_suc = tvb_get_guint8(tvb, offset); + proto_tree_add_text(subtree, tvb, offset, 1, + "Authorization: (%u) %s",auth_suc, + (auth_suc==0)?"Denied":"Allowed"); + offset++; + proto_tree_add_text(subtree, tvb, offset, 2, "x1: 0x%04x", + tvb_get_letohs(tvb, offset)); + break; + } + case MSG_AUTH_REQ: + for (n = 0; n < N_AUTH_REQ_FIELDS; n++) { + if (n != N_AUTH_REQ_FIELDS - 1) { + sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); + sz = sep_offset - offset + 1; + } else { + sz = left; + } + if (sz != 0) { + proto_tree_add_text(subtree, tvb, offset, sz, "%s: %.*s", + auth_req_field_descr[n], sz - 1, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz, ENC_ASCII)); + } else { + proto_tree_add_text(subtree, tvb, offset, 0, "%s: %s", + auth_req_field_descr[n], "(empty)"); + } + offset += sz; + left -= sz; + } + break; + case MSG_USER_ADDED: + for (n = 0; n < N_USER_ADDED_FIELDS; n++) { + if (n != N_USER_ADDED_FIELDS - 1) { + sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); + sz = sep_offset - offset + 1; + } else { + sz = left; + } + if (sz != 0) { + proto_tree_add_text(subtree, tvb, offset, sz, "%s: %.*s", + user_added_field_descr[n], sz - 1, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz, ENC_ASCII)); + } else { + proto_tree_add_text(subtree, tvb, offset, 0, "%s: %s", + user_added_field_descr[n], "(empty)"); + } + offset += sz; + left -= sz; + } + break; + case MSG_CONTACTS: + { + gint sep_offset_prev; + int sz_local = 0; /* Size of the current element */ + int n_local = 0; /* The nth element */ + gboolean last = FALSE; + + while (!last) { + sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe); + if (sep_offset != -1) { + sz_local = sep_offset - offset + 1; + } + else { + sz_local = left; + last = TRUE; + } + + if (n_local == 0) { + /* The first element is the number of Nick/UIN pairs follow */ + proto_tree_add_text(subtree, tvb, offset, sz_local, + "Number of pairs: %.*s", sz_local - 1, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sz_local, ENC_ASCII)); + n_local++; + } else if (!last) { + int svsz = sz_local; + + left -= sz_local; + sep_offset_prev = sep_offset; + sep_offset = tvb_find_guint8(tvb, sep_offset_prev, left, 0xfe); + if (sep_offset != -1) + sz_local = sep_offset - offset + 1; + else { + sz_local = left; + last = TRUE; + } + proto_tree_add_text(subtree, tvb, offset, sz_local + svsz, + "%.*s: %.*s", svsz - 1, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset, svsz, ENC_ASCII), sz_local - 1, + tvb_get_string_enc(wmem_packet_scope(), tvb, sep_offset_prev + 1, sz_local, ENC_ASCII)); + n_local += 2; + } + + left -= (sz_local+1); + offset = sep_offset + 1; + } + break; + } + } } /********************************* @@ -674,95 +674,95 @@ icqv5_decode_msgType(proto_tree* tree, tvbuff_t *tvb, int offset, int size, * *********************************/ static void -icqv5_cmd_send_text_code(proto_tree* tree, /* Tree to put the data in */ - tvbuff_t *tvb, /* Decrypted packet content */ - int offset) /* Offset from the start of the packet to the content */ +icqv5_cmd_send_text_code(proto_tree *tree, /* Tree to put the data in */ + tvbuff_t *tvb, /* Decrypted packet content */ + int offset) /* Offset from the start of the packet to the content */ { - proto_tree* subtree = tree; - guint16 len; - guint16 x1; - - len = tvb_get_letohs(tvb, offset+CMD_SEND_TEXT_CODE_LEN); - proto_tree_add_text(subtree, tvb, offset + CMD_SEND_TEXT_CODE_LEN, - 2, "Length: %d", len); - - if (len>0) { - proto_tree_add_text(subtree, tvb, offset + CMD_SEND_TEXT_CODE_TEXT, - len, "Text: %.*s", len, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset + CMD_SEND_TEXT_CODE_TEXT, - len, ENC_ASCII)); - } - - x1 = tvb_get_letohs(tvb, offset + CMD_SEND_TEXT_CODE_TEXT + len); - proto_tree_add_text(subtree, tvb, - offset + CMD_SEND_TEXT_CODE_TEXT + len, - 2, "X1: 0x%04x", x1); + proto_tree *subtree = tree; + guint16 len; + guint16 x1; + + len = tvb_get_letohs(tvb, offset+CMD_SEND_TEXT_CODE_LEN); + proto_tree_add_text(subtree, tvb, offset + CMD_SEND_TEXT_CODE_LEN, + 2, "Length: %d", len); + + if (len>0) { + proto_tree_add_text(subtree, tvb, offset + CMD_SEND_TEXT_CODE_TEXT, + len, "Text: %.*s", len, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset + CMD_SEND_TEXT_CODE_TEXT, + len, ENC_ASCII)); + } + + x1 = tvb_get_letohs(tvb, offset + CMD_SEND_TEXT_CODE_TEXT + len); + proto_tree_add_text(subtree, tvb, + offset + CMD_SEND_TEXT_CODE_TEXT + len, + 2, "X1: 0x%04x", x1); } static void -icqv5_cmd_send_msg(proto_tree* tree, tvbuff_t *tvb, int offset, int size, - packet_info *pinfo) +icqv5_cmd_send_msg(proto_tree *tree, tvbuff_t *tvb, int offset, int size, + packet_info *pinfo) { - proto_tree_add_text(tree, tvb, offset + CMD_SEND_MSG_RECV_UIN, 4, - "Receiver UIN: %u", - tvb_get_letohl(tvb, offset + CMD_SEND_MSG_RECV_UIN)); - size -= 4; + proto_tree_add_text(tree, tvb, offset + CMD_SEND_MSG_RECV_UIN, 4, + "Receiver UIN: %u", + tvb_get_letohl(tvb, offset + CMD_SEND_MSG_RECV_UIN)); + size -= 4; - icqv5_decode_msgType(tree, tvb, offset + CMD_SEND_MSG_MSG_TYPE, - size, pinfo); + icqv5_decode_msgType(tree, tvb, offset + CMD_SEND_MSG_MSG_TYPE, + size, pinfo); } static void -icqv5_cmd_login(proto_tree* tree, tvbuff_t *tvb, int offset) +icqv5_cmd_login(proto_tree *tree, tvbuff_t *tvb, int offset) { - proto_tree* subtree = tree; - time_t theTime; - char *aTime; - guint32 port; - guint32 passwdLen; - - if (tree) { - theTime = tvb_get_letohl(tvb, offset + CMD_LOGIN_TIME); - aTime = abs_time_secs_to_str(wmem_packet_scope(), theTime, ABSOLUTE_TIME_LOCAL, TRUE); - proto_tree_add_text(subtree, tvb, offset + CMD_LOGIN_TIME, 4, - "Time: %ld = %s", (long)theTime, aTime); - port = tvb_get_letohl(tvb, offset + CMD_LOGIN_PORT); - proto_tree_add_text(subtree, tvb, offset + CMD_LOGIN_PORT, 4, - "Port: %u", port); - passwdLen = tvb_get_letohs(tvb, offset + CMD_LOGIN_PASSLEN); - proto_tree_add_text(subtree, tvb, offset + CMD_LOGIN_PASSLEN, - 2 + passwdLen, "Passwd: %.*s", (int)passwdLen, - tvb_get_string_enc(wmem_packet_scope(), tvb, offset + CMD_LOGIN_PASSWD, - passwdLen, ENC_ASCII)); - proto_tree_add_text(subtree, tvb, - offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_IP, - 4, "IP: %s", tvb_ip_to_str(tvb, offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_IP)); - proto_tree_add_item(subtree, hf_icq_status, tvb, offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_STATUS, 4, ENC_LITTLE_ENDIAN); - } + proto_tree *subtree = tree; + time_t theTime; + char *aTime; + guint32 port; + guint32 passwdLen; + + if (tree) { + theTime = tvb_get_letohl(tvb, offset + CMD_LOGIN_TIME); + aTime = abs_time_secs_to_str(wmem_packet_scope(), theTime, ABSOLUTE_TIME_LOCAL, TRUE); + proto_tree_add_text(subtree, tvb, offset + CMD_LOGIN_TIME, 4, + "Time: %ld = %s", (long)theTime, aTime); + port = tvb_get_letohl(tvb, offset + CMD_LOGIN_PORT); + proto_tree_add_text(subtree, tvb, offset + CMD_LOGIN_PORT, 4, + "Port: %u", port); + passwdLen = tvb_get_letohs(tvb, offset + CMD_LOGIN_PASSLEN); + proto_tree_add_text(subtree, tvb, offset + CMD_LOGIN_PASSLEN, + 2 + passwdLen, "Passwd: %.*s", (int)passwdLen, + tvb_get_string_enc(wmem_packet_scope(), tvb, offset + CMD_LOGIN_PASSWD, + passwdLen, ENC_ASCII)); + proto_tree_add_text(subtree, tvb, + offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_IP, + 4, "IP: %s", tvb_ip_to_str(tvb, offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_IP)); + proto_tree_add_item(subtree, hf_icq_status, tvb, offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_STATUS, 4, ENC_LITTLE_ENDIAN); + } } static void -icqv5_cmd_contact_list(proto_tree* tree, tvbuff_t *tvb, int offset) +icqv5_cmd_contact_list(proto_tree *tree, tvbuff_t *tvb, int offset) { - unsigned char num; - int i; - guint32 uin; - - if (tree) { - num = tvb_get_guint8(tvb, offset + CMD_CONTACT_LIST_NUM); - proto_tree_add_text(tree, tvb, offset + CMD_CONTACT_LIST, - 1, "Number of uins: %u", num); - /* - * A sequence of num times UIN follows - */ - offset += (CMD_CONTACT_LIST_NUM + 1); - for (i = 0; i < num; i++) { - uin = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, - "UIN[%d]: %u", i ,uin); - offset += 4; - } - } + unsigned char num; + int i; + guint32 uin; + + if (tree) { + num = tvb_get_guint8(tvb, offset + CMD_CONTACT_LIST_NUM); + proto_tree_add_text(tree, tvb, offset + CMD_CONTACT_LIST, + 1, "Number of uins: %u", num); + /* + * A sequence of num times UIN follows + */ + offset += (CMD_CONTACT_LIST_NUM + 1); + for (i = 0; i < num; i++) { + uin = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, + "UIN[%d]: %u", i ,uin); + offset += 4; + } + } } /********************** @@ -772,306 +772,306 @@ icqv5_cmd_contact_list(proto_tree* tree, tvbuff_t *tvb, int offset) ********************** */ static void -icqv5_srv_user_online(proto_tree* tree,/* Tree to put the data in */ - tvbuff_t *tvb, /* Tvbuff with packet */ - int offset) /* Offset from the start of the packet to the content */ +icqv5_srv_user_online(proto_tree *tree,/* Tree to put the data in */ + tvbuff_t *tvb, /* Tvbuff with packet */ + int offset) /* Offset from the start of the packet to the content */ { - proto_tree* subtree = tree; - - if (tree) { - proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_UIN, 4, - "UIN: %u", - tvb_get_letohl(tvb, offset + SRV_USER_ONL_UIN)); - proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_IP, 4, - "IP: %s", tvb_ip_to_str(tvb, offset + SRV_USER_ONL_IP)); - proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_PORT, 4, - "Port: %u", - tvb_get_letohl(tvb, offset + SRV_USER_ONL_PORT)); - proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_REALIP, 4, - "RealIP: %s", tvb_ip_to_str(tvb, offset + SRV_USER_ONL_REALIP)); - proto_tree_add_item(subtree, hf_icq_status, tvb, offset + SRV_USER_ONL_STATUS, 2, ENC_LITTLE_ENDIAN); - /* - * Kojak: Hypothesis is that this field might be an encoding for the - * version used by the UIN that changed. To test this, I included - * this line to the code. - */ - proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_X2, 4, - "Version: %08x", - tvb_get_letohl(tvb, offset + SRV_USER_ONL_X2)); - } + proto_tree *subtree = tree; + + if (tree) { + proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_UIN, 4, + "UIN: %u", + tvb_get_letohl(tvb, offset + SRV_USER_ONL_UIN)); + proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_IP, 4, + "IP: %s", tvb_ip_to_str(tvb, offset + SRV_USER_ONL_IP)); + proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_PORT, 4, + "Port: %u", + tvb_get_letohl(tvb, offset + SRV_USER_ONL_PORT)); + proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_REALIP, 4, + "RealIP: %s", tvb_ip_to_str(tvb, offset + SRV_USER_ONL_REALIP)); + proto_tree_add_item(subtree, hf_icq_status, tvb, offset + SRV_USER_ONL_STATUS, 2, ENC_LITTLE_ENDIAN); + /* + * Kojak: Hypothesis is that this field might be an encoding for the + * version used by the UIN that changed. To test this, I included + * this line to the code. + */ + proto_tree_add_text(subtree, tvb, offset + SRV_USER_ONL_X2, 4, + "Version: %08x", + tvb_get_letohl(tvb, offset + SRV_USER_ONL_X2)); + } } static void -icqv5_srv_multi(proto_tree* tree, /* Tree to put the data in */ - tvbuff_t *tvb, /* Packet content */ - int offset, /* Offset from the start of the packet to the content */ - packet_info* pinfo) +icqv5_srv_multi(proto_tree *tree, /* Tree to put the data in */ + tvbuff_t *tvb, /* Packet content */ + int offset, /* Offset from the start of the packet to the content */ + packet_info *pinfo) { - guint8 num; - guint16 pktSz; - int i; - - num = tvb_get_guint8(tvb, offset + SRV_MULTI_NUM); - proto_tree_add_text(tree, tvb, offset + SRV_MULTI_NUM, 1, - "Number of pkts: %u", num); - /* - * A sequence of num times ( pktsize, packetData) follows - */ - offset += (SRV_MULTI_NUM + 1); - for (i = 0; i < num; i++) { - pktSz = tvb_get_letohs(tvb, offset); - offset += 2; - dissect_icqv5Server(tvb, offset, pinfo, tree, pktSz); - offset += pktSz; - } + guint8 num; + guint16 pktSz; + int i; + + num = tvb_get_guint8(tvb, offset + SRV_MULTI_NUM); + proto_tree_add_text(tree, tvb, offset + SRV_MULTI_NUM, 1, + "Number of pkts: %u", num); + /* + * A sequence of num times ( pktsize, packetData) follows + */ + offset += (SRV_MULTI_NUM + 1); + for (i = 0; i < num; i++) { + pktSz = tvb_get_letohs(tvb, offset); + offset += 2; + dissect_icqv5Server(tvb, offset, pinfo, tree, pktSz); + offset += pktSz; + } } static void -icqv5_srv_meta_user(proto_tree* tree, /* Tree to put the data in */ - tvbuff_t *tvb, /* Tvbuff with packet */ - int offset, /* Offset from the start of the packet to the content */ - int size _U_, /* Number of chars left to do */ - packet_info *pinfo) +icqv5_srv_meta_user(proto_tree *tree, /* Tree to put the data in */ + tvbuff_t *tvb, /* Tvbuff with packet */ + int offset, /* Offset from the start of the packet to the content */ + int size _U_, /* Number of chars left to do */ + packet_info *pinfo) { - proto_tree* sstree; - proto_item* ti; - guint16 subcmd; - unsigned char result; - - subcmd = tvb_get_letohs(tvb, offset + SRV_META_USER_SUBCMD); - ti = proto_tree_add_item(tree, hf_icq_meta_user_subcmd, tvb, offset + SRV_META_USER_SUBCMD, 2, ENC_LITTLE_ENDIAN); - sstree = proto_item_add_subtree(ti, ett_icq_body_parts); - result = tvb_get_guint8(tvb, offset + SRV_META_USER_RESULT); - proto_tree_add_text(sstree, tvb, offset + SRV_META_USER_RESULT, - 1, "%s", (result==0x0a)?"Success":"Failure"); - - /* Skip the META_USER header */ - offset += 3; - - switch(subcmd) { - case META_EX_USER_FOUND: - { - /* This is almost the same as META_USER_FOUND, - * however, there's an extra length field - */ - guint16 pktLen; - - /* Read the length field */ - pktLen = tvb_get_letohs(tvb, offset); - proto_tree_add_text(sstree, tvb, offset, 2, - "Length: %u", pktLen); - - offset += 2; - } - /* FALLTHRU */ - case META_USER_FOUND: - { - /* The goto mentioned in this block should be local to this - * block if C'd allow it. - * - * They are used to "implement" a poorman's exception handling - */ - int len = 0; - static const char *descr[] = { - "Nick", - "First name", - "Last name", - "Email", - NULL - }; - const char** d = descr; - unsigned char auth; - /* - * Read UIN - */ - proto_tree_add_text(sstree, tvb, offset, 4, - "UIN: %u", tvb_get_letohl(tvb, offset)); - offset+=4; - - for ( ; *d!=NULL; d++) { - len = proto_add_icq_attr(sstree, tvb, offset, *d); - if (len == -1) - return; - offset += len; - } - /* Get the authorize setting */ - auth = tvb_get_guint8(tvb, offset); - proto_tree_add_text(sstree, tvb, offset, 1, - "authorization: %s", (auth==0x01)?"Necessary":"Who needs it"); - offset++; - /* Get x2 */ - proto_tree_add_text(sstree, tvb, offset, 2, - "x2: 0x%04x", tvb_get_letohs(tvb, offset)); - offset+=2; - /* Get x3 */ - proto_tree_add_text(sstree, tvb, offset, 4, - "x3: 0x%08x", tvb_get_letohl(tvb, offset)); - break; - } - case META_ABOUT: - { - int len; - - /* Get the about information */ - len = tvb_get_letohs(tvb, offset); - offset+=2; - proto_tree_add_text(sstree, tvb, offset - 2, - len+2, "About(%d): %.*s", len, - len, tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_ASCII)); - break; - } - case META_USER_INFO: - { - /* The goto mentioned in this block should be local to this - * block if C'd allow it. - * - * They are used to "implement" a poorman's exception handling - */ - static const char* descr[] = { - "Nick", - "First name", - "Last name", - "Primary email", - "Secondary email", - "Old email", - "City", - "State", - "Phone", - "Fax", - "Street", - "Cellphone", - "Zip", - NULL - }; - const char** d = descr; - guint16 country; - guint8 user_timezone; - guint8 auth; - int len = 0; + proto_tree *sstree; + proto_item *ti; + guint16 subcmd; + unsigned char result; + + subcmd = tvb_get_letohs(tvb, offset + SRV_META_USER_SUBCMD); + ti = proto_tree_add_item(tree, hf_icq_meta_user_subcmd, tvb, offset + SRV_META_USER_SUBCMD, 2, ENC_LITTLE_ENDIAN); + sstree = proto_item_add_subtree(ti, ett_icq_body_parts); + result = tvb_get_guint8(tvb, offset + SRV_META_USER_RESULT); + proto_tree_add_text(sstree, tvb, offset + SRV_META_USER_RESULT, + 1, "%s", (result==0x0a)?"Success":"Failure"); + + /* Skip the META_USER header */ + offset += 3; + + switch(subcmd) { + case META_EX_USER_FOUND: + { + /* This is almost the same as META_USER_FOUND, + * however, there's an extra length field + */ + guint16 pktLen; + + /* Read the length field */ + pktLen = tvb_get_letohs(tvb, offset); + proto_tree_add_text(sstree, tvb, offset, 2, + "Length: %u", pktLen); + + offset += 2; + } + /* FALLTHRU */ + case META_USER_FOUND: + { + /* The goto mentioned in this block should be local to this + * block if C'd allow it. + * + * They are used to "implement" a poorman's exception handling + */ + int len = 0; + static const char *descr[] = { + "Nick", + "First name", + "Last name", + "Email", + NULL + }; + const char **d = descr; + unsigned char auth; + /* + * Read UIN + */ + proto_tree_add_text(sstree, tvb, offset, 4, + "UIN: %u", tvb_get_letohl(tvb, offset)); + offset+=4; + + for ( ; *d!=NULL; d++) { + len = proto_add_icq_attr(sstree, tvb, offset, *d); + if (len == -1) + return; + offset += len; + } + /* Get the authorize setting */ + auth = tvb_get_guint8(tvb, offset); + proto_tree_add_text(sstree, tvb, offset, 1, + "authorization: %s", (auth==0x01)?"Necessary":"Who needs it"); + offset++; + /* Get x2 */ + proto_tree_add_text(sstree, tvb, offset, 2, + "x2: 0x%04x", tvb_get_letohs(tvb, offset)); + offset+=2; + /* Get x3 */ + proto_tree_add_text(sstree, tvb, offset, 4, + "x3: 0x%08x", tvb_get_letohl(tvb, offset)); + break; + } + case META_ABOUT: + { + int len; + + /* Get the about information */ + len = tvb_get_letohs(tvb, offset); + offset+=2; + proto_tree_add_text(sstree, tvb, offset - 2, + len+2, "About(%d): %.*s", len, + len, tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_ASCII)); + break; + } + case META_USER_INFO: + { + /* The goto mentioned in this block should be local to this + * block if C'd allow it. + * + * They are used to "implement" a poorman's exception handling + */ + static const char *descr[] = { + "Nick", + "First name", + "Last name", + "Primary email", + "Secondary email", + "Old email", + "City", + "State", + "Phone", + "Fax", + "Street", + "Cellphone", + "Zip", + NULL + }; + const char **d = descr; + guint16 country; + guint8 user_timezone; + guint8 auth; + int len = 0; #if 0 - /* Get the uin */ - uin = tvb_get_letohl(tvb, offset); - proto_tree_add_text(sstree, tvb, offset, 4, "UIN: %u", uin); - offset+=4; + /* Get the uin */ + uin = tvb_get_letohl(tvb, offset); + proto_tree_add_text(sstree, tvb, offset, 4, "UIN: %u", uin); + offset+=4; #endif - /* - * Get every field from the description - */ - for ( ; *d!=NULL; d++) { - len = proto_add_icq_attr(sstree, tvb, offset, *d); - if (len < 0) { - offset+=2; - continue; - } - offset+=len; - } - /* Get country code */ - country = tvb_get_letohs(tvb, offset); - proto_tree_add_text(sstree, tvb, offset, 2, - "Countrycode: %u", country); - offset+=2; - /* Get the timezone setting */ - user_timezone = tvb_get_guint8(tvb, offset); - proto_tree_add_text(sstree, tvb, offset, 1, - "Timezone: %u", user_timezone); - offset++; - /* Get the authorize setting */ - auth = tvb_get_guint8(tvb, offset); - proto_tree_add_text(sstree, tvb, offset, 1, - "Authorization: (%u) %s", auth, - (auth==0)?"No":"Yes"); - offset++; - /* Get the webaware setting */ - auth = tvb_get_guint8(tvb, offset); - proto_tree_add_text(sstree, tvb, offset, 1, - "Webaware: (%u) %s", auth, - (auth==0)?"No":"Yes"); - offset++; - /* Get the authorize setting */ - auth = tvb_get_guint8(tvb, offset); - proto_tree_add_text(sstree, tvb, offset, 1, - "HideIP: (%u) %s", auth, (auth==0)?"No":"Yes"); - break; - } - default: - /* This information is already printed in the tree */ - expert_add_info_format(pinfo, ti, &ei_icq_unknown_meta_subcmd, - "Unknown Meta subcmd: 0x%x", subcmd); - break; - } + /* + * Get every field from the description + */ + for ( ; *d!=NULL; d++) { + len = proto_add_icq_attr(sstree, tvb, offset, *d); + if (len < 0) { + offset+=2; + continue; + } + offset+=len; + } + /* Get country code */ + country = tvb_get_letohs(tvb, offset); + proto_tree_add_text(sstree, tvb, offset, 2, + "Countrycode: %u", country); + offset+=2; + /* Get the timezone setting */ + user_timezone = tvb_get_guint8(tvb, offset); + proto_tree_add_text(sstree, tvb, offset, 1, + "Timezone: %u", user_timezone); + offset++; + /* Get the authorize setting */ + auth = tvb_get_guint8(tvb, offset); + proto_tree_add_text(sstree, tvb, offset, 1, + "Authorization: (%u) %s", auth, + (auth==0)?"No":"Yes"); + offset++; + /* Get the webaware setting */ + auth = tvb_get_guint8(tvb, offset); + proto_tree_add_text(sstree, tvb, offset, 1, + "Webaware: (%u) %s", auth, + (auth==0)?"No":"Yes"); + offset++; + /* Get the authorize setting */ + auth = tvb_get_guint8(tvb, offset); + proto_tree_add_text(sstree, tvb, offset, 1, + "HideIP: (%u) %s", auth, (auth==0)?"No":"Yes"); + break; + } + default: + /* This information is already printed in the tree */ + expert_add_info_format(pinfo, ti, &ei_icq_unknown_meta_subcmd, + "Unknown Meta subcmd: 0x%x", subcmd); + break; + } } static void -icqv5_srv_recv_message(proto_tree* tree, /* Tree to put the data in */ - tvbuff_t* tvb, /* Packet content */ - int offset, /* Offset from the start of the packet to the content */ - int size, /* Number of chars left to do */ - packet_info *pinfo) +icqv5_srv_recv_message(proto_tree *tree, /* Tree to put the data in */ + tvbuff_t *tvb, /* Packet content */ + int offset, /* Offset from the start of the packet to the content */ + int size, /* Number of chars left to do */ + packet_info *pinfo) { - guint16 year; - guint8 month; - guint8 day; - guint8 hour; - guint8 minute; - - proto_tree_add_item(tree, hf_icq_uin, tvb, offset + SRV_RECV_MSG_UIN, - 4, ENC_LITTLE_ENDIAN); - year = tvb_get_letohs(tvb, offset + SRV_RECV_MSG_YEAR); - month = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_MONTH); - day = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_DAY); - hour = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_HOUR); - minute = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_MINUTE); - - proto_tree_add_text(tree, tvb, offset + SRV_RECV_MSG_YEAR, - 2 + 4, - "Time: %u-%u-%u %02u:%02u", - day, month, year, hour, minute); - icqv5_decode_msgType(tree, tvb, offset + SRV_RECV_MSG_MSG_TYPE, - size-10, pinfo); + guint16 year; + guint8 month; + guint8 day; + guint8 hour; + guint8 minute; + + proto_tree_add_item(tree, hf_icq_uin, tvb, offset + SRV_RECV_MSG_UIN, + 4, ENC_LITTLE_ENDIAN); + year = tvb_get_letohs(tvb, offset + SRV_RECV_MSG_YEAR); + month = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_MONTH); + day = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_DAY); + hour = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_HOUR); + minute = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_MINUTE); + + proto_tree_add_text(tree, tvb, offset + SRV_RECV_MSG_YEAR, + 2 + 4, + "Time: %u-%u-%u %02u:%02u", + day, month, year, hour, minute); + icqv5_decode_msgType(tree, tvb, offset + SRV_RECV_MSG_MSG_TYPE, + size-10, pinfo); } static void -icqv5_srv_rand_user(proto_tree* tree, /* Tree to put the data in */ - tvbuff_t *tvb, /* Tvbuff with packet */ - int offset) /* Offset from the start of the packet to the content */ +icqv5_srv_rand_user(proto_tree *tree, /* Tree to put the data in */ + tvbuff_t *tvb, /* Tvbuff with packet */ + int offset) /* Offset from the start of the packet to the content */ { - proto_tree* subtree = tree; - guint32 uin; - guint32 port; - guint8 commClass; - guint16 tcpVer; - - if (tree) { - /* guint32 UIN */ - uin = tvb_get_letohl(tvb, offset + SRV_RAND_USER_UIN); - proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_UIN, - 4, "UIN: %u", uin); - /* guint32 IP */ - proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_IP, - 4, "IP: %s", tvb_ip_to_str(tvb, offset + SRV_RAND_USER_IP)); - /* guint16 portNum */ - /* XXX - 16 bits, or 32 bits? */ - port = tvb_get_letohs(tvb, offset + SRV_RAND_USER_PORT); - proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_UIN, - 4, "Port: %u", port); - /* guint32 realIP */ - proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_REAL_IP, - 4, "RealIP: %s", tvb_ip_to_str(tvb, offset + SRV_RAND_USER_REAL_IP)); - /* guint8 Communication Class */ - commClass = tvb_get_guint8(tvb, offset + SRV_RAND_USER_CLASS); - proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_CLASS, - 1, "Class: %s", - (commClass!=4)?"User to User":"Through Server"); - /* guint32 status */ - /* XXX - 16 bits, or 32 bits? */ - proto_tree_add_item(subtree, hf_icq_status, tvb, offset + SRV_RAND_USER_STATUS, 4, ENC_LITTLE_ENDIAN); - - /* guint16 tcpVersion */ - tcpVer = tvb_get_letohs(tvb, offset + SRV_RAND_USER_TCP_VER); - proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_TCP_VER, - 2, "TCPVersion: %u", tcpVer); - } + proto_tree *subtree = tree; + guint32 uin; + guint32 port; + guint8 commClass; + guint16 tcpVer; + + if (tree) { + /* guint32 UIN */ + uin = tvb_get_letohl(tvb, offset + SRV_RAND_USER_UIN); + proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_UIN, + 4, "UIN: %u", uin); + /* guint32 IP */ + proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_IP, + 4, "IP: %s", tvb_ip_to_str(tvb, offset + SRV_RAND_USER_IP)); + /* guint16 portNum */ + /* XXX - 16 bits, or 32 bits? */ + port = tvb_get_letohs(tvb, offset + SRV_RAND_USER_PORT); + proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_UIN, + 4, "Port: %u", port); + /* guint32 realIP */ + proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_REAL_IP, + 4, "RealIP: %s", tvb_ip_to_str(tvb, offset + SRV_RAND_USER_REAL_IP)); + /* guint8 Communication Class */ + commClass = tvb_get_guint8(tvb, offset + SRV_RAND_USER_CLASS); + proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_CLASS, + 1, "Class: %s", + (commClass!=4)?"User to User":"Through Server"); + /* guint32 status */ + /* XXX - 16 bits, or 32 bits? */ + proto_tree_add_item(subtree, hf_icq_status, tvb, offset + SRV_RAND_USER_STATUS, 4, ENC_LITTLE_ENDIAN); + + /* guint16 tcpVersion */ + tcpVer = tvb_get_letohs(tvb, offset + SRV_RAND_USER_TCP_VER); + proto_tree_add_text(subtree, tvb, offset + SRV_RAND_USER_TCP_VER, + 2, "TCPVersion: %u", tcpVer); + } } /* @@ -1080,227 +1080,227 @@ icqv5_srv_rand_user(proto_tree* tree, /* Tree to put the data in */ static void dissect_icqv5Client(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - proto_tree *icq_header_tree, *icq_body_tree; - proto_item *ti, *cmd_item; - - int pktsize; /* The actual size of the ICQ content */ - int capturedsize; /* The captured size of the ICQ content */ - guint32 rounded_size; - guint32 code, key; - guint16 cmd; - guint8 *decr_pd; /* Decrypted content */ - tvbuff_t *decr_tvb; - - pktsize = tvb_reported_length(tvb); - capturedsize = tvb_length(tvb); - - /* Get the encryption key */ - code = tvb_get_letohl(tvb, ICQ5_CL_CHECKCODE); - key = get_v5key(code, pktsize); - - /* - * Make a copy of the packet data, and decrypt it. - * The decryption processes 4 bytes at a time, and starts at - * an offset of ICQ5_CL_SESSIONID (which isn't a multiple of 4), - * so we make sure that there are - * - * (ICQ5_CL_SESSIONID + a multiple of 4) - * - * bytes in the buffer. - */ - rounded_size = ((((capturedsize - ICQ5_CL_SESSIONID) + 3)/4)*4) + ICQ5_CL_SESSIONID; - /* rounded_size might exceed the tvb bounds so we can't just use tvb_memdup here. */ - decr_pd = (guint8 *)g_malloc(rounded_size); - tvb_memcpy(tvb, decr_pd, 0, capturedsize); - decrypt_v5(decr_pd, rounded_size, key); - - /* Allocate a new tvbuff, referring to the decrypted data. */ - decr_tvb = tvb_new_child_real_data(tvb, decr_pd, capturedsize, pktsize); - - /* Arrange that the allocated packet data copy be freed when the - tvbuff is freed. */ - tvb_set_free_cb(decr_tvb, g_free); - - /* Add the decrypted data to the data source list. */ - add_new_data_source(pinfo, decr_tvb, "Decrypted"); - - cmd = tvb_get_letohs(decr_tvb, ICQ5_CL_CMD); - - col_add_fstr(pinfo->cinfo, COL_INFO, "ICQv5 %s", val_to_str_const(cmd, clientCmdCode, "Unknown")); - - icq_header_tree = proto_tree_add_subtree(tree, tvb, 0, ICQ5_CL_HDRSIZE, ett_icq_header, NULL, "Header"); - - ti = proto_tree_add_boolean(icq_header_tree, hf_icq_type, tvb, 0, 0, ICQ5_CLIENT); - PROTO_ITEM_SET_GENERATED(ti); - - proto_tree_add_item(icq_header_tree, hf_icq_version, tvb, ICQ_VERSION, 2, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_uin, tvb, ICQ5_CL_UIN, 4, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_sessionid, decr_tvb, ICQ5_CL_SESSIONID, 4, ENC_LITTLE_ENDIAN); - cmd_item = proto_tree_add_item(icq_header_tree, hf_icq_client_cmd, decr_tvb, ICQ5_CL_CMD, 2, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_seqnum1, decr_tvb, ICQ5_CL_SEQNUM1, 2, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_seqnum2, decr_tvb, ICQ5_CL_SEQNUM2, 2, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_checkcode, tvb, ICQ5_CL_CHECKCODE, 4, ENC_LITTLE_ENDIAN); - ti = proto_tree_add_uint(icq_header_tree, hf_icq_checkcode_key, tvb, ICQ5_CL_CHECKCODE, 4, key); - PROTO_ITEM_SET_GENERATED(ti); - - icq_body_tree = proto_tree_add_subtree(tree, decr_tvb, ICQ5_CL_HDRSIZE, pktsize - ICQ5_CL_HDRSIZE, ett_icq_body, NULL, "Body"); - - switch(cmd) { - case CMD_ACK: - proto_tree_add_item(icq_body_tree, hf_icq_ack_random, decr_tvb, ICQ5_CL_HDRSIZE + CMD_ACK_RANDOM, 4, ENC_LITTLE_ENDIAN); - break; - case CMD_SEND_MSG: - case CMD_MSG_TO_NEW_USER: - icqv5_cmd_send_msg(icq_body_tree, decr_tvb, ICQ5_CL_HDRSIZE, - pktsize - ICQ5_CL_HDRSIZE, pinfo); - break; - case CMD_RAND_SEARCH: - proto_tree_add_item(icq_body_tree, hf_icq_group, decr_tvb, ICQ5_CL_HDRSIZE + CMD_RAND_SEARCH_GROUP, 4, ENC_LITTLE_ENDIAN); - break; - case CMD_LOGIN: - icqv5_cmd_login(icq_body_tree, decr_tvb, ICQ5_CL_HDRSIZE); - break; - case CMD_SEND_TEXT_CODE: - icqv5_cmd_send_text_code(icq_body_tree, decr_tvb, ICQ5_CL_HDRSIZE); - break; - case CMD_STATUS_CHANGE: - proto_tree_add_item(icq_body_tree, hf_icq_status, decr_tvb, ICQ5_CL_HDRSIZE + CMD_STATUS_CHANGE_STATUS, 4, ENC_LITTLE_ENDIAN); - break; - case CMD_ACK_MESSAGES: - proto_tree_add_item(icq_body_tree, hf_icq_ack_random, decr_tvb, ICQ5_CL_HDRSIZE + CMD_ACK_MESSAGES_RANDOM, 4, ENC_LITTLE_ENDIAN); - break; - case CMD_KEEP_ALIVE: - proto_tree_add_item(icq_body_tree, hf_icq_keep_alive_random, decr_tvb, ICQ5_CL_HDRSIZE + CMD_KEEP_ALIVE_RANDOM, 4, ENC_LITTLE_ENDIAN); - break; - case CMD_ADD_TO_LIST: - proto_tree_add_item(icq_body_tree, hf_icq_uin, decr_tvb, ICQ5_CL_HDRSIZE + CMD_ADD_TO_LIST_UIN, 4, ENC_LITTLE_ENDIAN); - break; - case CMD_CONTACT_LIST: - icqv5_cmd_contact_list(icq_body_tree, decr_tvb, ICQ5_CL_HDRSIZE); - break; - case CMD_META_USER: - case CMD_REG_NEW_USER: - case CMD_QUERY_SERVERS: - case CMD_QUERY_ADDONS: - proto_tree_add_text(icq_body_tree, tvb, ICQ5_CL_HDRSIZE, 0, "No parameters"); - break; - default: - expert_add_info(pinfo, cmd_item, &ei_icq_unknown_command); - break; - } + proto_tree *icq_header_tree, *icq_body_tree; + proto_item *ti, *cmd_item; + + int pktsize; /* The actual size of the ICQ content */ + int capturedsize; /* The captured size of the ICQ content */ + guint32 rounded_size; + guint32 code, key; + guint16 cmd; + guint8 *decr_pd; /* Decrypted content */ + tvbuff_t *decr_tvb; + + pktsize = tvb_reported_length(tvb); + capturedsize = tvb_length(tvb); + + /* Get the encryption key */ + code = tvb_get_letohl(tvb, ICQ5_CL_CHECKCODE); + key = get_v5key(code, pktsize); + + /* + * Make a copy of the packet data, and decrypt it. + * The decryption processes 4 bytes at a time, and starts at + * an offset of ICQ5_CL_SESSIONID (which isn't a multiple of 4), + * so we make sure that there are + * + * (ICQ5_CL_SESSIONID + a multiple of 4) + * + * bytes in the buffer. + */ + rounded_size = ((((capturedsize - ICQ5_CL_SESSIONID) + 3)/4)*4) + ICQ5_CL_SESSIONID; + /* rounded_size might exceed the tvb bounds so we can't just use tvb_memdup here. */ + decr_pd = (guint8 *)g_malloc(rounded_size); + tvb_memcpy(tvb, decr_pd, 0, capturedsize); + decrypt_v5(decr_pd, rounded_size, key); + + /* Allocate a new tvbuff, referring to the decrypted data. */ + decr_tvb = tvb_new_child_real_data(tvb, decr_pd, capturedsize, pktsize); + + /* Arrange that the allocated packet data copy be freed when the + tvbuff is freed. */ + tvb_set_free_cb(decr_tvb, g_free); + + /* Add the decrypted data to the data source list. */ + add_new_data_source(pinfo, decr_tvb, "Decrypted"); + + cmd = tvb_get_letohs(decr_tvb, ICQ5_CL_CMD); + + col_add_fstr(pinfo->cinfo, COL_INFO, "ICQv5 %s", val_to_str_const(cmd, clientCmdCode, "Unknown")); + + icq_header_tree = proto_tree_add_subtree(tree, tvb, 0, ICQ5_CL_HDRSIZE, ett_icq_header, NULL, "Header"); + + ti = proto_tree_add_boolean(icq_header_tree, hf_icq_type, tvb, 0, 0, ICQ5_CLIENT); + PROTO_ITEM_SET_GENERATED(ti); + + proto_tree_add_item(icq_header_tree, hf_icq_version, tvb, ICQ_VERSION, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_uin, tvb, ICQ5_CL_UIN, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_sessionid, decr_tvb, ICQ5_CL_SESSIONID, 4, ENC_LITTLE_ENDIAN); + cmd_item = proto_tree_add_item(icq_header_tree, hf_icq_client_cmd, decr_tvb, ICQ5_CL_CMD, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_seqnum1, decr_tvb, ICQ5_CL_SEQNUM1, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_seqnum2, decr_tvb, ICQ5_CL_SEQNUM2, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_checkcode, tvb, ICQ5_CL_CHECKCODE, 4, ENC_LITTLE_ENDIAN); + ti = proto_tree_add_uint(icq_header_tree, hf_icq_checkcode_key, tvb, ICQ5_CL_CHECKCODE, 4, key); + PROTO_ITEM_SET_GENERATED(ti); + + icq_body_tree = proto_tree_add_subtree(tree, decr_tvb, ICQ5_CL_HDRSIZE, pktsize - ICQ5_CL_HDRSIZE, ett_icq_body, NULL, "Body"); + + switch(cmd) { + case CMD_ACK: + proto_tree_add_item(icq_body_tree, hf_icq_ack_random, decr_tvb, ICQ5_CL_HDRSIZE + CMD_ACK_RANDOM, 4, ENC_LITTLE_ENDIAN); + break; + case CMD_SEND_MSG: + case CMD_MSG_TO_NEW_USER: + icqv5_cmd_send_msg(icq_body_tree, decr_tvb, ICQ5_CL_HDRSIZE, + pktsize - ICQ5_CL_HDRSIZE, pinfo); + break; + case CMD_RAND_SEARCH: + proto_tree_add_item(icq_body_tree, hf_icq_group, decr_tvb, ICQ5_CL_HDRSIZE + CMD_RAND_SEARCH_GROUP, 4, ENC_LITTLE_ENDIAN); + break; + case CMD_LOGIN: + icqv5_cmd_login(icq_body_tree, decr_tvb, ICQ5_CL_HDRSIZE); + break; + case CMD_SEND_TEXT_CODE: + icqv5_cmd_send_text_code(icq_body_tree, decr_tvb, ICQ5_CL_HDRSIZE); + break; + case CMD_STATUS_CHANGE: + proto_tree_add_item(icq_body_tree, hf_icq_status, decr_tvb, ICQ5_CL_HDRSIZE + CMD_STATUS_CHANGE_STATUS, 4, ENC_LITTLE_ENDIAN); + break; + case CMD_ACK_MESSAGES: + proto_tree_add_item(icq_body_tree, hf_icq_ack_random, decr_tvb, ICQ5_CL_HDRSIZE + CMD_ACK_MESSAGES_RANDOM, 4, ENC_LITTLE_ENDIAN); + break; + case CMD_KEEP_ALIVE: + proto_tree_add_item(icq_body_tree, hf_icq_keep_alive_random, decr_tvb, ICQ5_CL_HDRSIZE + CMD_KEEP_ALIVE_RANDOM, 4, ENC_LITTLE_ENDIAN); + break; + case CMD_ADD_TO_LIST: + proto_tree_add_item(icq_body_tree, hf_icq_uin, decr_tvb, ICQ5_CL_HDRSIZE + CMD_ADD_TO_LIST_UIN, 4, ENC_LITTLE_ENDIAN); + break; + case CMD_CONTACT_LIST: + icqv5_cmd_contact_list(icq_body_tree, decr_tvb, ICQ5_CL_HDRSIZE); + break; + case CMD_META_USER: + case CMD_REG_NEW_USER: + case CMD_QUERY_SERVERS: + case CMD_QUERY_ADDONS: + proto_tree_add_text(icq_body_tree, tvb, ICQ5_CL_HDRSIZE, 0, "No parameters"); + break; + default: + expert_add_info(pinfo, cmd_item, &ei_icq_unknown_command); + break; + } } static void dissect_icqv5Server(tvbuff_t *tvb, int offset, packet_info *pinfo, - proto_tree *tree, int pktsize) + proto_tree *tree, int pktsize) { - /* Server traffic is easy, not encrypted */ - proto_tree *icq_header_tree, *icq_body_tree; - proto_item *ti, *cmd_item; - - guint16 cmd = tvb_get_letohs(tvb, offset + ICQ5_SRV_CMD); - - if (pktsize == -1) { - col_add_fstr(pinfo->cinfo, COL_INFO, "ICQv5 %s", val_to_str_const(cmd, serverCmdCode, "Unknown")); - pktsize = tvb_reported_length(tvb); - } - - icq_header_tree = proto_tree_add_subtree(tree, tvb, offset, ICQ5_SRV_HDRSIZE, ett_icq_header, NULL, "Header"); - - ti = proto_tree_add_boolean(icq_header_tree, hf_icq_type, tvb, 0, 0, ICQ5_SERVER); - PROTO_ITEM_SET_GENERATED(ti); - - proto_tree_add_item(icq_header_tree, hf_icq_version, tvb, offset + ICQ_VERSION, 2, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_sessionid, tvb, offset + ICQ5_SRV_SESSIONID, 4, ENC_LITTLE_ENDIAN); - cmd_item = proto_tree_add_item(icq_header_tree, hf_icq_server_cmd, tvb, offset + ICQ5_SRV_CMD, 2, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_seqnum1, tvb, offset + ICQ5_SRV_SEQNUM1, 2, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_seqnum2, tvb, offset + ICQ5_SRV_SEQNUM2, 2, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_uin, tvb, offset + ICQ5_SRV_UIN, 4, ENC_LITTLE_ENDIAN); - proto_tree_add_item(icq_header_tree, hf_icq_checkcode, tvb, offset + ICQ5_SRV_CHECKCODE, 4, ENC_LITTLE_ENDIAN); - - icq_body_tree = proto_tree_add_subtree(tree, tvb, ICQ5_CL_HDRSIZE, pktsize - ICQ5_SRV_HDRSIZE, ett_icq_body, NULL, "Body"); - - switch (cmd) { - case SRV_RAND_USER: - icqv5_srv_rand_user(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE); - break; - case SRV_SYS_DELIVERED_MESS: - /* The message structures are all the same. Why not run - * the same routine? */ - icqv5_cmd_send_msg(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, - pktsize - ICQ5_SRV_HDRSIZE, pinfo); - break; - case SRV_USER_ONLINE: - icqv5_srv_user_online(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE); - break; - case SRV_USER_OFFLINE: - proto_tree_add_item(icq_body_tree, hf_icq_uin, tvb, offset + ICQ5_SRV_HDRSIZE + SRV_USER_OFFLINE_UIN, 4, ENC_LITTLE_ENDIAN); - break; - case SRV_LOGIN_REPLY: - proto_tree_add_text(tree, tvb, offset + ICQ5_SRV_HDRSIZE + SRV_LOGIN_REPLY_IP, 4, - "IP: %s", tvb_ip_to_str(tvb, offset + ICQ5_SRV_HDRSIZE + SRV_LOGIN_REPLY_IP)); - break; - case SRV_META_USER: - icqv5_srv_meta_user(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, - pktsize - ICQ5_SRV_HDRSIZE, pinfo); - break; - case SRV_RECV_MESSAGE: - icqv5_srv_recv_message(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, - pktsize - ICQ5_SRV_HDRSIZE, pinfo); - break; - case SRV_MULTI: - icqv5_srv_multi(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, pinfo); - break; - case SRV_ACK: - case SRV_SILENT_TOO_LONG: - case SRV_GO_AWAY: - case SRV_NEW_UIN: - case SRV_BAD_PASS: - case SRV_UPDATE_SUCCESS: - proto_tree_add_text(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, 0, "No Parameters"); - break; - default: - expert_add_info(pinfo, cmd_item, &ei_icq_unknown_command); - break; - } + /* Server traffic is easy, not encrypted */ + proto_tree *icq_header_tree, *icq_body_tree; + proto_item *ti, *cmd_item; + + guint16 cmd = tvb_get_letohs(tvb, offset + ICQ5_SRV_CMD); + + if (pktsize == -1) { + col_add_fstr(pinfo->cinfo, COL_INFO, "ICQv5 %s", val_to_str_const(cmd, serverCmdCode, "Unknown")); + pktsize = tvb_reported_length(tvb); + } + + icq_header_tree = proto_tree_add_subtree(tree, tvb, offset, ICQ5_SRV_HDRSIZE, ett_icq_header, NULL, "Header"); + + ti = proto_tree_add_boolean(icq_header_tree, hf_icq_type, tvb, 0, 0, ICQ5_SERVER); + PROTO_ITEM_SET_GENERATED(ti); + + proto_tree_add_item(icq_header_tree, hf_icq_version, tvb, offset + ICQ_VERSION, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_sessionid, tvb, offset + ICQ5_SRV_SESSIONID, 4, ENC_LITTLE_ENDIAN); + cmd_item = proto_tree_add_item(icq_header_tree, hf_icq_server_cmd, tvb, offset + ICQ5_SRV_CMD, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_seqnum1, tvb, offset + ICQ5_SRV_SEQNUM1, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_seqnum2, tvb, offset + ICQ5_SRV_SEQNUM2, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_uin, tvb, offset + ICQ5_SRV_UIN, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(icq_header_tree, hf_icq_checkcode, tvb, offset + ICQ5_SRV_CHECKCODE, 4, ENC_LITTLE_ENDIAN); + + icq_body_tree = proto_tree_add_subtree(tree, tvb, ICQ5_CL_HDRSIZE, pktsize - ICQ5_SRV_HDRSIZE, ett_icq_body, NULL, "Body"); + + switch (cmd) { + case SRV_RAND_USER: + icqv5_srv_rand_user(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE); + break; + case SRV_SYS_DELIVERED_MESS: + /* The message structures are all the same. Why not run + * the same routine? */ + icqv5_cmd_send_msg(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, + pktsize - ICQ5_SRV_HDRSIZE, pinfo); + break; + case SRV_USER_ONLINE: + icqv5_srv_user_online(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE); + break; + case SRV_USER_OFFLINE: + proto_tree_add_item(icq_body_tree, hf_icq_uin, tvb, offset + ICQ5_SRV_HDRSIZE + SRV_USER_OFFLINE_UIN, 4, ENC_LITTLE_ENDIAN); + break; + case SRV_LOGIN_REPLY: + proto_tree_add_text(tree, tvb, offset + ICQ5_SRV_HDRSIZE + SRV_LOGIN_REPLY_IP, 4, + "IP: %s", tvb_ip_to_str(tvb, offset + ICQ5_SRV_HDRSIZE + SRV_LOGIN_REPLY_IP)); + break; + case SRV_META_USER: + icqv5_srv_meta_user(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, + pktsize - ICQ5_SRV_HDRSIZE, pinfo); + break; + case SRV_RECV_MESSAGE: + icqv5_srv_recv_message(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, + pktsize - ICQ5_SRV_HDRSIZE, pinfo); + break; + case SRV_MULTI: + icqv5_srv_multi(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, pinfo); + break; + case SRV_ACK: + case SRV_SILENT_TOO_LONG: + case SRV_GO_AWAY: + case SRV_NEW_UIN: + case SRV_BAD_PASS: + case SRV_UPDATE_SUCCESS: + proto_tree_add_text(icq_body_tree, tvb, offset + ICQ5_SRV_HDRSIZE, 0, "No Parameters"); + break; + default: + expert_add_info(pinfo, cmd_item, &ei_icq_unknown_command); + break; + } } static void dissect_icqv5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - if (tvb_get_letohl(tvb, ICQ5_UNKNOWN) == 0) { - dissect_icqv5Client(tvb, pinfo, tree); - } else { - dissect_icqv5Server(tvb, 0, pinfo, tree, -1); - } + if (tvb_get_letohl(tvb, ICQ5_UNKNOWN) == 0) { + dissect_icqv5Client(tvb, pinfo, tree); + } else { + dissect_icqv5Server(tvb, 0, pinfo, tree, -1); + } } static int dissect_icq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { - int version; - proto_item *ti; - proto_tree *icq_tree; - - version = tvb_get_letohs(tvb, ICQ_VERSION); - if (version < 2 || version > 5) - return 0; /* This is not a (recognized) ICQ packet */ - - col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "ICQv%d", version); - col_add_fstr(pinfo->cinfo, COL_INFO, "ICQ Version %d protocol", version); - - ti = proto_tree_add_protocol_format(tree, proto_icq, tvb, 0, -1, "ICQv%d", version); - icq_tree = proto_item_add_subtree(ti, ett_icq); - - if (version == 5) - { - dissect_icqv5(tvb, pinfo, icq_tree); - } - else - { - proto_tree_add_item(icq_tree, hf_icq_version, tvb, ICQ_VERSION, 2, ENC_LITTLE_ENDIAN); - } - - return (tvb_length(tvb)); + int version; + proto_item *ti; + proto_tree *icq_tree; + + version = tvb_get_letohs(tvb, ICQ_VERSION); + if (version < 2 || version > 5) + return 0; /* This is not a (recognized) ICQ packet */ + + col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "ICQv%d", version); + col_add_fstr(pinfo->cinfo, COL_INFO, "ICQ Version %d protocol", version); + + ti = proto_tree_add_protocol_format(tree, proto_icq, tvb, 0, -1, "ICQv%d", version); + icq_tree = proto_item_add_subtree(ti, ett_icq); + + if (version == 5) + { + dissect_icqv5(tvb, pinfo, icq_tree); + } + else + { + proto_tree_add_item(icq_tree, hf_icq_version, tvb, ICQ_VERSION, 2, ENC_LITTLE_ENDIAN); + } + + return (tvb_length(tvb)); } /* registration with the filtering engine */ @@ -1308,79 +1308,79 @@ void proto_register_icq(void) { static hf_register_info hf[] = { - { &hf_icq_version, - {"Version", "icq.version", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_type, - {"Client/Server", "icq.client", FT_BOOLEAN, BASE_NONE, TFS(&tfs_client_server), 0x0, NULL, HFILL }}, - { &hf_icq_msg_type, - {"Type", "icq.msg_type", FT_UINT16, BASE_DEC, VALS(msgTypeCode), 0x0, NULL, HFILL }}, - { &hf_icq_uin, - {"UIN", "icq.uin", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_sessionid, - {"Session ID", "icq.sessionid", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_client_cmd, - {"Client command", "icq.client_cmd", FT_UINT16, BASE_DEC, VALS(clientCmdCode), 0x0, NULL, HFILL }}, - { &hf_icq_server_cmd, - {"Server command", "icq.server_cmd", FT_UINT16, BASE_DEC, VALS(serverCmdCode), 0x0, NULL, HFILL }}, - { &hf_icq_checkcode, - {"Checkcode", "icq.checkcode", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_checkcode_key, - {"Key", "icq.checkcode_key", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_seqnum1, - {"Seq Number 1", "icq.seqnum1", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_seqnum2, - {"Seq Number 2", "icq.seqnum2", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_group, - {"Group", "icq.group", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_ack_random, - {"Random", "icq.ack.random", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_keep_alive_random, - {"Random", "icq.keep_alive.random", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_icq_status, - {"Client command", "icq.status", FT_UINT32, BASE_DEC, VALS(statusCode), 0x0, NULL, HFILL }}, - { &hf_icq_meta_user_subcmd, - {"Subcommand", "icq.meta_user.subcmd", FT_UINT16, BASE_DEC, VALS(serverMetaSubCmdCode), 0x0, NULL, HFILL }}, + { &hf_icq_version, + {"Version", "icq.version", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_type, + {"Client/Server", "icq.client", FT_BOOLEAN, BASE_NONE, TFS(&tfs_client_server), 0x0, NULL, HFILL }}, + { &hf_icq_msg_type, + {"Type", "icq.msg_type", FT_UINT16, BASE_DEC, VALS(msgTypeCode), 0x0, NULL, HFILL }}, + { &hf_icq_uin, + {"UIN", "icq.uin", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_sessionid, + {"Session ID", "icq.sessionid", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_client_cmd, + {"Client command", "icq.client_cmd", FT_UINT16, BASE_DEC, VALS(clientCmdCode), 0x0, NULL, HFILL }}, + { &hf_icq_server_cmd, + {"Server command", "icq.server_cmd", FT_UINT16, BASE_DEC, VALS(serverCmdCode), 0x0, NULL, HFILL }}, + { &hf_icq_checkcode, + {"Checkcode", "icq.checkcode", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_checkcode_key, + {"Key", "icq.checkcode_key", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_seqnum1, + {"Seq Number 1", "icq.seqnum1", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_seqnum2, + {"Seq Number 2", "icq.seqnum2", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_group, + {"Group", "icq.group", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_ack_random, + {"Random", "icq.ack.random", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_keep_alive_random, + {"Random", "icq.keep_alive.random", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_icq_status, + {"Client command", "icq.status", FT_UINT32, BASE_DEC, VALS(statusCode), 0x0, NULL, HFILL }}, + { &hf_icq_meta_user_subcmd, + {"Subcommand", "icq.meta_user.subcmd", FT_UINT16, BASE_DEC, VALS(serverMetaSubCmdCode), 0x0, NULL, HFILL }}, + }; + + + static gint *ett[] = { + &ett_icq, + &ett_icq_header, + &ett_icq_body, + &ett_icq_body_parts, + }; + static ei_register_info ei[] = { + { &ei_icq_unknown_meta_subcmd, { "icq.unknown_meta_subcmd", PI_UNDECODED, PI_WARN, "Unknown meta subcmd", EXPFILL }}, + { &ei_icq_unknown_command, { "icq.unknown_command", PI_UNDECODED, PI_WARN, "Unknown command", EXPFILL }}, }; + expert_module_t *expert_icq; - static gint *ett[] = { - &ett_icq, - &ett_icq_header, - &ett_icq_body, - &ett_icq_body_parts, - }; - static ei_register_info ei[] = { - { &ei_icq_unknown_meta_subcmd, { "icq.unknown_meta_subcmd", PI_UNDECODED, PI_WARN, "Unknown meta subcmd", EXPFILL }}, - { &ei_icq_unknown_command, { "icq.unknown_command", PI_UNDECODED, PI_WARN, "Unknown command", EXPFILL }}, - }; - - expert_module_t* expert_icq; - - proto_icq = proto_register_protocol("ICQ Protocol", "ICQ", "icq"); - proto_register_field_array(proto_icq, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); - expert_icq = expert_register_protocol(proto_icq); - expert_register_field_array(expert_icq, ei, array_length(ei)); + proto_icq = proto_register_protocol("ICQ Protocol", "ICQ", "icq"); + proto_register_field_array(proto_icq, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_icq = expert_register_protocol(proto_icq); + expert_register_field_array(expert_icq, ei, array_length(ei)); } void proto_reg_handoff_icq(void) { - dissector_handle_t icq_handle; + dissector_handle_t icq_handle; - icq_handle = new_create_dissector_handle(dissect_icq, proto_icq); - dissector_add_uint("udp.port", UDP_PORT_ICQ, icq_handle); + icq_handle = new_create_dissector_handle(dissect_icq, proto_icq); + dissector_add_uint("udp.port", UDP_PORT_ICQ, icq_handle); } /* - * Editor modelines + * Editor modelines - http://www.wireshark.org/tools/modelines.html * - * Local Variables: - * c-basic-offset: 8 + * Local variables: + * c-basic-offset: 4 * tab-width: 8 - * indent-tabs-mode: t + * indent-tabs-mode: nil * End: * - * ex: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: */ diff --git a/epan/dissectors/packet-rtpproxy.c b/epan/dissectors/packet-rtpproxy.c index c0b60ebfb4..f58163ae00 100644 --- a/epan/dissectors/packet-rtpproxy.c +++ b/epan/dissectors/packet-rtpproxy.c @@ -97,10 +97,10 @@ static int hf_rtpproxy_response_in = -1; static int hf_rtpproxy_response_time = -1; typedef struct _rtpproxy_info { - guint32 req_frame; - guint32 resp_frame; - nstime_t req_time; - gchar* callid; + guint32 req_frame; + guint32 resp_frame; + nstime_t req_time; + gchar* callid; } rtpproxy_info_t; static dissector_handle_t rtcp_handle; @@ -109,122 +109,122 @@ static dissector_handle_t rtp_handle; static dissector_handle_t bencode_handle; typedef struct _rtpproxy_conv_info { - wmem_tree_t *trans; + wmem_tree_t *trans; } rtpproxy_conv_info_t; static const string_string versiontypenames[] = { - { "20040107", "Basic RTP proxy functionality" }, - { "20050322", "Support for multiple RTP streams and MOH" }, - { "20060704", "Support for extra parameter in the V command" }, - { "20071116", "Support for RTP re-packetization" }, - { "20071218", "Support for forking (copying) RTP stream" }, - { "20080403", "Support for RTP statistics querying" }, - { "20081102", "Support for setting codecs in the update/lookup command" }, - { "20081224", "Support for session timeout notifications" }, - { "20090810", "Support for automatic bridging" }, - { 0, NULL } + { "20040107", "Basic RTP proxy functionality" }, + { "20050322", "Support for multiple RTP streams and MOH" }, + { "20060704", "Support for extra parameter in the V command" }, + { "20071116", "Support for RTP re-packetization" }, + { "20071218", "Support for forking (copying) RTP stream" }, + { "20080403", "Support for RTP statistics querying" }, + { "20081102", "Support for setting codecs in the update/lookup command" }, + { "20081224", "Support for session timeout notifications" }, + { "20090810", "Support for automatic bridging" }, + { 0, NULL } }; static const value_string commandtypenames[] = { - { 'V', "Handshake/Ping" }, - { 'v', "Handshake/Ping" }, - { 'U', "Offer/Update" }, - { 'u', "Offer/Update" }, - { 'L', "Answer/Lookup" }, - { 'l', "Answer/Lookup" }, - { 'I', "Information"}, - { 'i', "Information"}, - { 'X', "Close all active sessions"}, - { 'x', "Close all active sessions"}, - { 'D', "Delete an active session (Bye/Cancel/Error)"}, - { 'd', "Delete an active session (Bye/Cancel/Error)"}, - { 'P', "Start playback (music-on-hold)"}, - { 'p', "Start playback (music-on-hold)"}, - { 'S', "Stop playback (music-on-hold)"}, - { 's', "Stop playback (music-on-hold)"}, - { 'R', "Start recording"}, - { 'r', "Start recording"}, - { 'C', "Copy stream"}, - { 'c', "Copy stream"}, - { 'Q', "Query info about a session"}, - { 'q', "Query info about a session"}, - { 0, NULL } + { 'V', "Handshake/Ping" }, + { 'v', "Handshake/Ping" }, + { 'U', "Offer/Update" }, + { 'u', "Offer/Update" }, + { 'L', "Answer/Lookup" }, + { 'l', "Answer/Lookup" }, + { 'I', "Information"}, + { 'i', "Information"}, + { 'X', "Close all active sessions"}, + { 'x', "Close all active sessions"}, + { 'D', "Delete an active session (Bye/Cancel/Error)"}, + { 'd', "Delete an active session (Bye/Cancel/Error)"}, + { 'P', "Start playback (music-on-hold)"}, + { 'p', "Start playback (music-on-hold)"}, + { 'S', "Stop playback (music-on-hold)"}, + { 's', "Stop playback (music-on-hold)"}, + { 'R', "Start recording"}, + { 'r', "Start recording"}, + { 'C', "Copy stream"}, + { 'c', "Copy stream"}, + { 'Q', "Query info about a session"}, + { 'q', "Query info about a session"}, + { 0, NULL } }; static const value_string paramtypenames[] = { - /* Official command parameters */ - {'4', "Remote address is IPv4"}, - {'6', "Remote address is IPv6"}, - {'a', "Asymmetric RTP"}, - {'A', "Asymmetric RTP"}, - {'b', "Brief stats"}, - {'B', "Brief stats"}, - {'c', "Codecs"}, - {'C', "Codecs"}, - {'e', "External network (non RFC 1918)"}, - {'E', "External network (non RFC 1918)"}, - {'i', "Internal network (RFC 1918)"}, - {'I', "Internal network (RFC 1918)"}, - {'l', "Local address"}, - {'L', "Local address"}, - {'r', "Remote address"}, - {'R', "Remote address"}, - {'s', "Symmetric RTP (default)"}, - {'S', "Symmetric RTP (default)"}, - {'w', "Weak connection (allows roaming)"}, - {'W', "Weak connection (allows roaming)"}, - {'z', "repacketiZe"}, - {'Z', "repacketiZe"}, - /* Unofficial command parameters / expensions */ - {'d', "DTMF payload ID (unofficial extension)"}, - {'D', "DTMF payload ID (unofficial extension)"}, - {'m', "codec Mapping (unofficial extension)"}, - {'M', "codec Mapping (unofficial extension)"}, - {'p', "Protocol type (unofficial extension)"}, - {'P', "Protocol type (unofficial extension)"}, - {'t', "Transcode to (unofficial extension)"}, - {'T', "Transcode to (unofficial extension)"}, - {'v', "Accounting (unofficial extension)"}, - {'V', "Accounting (unofficial extension)"}, - {0, NULL} + /* Official command parameters */ + {'4', "Remote address is IPv4"}, + {'6', "Remote address is IPv6"}, + {'a', "Asymmetric RTP"}, + {'A', "Asymmetric RTP"}, + {'b', "Brief stats"}, + {'B', "Brief stats"}, + {'c', "Codecs"}, + {'C', "Codecs"}, + {'e', "External network (non RFC 1918)"}, + {'E', "External network (non RFC 1918)"}, + {'i', "Internal network (RFC 1918)"}, + {'I', "Internal network (RFC 1918)"}, + {'l', "Local address"}, + {'L', "Local address"}, + {'r', "Remote address"}, + {'R', "Remote address"}, + {'s', "Symmetric RTP (default)"}, + {'S', "Symmetric RTP (default)"}, + {'w', "Weak connection (allows roaming)"}, + {'W', "Weak connection (allows roaming)"}, + {'z', "repacketiZe"}, + {'Z', "repacketiZe"}, + /* Unofficial command parameters / expensions */ + {'d', "DTMF payload ID (unofficial extension)"}, + {'D', "DTMF payload ID (unofficial extension)"}, + {'m', "codec Mapping (unofficial extension)"}, + {'M', "codec Mapping (unofficial extension)"}, + {'p', "Protocol type (unofficial extension)"}, + {'P', "Protocol type (unofficial extension)"}, + {'t', "Transcode to (unofficial extension)"}, + {'T', "Transcode to (unofficial extension)"}, + {'v', "Accounting (unofficial extension)"}, + {'V', "Accounting (unofficial extension)"}, + {0, NULL} }; static const value_string prototypenames[] = { - { '0', "UDP (default)"}, - { '1', "TCP"}, - { '2', "SCTP"}, - { 0, NULL } + { '0', "UDP (default)"}, + { '1', "TCP"}, + { '2', "SCTP"}, + { 0, NULL } }; static const value_string acctypenames[] = { - { '0', "Start"}, - { '1', "Interim update"}, - { '2', "Stop"}, - { 0, NULL } + { '0', "Start"}, + { '1', "Interim update"}, + { '2', "Stop"}, + { 0, NULL } }; static const value_string oktypenames[] = { - { '0', "Ok"}, - { '1', "Version Supported"}, - { 0, NULL } + { '0', "Ok"}, + { '1', "Version Supported"}, + { 0, NULL } }; static const string_string errortypenames[] = { - { "E0", "Syntax error" }, - { "E1", "Syntax error" }, - { "E2", "Syntax error" }, - { "E3", "Unknown command" }, - { "E4", "Syntax error" }, - { "E5", "Out of memory" }, - { "E6", "<no description>" }, - { "E7", "Software error (can't create listener)" }, - { "E8", "Not Found" }, - { "E10", "Software error (can't create listener)" }, - { "E11", "Out of memory" }, - { "E12", "Out of memory" }, - { "E13", "Out of memory" }, - { "E14", "Out of memory" }, - { 0, NULL } + { "E0", "Syntax error" }, + { "E1", "Syntax error" }, + { "E2", "Syntax error" }, + { "E3", "Unknown command" }, + { "E4", "Syntax error" }, + { "E5", "Out of memory" }, + { "E6", "<no description>" }, + { "E7", "Software error (can't create listener)" }, + { "E8", "Not Found" }, + { "E10", "Software error (can't create listener)" }, + { "E11", "Out of memory" }, + { "E12", "Out of memory" }, + { "E13", "Out of memory" }, + { "E14", "Out of memory" }, + { 0, NULL } }; static gint ett_rtpproxy = -1; @@ -262,1221 +262,1229 @@ void proto_reg_handoff_rtpproxy(void); static gint rtpproxy_add_tag(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint realsize) { - proto_item *ti = NULL; - proto_tree *another_tree = NULL; - gint new_offset; - guint end; - - new_offset = tvb_find_guint8(tvb, begin, -1, ' '); - if(new_offset < 0) - end = realsize; /* No more parameters */ - else - end = new_offset; - - /* SER/OpenSER/OpenSIPS/Kamailio adds Media-ID right after the Tag - * separated by a semicolon - */ - new_offset = tvb_find_guint8(tvb, begin, end, ';'); - if(new_offset == -1){ - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, end - begin, ENC_ASCII | ENC_NA); - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag); - ti = proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, 0, ENC_ASCII | ENC_NA); - proto_item_append_text(ti, "<skipped>"); - PROTO_ITEM_SET_GENERATED(ti); - } - else{ - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, new_offset - begin, ENC_ASCII | ENC_NA); - if ((guint)new_offset == begin){ - proto_item_append_text(ti, "<skipped>"); /* A very first Offer/Update command */ - PROTO_ITEM_SET_GENERATED(ti); - } - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag); - proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, end - (new_offset+1), ENC_ASCII | ENC_NA); - } - return (end == realsize ? -1 : (gint)end); + proto_item *ti = NULL; + proto_tree *another_tree = NULL; + gint new_offset; + guint end; + + new_offset = tvb_find_guint8(tvb, begin, -1, ' '); + if(new_offset < 0) + end = realsize; /* No more parameters */ + else + end = new_offset; + + /* SER/OpenSER/OpenSIPS/Kamailio adds Media-ID right after the Tag + * separated by a semicolon + */ + new_offset = tvb_find_guint8(tvb, begin, end, ';'); + if(new_offset == -1){ + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, end - begin, ENC_ASCII | ENC_NA); + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag); + ti = proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, 0, ENC_ASCII | ENC_NA); + proto_item_append_text(ti, "<skipped>"); + PROTO_ITEM_SET_GENERATED(ti); + } + else{ + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, new_offset - begin, ENC_ASCII | ENC_NA); + if ((guint)new_offset == begin){ + proto_item_append_text(ti, "<skipped>"); /* A very first Offer/Update command */ + PROTO_ITEM_SET_GENERATED(ti); + } + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag); + proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, end - (new_offset+1), ENC_ASCII | ENC_NA); + } + return (end == realsize ? -1 : (gint)end); } static void rtpproxy_add_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtpproxy_tree, guint begin, guint realsize) { - proto_item *ti; - proto_tree *another_tree = NULL; - guint offset = 0; - guint new_offset = 0; - gint i; - guint pt = 0; - gchar** codecs = NULL; - guint codec_len; - guint8* rawstr = NULL; - guint32 ipaddr[4]; /* Enough room for IPv4 or IPv6 */ - - /* Extract the entire parameters line. */ - /* Something like "t4p1iic8,0,2,4,18,96,97,98,100,101" */ - rawstr = tvb_get_string_enc(wmem_packet_scope(), tvb, begin, realsize, ENC_ASCII); - - while(offset < realsize){ - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameter, tvb, begin + offset, 1, ENC_NA); - offset++; /* Skip 1-byte parameter's type */ - switch (g_ascii_tolower(tvb_get_guint8(tvb, begin+offset-1))) - { - /* Official long parameters */ - case 'c': - new_offset = (gint)strspn(rawstr+offset, "0123456789,"); - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_codecs); - codecs = g_strsplit(tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), ",", 0); - i = 0; - while(codecs[i]){ - /* We assume strings < 2^32-1 bytes long. :-) */ - codec_len = (guint)strlen(codecs[i]); - ti = proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_codec, tvb, begin+offset, codec_len, - (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, codec_len, ENC_ASCII), NULL, 10)); - proto_item_append_text(ti, " (%s)", val_to_str_ext((guint)strtoul(tvb_format_text(tvb,begin+offset,codec_len),NULL,10), &rtp_payload_type_vals_ext, "Unknown")); - offset += codec_len; - if(codecs[i+1]) - offset++; /* skip comma */ - i++; - }; - g_strfreev(codecs); - break; - case 'l': - new_offset = (gint)strspn(rawstr+offset, "0123456789."); - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_local); - if(str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), ipaddr)) - proto_tree_add_ipv4(another_tree, hf_rtpproxy_command_parameter_local_ipv4, tvb, begin+offset, new_offset, ipaddr[0]); - else - proto_tree_add_expert(another_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, begin+offset, new_offset); - offset += new_offset; - break; - case 'r': - new_offset = (gint)strspn(rawstr+offset, "0123456789."); - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_remote); - if(str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), ipaddr)) - proto_tree_add_ipv4(another_tree, hf_rtpproxy_command_parameter_remote_ipv4, tvb, begin+offset, new_offset, ipaddr[0]); - else - proto_tree_add_expert(another_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, begin+offset, new_offset); - offset += new_offset; - break; - case 'z': - new_offset = (gint)strspn(rawstr+offset, "0123456789"); - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_repacketize); - proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_repacketize, tvb, begin+offset, new_offset, - (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), NULL, 10)); - offset += new_offset; - break; - /* Unofficial long parameters */ - case 'd': - new_offset = (gint)strspn(rawstr+offset, "0123456789"); - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_dtmf); - proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_dtmf, tvb, begin+offset, new_offset, - (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), NULL, 10)); - if(rtpproxy_establish_conversation){ - pt = (guint)strtoul(tvb_format_text(tvb,begin+offset,new_offset),NULL,10); - dissector_add_uint("rtp.pt", pt, rtp_events_handle); - } - offset += new_offset; - break; - case 'm': - new_offset = (gint)strspn(rawstr+offset, "0123456789=,"); - /* TODO */ - offset += new_offset; - break; - case 'p': - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_proto); - proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_proto, tvb, begin+offset, 1, ENC_NA); - offset++; - break; - case 't': - new_offset = (gint)strspn(rawstr+offset, "0123456789"); - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_transcode); - ti = proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_transcode, tvb, begin+offset, new_offset, - (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), NULL, 10)); - proto_item_append_text(ti, " (%s)", val_to_str_ext((guint)strtoul(tvb_format_text(tvb,begin+offset, new_offset),NULL,10), &rtp_payload_type_vals_ext, "Unknown")); - offset += new_offset; - break; - case 'v': - another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_acc); - proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_acc, tvb, begin+offset, 1, ENC_NA); - offset++; - break; - default: - break; - } - } + proto_item *ti; + proto_tree *another_tree = NULL; + guint offset = 0; + guint new_offset = 0; + gint i; + guint pt = 0; + gchar** codecs = NULL; + guint codec_len; + guint8* rawstr = NULL; + guint32 ipaddr[4]; /* Enough room for IPv4 or IPv6 */ + + /* Extract the entire parameters line. */ + /* Something like "t4p1iic8,0,2,4,18,96,97,98,100,101" */ + rawstr = tvb_get_string_enc(wmem_packet_scope(), tvb, begin, realsize, ENC_ASCII); + + while(offset < realsize){ + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameter, tvb, begin + offset, 1, ENC_NA); + offset++; /* Skip 1-byte parameter's type */ + switch (g_ascii_tolower(tvb_get_guint8(tvb, begin+offset-1))) + { + /* Official long parameters */ + case 'c': + new_offset = (gint)strspn(rawstr+offset, "0123456789,"); + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_codecs); + codecs = g_strsplit(tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), ",", 0); + i = 0; + while(codecs[i]){ + /* We assume strings < 2^32-1 bytes long. :-) */ + codec_len = (guint)strlen(codecs[i]); + ti = proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_codec, tvb, begin+offset, codec_len, + (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, codec_len, ENC_ASCII), NULL, 10)); + proto_item_append_text(ti, " (%s)", val_to_str_ext((guint)strtoul(tvb_format_text(tvb,begin+offset,codec_len),NULL,10), &rtp_payload_type_vals_ext, "Unknown")); + offset += codec_len; + if(codecs[i+1]) + offset++; /* skip comma */ + i++; + }; + g_strfreev(codecs); + break; + case 'l': + new_offset = (gint)strspn(rawstr+offset, "0123456789."); + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_local); + if(str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), ipaddr)) + proto_tree_add_ipv4(another_tree, hf_rtpproxy_command_parameter_local_ipv4, tvb, begin+offset, new_offset, ipaddr[0]); + else + proto_tree_add_expert(another_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, begin+offset, new_offset); + offset += new_offset; + break; + case 'r': + new_offset = (gint)strspn(rawstr+offset, "0123456789."); + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_remote); + if(str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), ipaddr)) + proto_tree_add_ipv4(another_tree, hf_rtpproxy_command_parameter_remote_ipv4, tvb, begin+offset, new_offset, ipaddr[0]); + else + proto_tree_add_expert(another_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, begin+offset, new_offset); + offset += new_offset; + break; + case 'z': + new_offset = (gint)strspn(rawstr+offset, "0123456789"); + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_repacketize); + proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_repacketize, tvb, begin+offset, new_offset, + (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), NULL, 10)); + offset += new_offset; + break; + /* Unofficial long parameters */ + case 'd': + new_offset = (gint)strspn(rawstr+offset, "0123456789"); + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_dtmf); + proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_dtmf, tvb, begin+offset, new_offset, + (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), NULL, 10)); + if(rtpproxy_establish_conversation){ + pt = (guint)strtoul(tvb_format_text(tvb,begin+offset,new_offset),NULL,10); + dissector_add_uint("rtp.pt", pt, rtp_events_handle); + } + offset += new_offset; + break; + case 'm': + new_offset = (gint)strspn(rawstr+offset, "0123456789=,"); + /* TODO */ + offset += new_offset; + break; + case 'p': + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_proto); + proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_proto, tvb, begin+offset, 1, ENC_NA); + offset++; + break; + case 't': + new_offset = (gint)strspn(rawstr+offset, "0123456789"); + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_transcode); + ti = proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_transcode, tvb, begin+offset, new_offset, + (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin+offset, new_offset, ENC_ASCII), NULL, 10)); + proto_item_append_text(ti, " (%s)", val_to_str_ext((guint)strtoul(tvb_format_text(tvb,begin+offset, new_offset),NULL,10), &rtp_payload_type_vals_ext, "Unknown")); + offset += new_offset; + break; + case 'v': + another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_acc); + proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_acc, tvb, begin+offset, 1, ENC_NA); + offset++; + break; + default: + break; + } + } } static rtpproxy_info_t * rtpproxy_add_tid(gboolean is_request, tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtpproxy_tree, rtpproxy_conv_info_t *rtpproxy_conv, gchar* cookie) { - rtpproxy_info_t *rtpproxy_info; - proto_item *pi; - - if (!PINFO_FD_VISITED(pinfo)) { - if (is_request){ - rtpproxy_info = wmem_new(wmem_file_scope(), rtpproxy_info_t); - rtpproxy_info->req_frame = PINFO_FD_NUM(pinfo); - rtpproxy_info->resp_frame = 0; - rtpproxy_info->req_time = pinfo->fd->abs_ts; - rtpproxy_info->callid = NULL; - wmem_tree_insert_string(rtpproxy_conv->trans, cookie, rtpproxy_info, 0); - } else { - rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0); - if (rtpproxy_info) { - rtpproxy_info->resp_frame = PINFO_FD_NUM(pinfo); - } - } - } else { - rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0); - if (rtpproxy_info && (is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame)) { - nstime_t ns; - - pi = proto_tree_add_uint(rtpproxy_tree, is_request ? hf_rtpproxy_response_in : hf_rtpproxy_request_in, tvb, 0, 0, is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame); - PROTO_ITEM_SET_GENERATED(pi); - - /* If reply then calculate response time */ - if (!is_request){ - nstime_delta(&ns, &pinfo->fd->abs_ts, &rtpproxy_info->req_time); - pi = proto_tree_add_time(rtpproxy_tree, hf_rtpproxy_response_time, tvb, 0, 0, &ns); - PROTO_ITEM_SET_GENERATED(pi); - if (nstime_cmp(&rtpproxy_timeout_ns, &ns) < 0) - expert_add_info_format(pinfo, rtpproxy_tree, &ei_rtpproxy_timeout, "Response timeout %.3f seconds", nstime_to_sec(&ns)); - } - } - } - /* Could be NULL so we should check it before dereferencing */ - return rtpproxy_info; + rtpproxy_info_t *rtpproxy_info; + proto_item *pi; + + if (!PINFO_FD_VISITED(pinfo)) { + if (is_request){ + rtpproxy_info = wmem_new(wmem_file_scope(), rtpproxy_info_t); + rtpproxy_info->req_frame = PINFO_FD_NUM(pinfo); + rtpproxy_info->resp_frame = 0; + rtpproxy_info->req_time = pinfo->fd->abs_ts; + rtpproxy_info->callid = NULL; + wmem_tree_insert_string(rtpproxy_conv->trans, cookie, rtpproxy_info, 0); + } else { + rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0); + if (rtpproxy_info) { + rtpproxy_info->resp_frame = PINFO_FD_NUM(pinfo); + } + } + } else { + rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0); + if (rtpproxy_info && (is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame)) { + nstime_t ns; + + pi = proto_tree_add_uint(rtpproxy_tree, is_request ? hf_rtpproxy_response_in : hf_rtpproxy_request_in, tvb, 0, 0, is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame); + PROTO_ITEM_SET_GENERATED(pi); + + /* If reply then calculate response time */ + if (!is_request){ + nstime_delta(&ns, &pinfo->fd->abs_ts, &rtpproxy_info->req_time); + pi = proto_tree_add_time(rtpproxy_tree, hf_rtpproxy_response_time, tvb, 0, 0, &ns); + PROTO_ITEM_SET_GENERATED(pi); + if (nstime_cmp(&rtpproxy_timeout_ns, &ns) < 0) + expert_add_info_format(pinfo, rtpproxy_tree, &ei_rtpproxy_timeout, "Response timeout %.3f seconds", nstime_to_sec(&ns)); + } + } + } + /* Could be NULL so we should check it before dereferencing */ + return rtpproxy_info; } static void rtpproxy_add_notify_addr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtpproxy_tree, guint begin, guint end) { - gint offset = 0; - gint tmp = 0; - gboolean ipv6 = FALSE; - guint32 ipaddr[4]; /* Enough room for IPv4 or IPv6 */ - proto_item *ti; - - /* Check for at least one colon */ - offset = tvb_find_guint8(tvb, begin, end, ':'); - if(offset != -1){ - /* Find if it's the latest colon (not in case of a IPv6) */ - while((tmp = tvb_find_guint8(tvb, offset+1, end, ':')) != -1){ - ipv6 = TRUE; - offset = tmp; - } - /* We have ip:port */ - if(ipv6){ - if(str_to_ip6((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin, offset - begin, ENC_ASCII), ipaddr)) - proto_tree_add_ipv6(rtpproxy_tree, hf_rtpproxy_notify_ipv6, tvb, begin, offset - begin, (const guint8 *)ipaddr); - else - proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv6, tvb, begin, offset - begin); - } - else{ - if(str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin, offset - begin, ENC_ASCII), ipaddr)) - proto_tree_add_ipv4(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, offset - begin, ipaddr[0]); - else - proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, begin, offset - begin); - } - proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, offset+1, end - (offset+1), - (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset+1, end - (offset+1), ENC_ASCII), NULL, 10)); - } - else{ - /* Only port is supplied - take IPv4/IPv6 from ip.src/ipv6.src respectively */ - expert_add_info(pinfo, rtpproxy_tree, &ei_rtpproxy_notify_no_ip); - if (pinfo->src.type == AT_IPv4) - ti = proto_tree_add_ipv4(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, 0, ((guint32*)(pinfo->src.data))[0]); - else - ti = proto_tree_add_ipv6(rtpproxy_tree, hf_rtpproxy_notify_ipv6, tvb, begin, 0, (const guint8 *)(pinfo->src.data)); - PROTO_ITEM_SET_GENERATED(ti); - proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, begin, end - begin, - (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin, end - begin, ENC_ASCII), NULL, 10)); - } + gint offset = 0; + gint tmp = 0; + gboolean ipv6 = FALSE; + guint32 ipaddr[4]; /* Enough room for IPv4 or IPv6 */ + proto_item *ti; + + /* Check for at least one colon */ + offset = tvb_find_guint8(tvb, begin, end, ':'); + if(offset != -1){ + /* Find if it's the latest colon (not in case of a IPv6) */ + while((tmp = tvb_find_guint8(tvb, offset+1, end, ':')) != -1){ + ipv6 = TRUE; + offset = tmp; + } + /* We have ip:port */ + if(ipv6){ + if(str_to_ip6((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin, offset - begin, ENC_ASCII), ipaddr)) + proto_tree_add_ipv6(rtpproxy_tree, hf_rtpproxy_notify_ipv6, tvb, begin, offset - begin, (const guint8 *)ipaddr); + else + proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv6, tvb, begin, offset - begin); + } + else{ + if(str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin, offset - begin, ENC_ASCII), ipaddr)) + proto_tree_add_ipv4(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, offset - begin, ipaddr[0]); + else + proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, begin, offset - begin); + } + proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, offset+1, end - (offset+1), + (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset+1, end - (offset+1), ENC_ASCII), NULL, 10)); + } + else{ + /* Only port is supplied - take IPv4/IPv6 from ip.src/ipv6.src respectively */ + expert_add_info(pinfo, rtpproxy_tree, &ei_rtpproxy_notify_no_ip); + if (pinfo->src.type == AT_IPv4) + ti = proto_tree_add_ipv4(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, 0, ((guint32*)(pinfo->src.data))[0]); + else + ti = proto_tree_add_ipv6(rtpproxy_tree, hf_rtpproxy_notify_ipv6, tvb, begin, 0, (const guint8 *)(pinfo->src.data)); + PROTO_ITEM_SET_GENERATED(ti); + proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, begin, end - begin, + (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, begin, end - begin, ENC_ASCII), NULL, 10)); + } } static int dissect_rtpproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { - gboolean has_lf = FALSE; - gint offset = 0; - gint new_offset = 0; - guint tmp; - guint tmp2; - gint realsize = 0; - guint8* rawstr; - guint8* tmpstr; - proto_item *ti; - proto_item *ti2; - proto_tree *rtpproxy_tree; - conversation_t *conversation; - rtpproxy_conv_info_t *rtpproxy_conv; - gchar* cookie = NULL; - /* For RT(C)P setup */ - address addr; - guint16 port; - guint32 ipaddr[4]; /* Enough room for IPv4 or IPv6 */ - rtpproxy_info_t *rtpproxy_info = NULL; - tvbuff_t *subtvb; - - /* If it does not start with a printable character it's not RTPProxy */ - if(!isprint(tvb_get_guint8(tvb, 0))) - return 0; - - /* Extract Cookie */ - offset = tvb_find_guint8(tvb, offset, -1, ' '); - if(offset == -1) - return 0; - - /* Clear out stuff in the info column - we''l set it later */ - col_clear(pinfo->cinfo, COL_INFO); - - ti = proto_tree_add_item(tree, proto_rtpproxy, tvb, 0, -1, ENC_NA); - rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy); - - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_cookie, tvb, 0, offset, ENC_ASCII | ENC_NA); - cookie = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, offset, ENC_ASCII); - - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, offset+1, -1); - - /* Calculate size to prevent recalculation in the future */ - realsize = tvb_reported_length(tvb); - - - /* Check for LF (required for TCP connection, optional for UDP) */ - if (tvb_get_guint8(tvb, realsize - 1) == '\n'){ - col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPproxy"); - /* Don't count trailing LF */ - realsize -= 1; - has_lf = TRUE; - } - else - col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPproxy (no LF)"); /* FIXME replace with expert info field */ - - - /* Try to create conversation */ - conversation = find_or_create_conversation(pinfo); - rtpproxy_conv = (rtpproxy_conv_info_t *)conversation_get_proto_data(conversation, proto_rtpproxy); - if (!rtpproxy_conv) { - rtpproxy_conv = wmem_new(wmem_file_scope(), rtpproxy_conv_info_t); - rtpproxy_conv->trans = wmem_tree_new(wmem_file_scope()); - conversation_add_proto_data(conversation, proto_rtpproxy, rtpproxy_conv); - } - - /* Get payload string */ - rawstr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, realsize - offset, ENC_ASCII); - - /* Extract command */ - tmp = g_ascii_tolower(tvb_get_guint8(tvb, offset)); - switch (tmp) - { - case 's': - /* A specific case - long statistics answer */ - /* %COOKIE% sessions created %NUM0% active sessions: %NUM1% */ - rtpproxy_add_tid(FALSE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie); - if ('e' == tvb_get_guint8(tvb, offset+1)){ - col_add_fstr(pinfo->cinfo, COL_INFO, "Reply: %s", rawstr); - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_reply, tvb, offset, -1, ENC_NA); - - rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_reply); - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_status, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA); - break; - } - case 'i': - case 'x': - case 'u': - case 'l': - case 'd': - tmp2 = tvb_get_guint8(tvb, offset+1); - if(('1' <= tmp2) && (tmp2 <= '9') && (tvb_get_guint8(tvb, offset+2) == ':')){ - col_add_fstr(pinfo->cinfo, COL_INFO, "RTPproxy-ng: %s", rawstr); - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ng_bencode, tvb, offset, -1, ENC_ASCII | ENC_NA); - rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_ng_bencode); - subtvb = tvb_new_subset_remaining(tvb, offset); - call_dissector(bencode_handle, subtvb, pinfo, rtpproxy_tree); - break; - } - case 'p': - case 'v': - case 'r': - case 'c': - case 'q': - rtpproxy_info = rtpproxy_add_tid(TRUE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie); - col_add_fstr(pinfo->cinfo, COL_INFO, "Request: %s", rawstr); - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_request, tvb, offset, -1, ENC_NA); - rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_request); - - /* A specific case - version request */ - if ((tmp == 'v') && (offset + (gint)strlen("VF YYYMMDD") + 1 == realsize)){ - /* Skip whitespace */ - new_offset = tvb_skip_wsp(tvb, offset + ((guint)strlen("VF") + 1), -1); - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_request, tvb, new_offset, (gint)strlen("YYYYMMDD"), ENC_ASCII | ENC_NA); - tmpstr = tvb_get_string_enc(wmem_packet_scope(), tvb, new_offset, (gint)strlen("YYYYMMDD"), ENC_ASCII); - proto_item_append_text(ti, " (%s)", str_to_str(tmpstr, versiontypenames, "Unknown")); - break; - } - - /* All other commands */ - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command, tvb, offset, 1, ENC_NA); - - /* A specific case - handshake/ping */ - if (tmp == 'v') - break; /* No more parameters */ - - /* A specific case - close all calls */ - if (tmp == 'x') - break; /* No more parameters */ - - /* Extract parameters */ - /* Parameters should be right after the command and before EOL (in case of Info command) or before whitespace */ - new_offset = (tmp == 'i' ? (realsize - 1 > offset ? offset + (gint)strlen("Ib") : offset + (gint)strlen("I")) : tvb_find_guint8(tvb, offset, -1, ' ')); - - if (new_offset != offset + 1){ - rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_command); - ti2 = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameters, tvb, offset+1, new_offset - (offset+1), ENC_ASCII | ENC_NA); - rtpproxy_add_parameter(tvb, pinfo, proto_item_add_subtree(ti2, ett_rtpproxy_command_parameters), offset+1, new_offset - (offset+1)); - rtpproxy_tree = proto_item_get_parent(ti); - } - - /* A specific case - query information */ - if (tmp == 'i') - break; /* No more parameters */ - - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - - /* Extract Call-ID */ - new_offset = tvb_find_guint8(tvb, offset, -1, ' '); - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_callid, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA); - if(rtpproxy_info && !rtpproxy_info->callid) - rtpproxy_info->callid = tvb_get_string_enc(wmem_file_scope(), tvb, offset, new_offset - offset, ENC_ASCII); - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - - /* Extract IP and Port in case of Offer/Answer */ - if ((tmp == 'u') || (tmp == 'l')){ - /* Extract IP */ - new_offset = tvb_find_guint8(tvb, offset, -1, ' '); - if (tvb_find_guint8(tvb, offset, new_offset - offset, ':') == -1){ - if(str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), ipaddr)) - proto_tree_add_ipv4(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, new_offset - offset, ipaddr[0]); - else - proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, offset, new_offset - offset); - } - else{ - if(str_to_ip6((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), ipaddr)) - proto_tree_add_ipv6(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, new_offset - offset, (const guint8 *)ipaddr); - else - proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv6, tvb, offset, new_offset - offset); - } - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - - /* Extract Port */ - new_offset = tvb_find_guint8(tvb, offset, -1, ' '); - proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset, - (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), NULL, 10)); - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - } - - /* Extract Copy target */ - if (tmp == 'c'){ - new_offset = tvb_find_guint8(tvb, offset, -1, ' '); - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_copy_target, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA); - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - } - - /* Extract Playback file and codecs */ - if (tmp == 'p'){ - /* Extract filename */ - new_offset = tvb_find_guint8(tvb, offset, -1, ' '); - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_playback_filename, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA); - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - - /* Extract codec */ - new_offset = tvb_find_guint8(tvb, offset, -1, ' '); - proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_playback_codec, tvb, offset, new_offset - offset, - (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), NULL, 10)); - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - } - - /* Extract first tag */ - new_offset = rtpproxy_add_tag(rtpproxy_tree, tvb, offset, realsize); - if(new_offset == -1) - break; /* No more parameters */ - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - - /* Extract second tag */ - new_offset = rtpproxy_add_tag(rtpproxy_tree, tvb, offset, realsize); - if(new_offset == -1) - break; /* No more parameters */ - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - - /* Extract Notification address */ - if (tmp == 'u'){ - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA); - proto_item_set_text(ti, "Notify"); - rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_notify); - - /* Check for NotifyTag parameter (separated by space) */ - new_offset = tvb_find_guint8(tvb, offset, -1, ' '); - if(new_offset == -1){ - /* NotifyTag wasn't found (we should re-use Call-ID instead) */ - rtpproxy_add_notify_addr(tvb, pinfo, rtpproxy_tree, offset, realsize); - break; /* No more parameters */ - } - - /* NotifyTag was found */ - rtpproxy_add_notify_addr(tvb, pinfo, rtpproxy_tree, offset, new_offset); - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_tag, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA); - } - break; - case 'a': - case 'e': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - rtpproxy_info = rtpproxy_add_tid(FALSE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie); - if (tmp == 'e') - col_add_fstr(pinfo->cinfo, COL_INFO, "Error reply: %s", rawstr); - else - col_add_fstr(pinfo->cinfo, COL_INFO, "Reply: %s", rawstr); - - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_reply, tvb, offset, -1, ENC_NA); - rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_reply); - - if(rtpproxy_info && rtpproxy_info->callid){ - ti = proto_tree_add_string(rtpproxy_tree, hf_rtpproxy_callid, tvb, offset, 0, rtpproxy_info->callid); - PROTO_ITEM_SET_GENERATED(ti); - } - - if (tmp == 'e'){ - tmp = tvb_find_line_end(tvb, offset, -1, &new_offset, FALSE); - tmpstr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tmp, ENC_ASCII); - ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_error, tvb, offset, (gint)strlen(tmpstr), ENC_ASCII | ENC_NA); - proto_item_append_text(ti, " (%s)", str_to_str(tmpstr, errortypenames, "Unknown")); - break; - } - - if (tmp == 'a'){ - /* A specific case - short statistics answer */ - /* %COOKIE% active sessions: %NUM1% */ - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_status, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA); - break; - } - if ((tmp == '0')&& ((tvb_reported_length(tvb) == (guint)(offset+1))||(tvb_reported_length(tvb) == (guint)(offset+2)))){ - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA); - break; - } - if ((tmp == '1') && ((tvb_reported_length(tvb) == (guint)(offset+1))||(tvb_reported_length(tvb) == (guint)(offset+2)))){ - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA); - break; - } - if (tvb_reported_length(tvb) == (guint)(offset+9)){ - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_supported, tvb, offset, 8, ENC_ASCII | ENC_NA); - break; - } - - /* Extract Port */ - new_offset = tvb_find_guint8(tvb, offset, -1, ' '); - /* Convert port to unsigned 16-bit number */ - port = (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), NULL, 10); - proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset, port); - /* Skip whitespace */ - offset = tvb_skip_wsp(tvb, new_offset+1, -1); - - /* Extract IP */ - memset(&addr, 0, sizeof(address)); - - /* Try rtpengine bogus extension first. It appends 4 or - * 6 depending on type of the IP. See - * https://github.com/sipwise/rtpengine/blob/master/daemon/call_interfaces.c#L66 - * for further details */ - tmp = tvb_find_guint8(tvb, offset, -1, ' '); - if(tmp == (guint)(-1)){ - /* No extension - operate normally */ - tmp = tvb_find_line_end(tvb, offset, -1, &new_offset, FALSE); - } - else { - tmp -= offset; - } - - if (tvb_find_guint8(tvb, offset, -1, ':') == -1){ - if (str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tmp, ENC_ASCII), ipaddr)){ - addr.type = AT_IPv4; - addr.len = 4; - addr.data = wmem_memdup(wmem_packet_scope(), ipaddr, 4); - proto_tree_add_ipv4(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, tmp, ipaddr[0]); - } - else - proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, offset, tmp); - } - else{ - if (str_to_ip6((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tmp, ENC_ASCII), ipaddr)){ - addr.type = AT_IPv6; - addr.len = 16; - addr.data = wmem_memdup(wmem_packet_scope(), ipaddr, 16); - proto_tree_add_ipv6(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, tmp, (const guint8 *)ipaddr); - } - else - proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv6, tvb, offset, tmp); - } - - if(rtpproxy_establish_conversation){ - if (rtp_handle) { - /* FIXME tell if isn't a video stream, and setup codec mapping */ - if (addr.len) - rtp_add_address(pinfo, &addr, port, 0, "RTPproxy", pinfo->fd->num, 0, NULL); - } - if (rtcp_handle) { - if (addr.len) - rtcp_add_address(pinfo, &addr, port+1, 0, "RTPproxy", pinfo->fd->num); - } - } - break; - default: - break; - } - if (has_lf) - proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_lf, tvb, realsize, 1, ENC_NA); - - return tvb_length(tvb); + gboolean has_lf = FALSE; + gint offset = 0; + gint new_offset = 0; + guint tmp; + guint tmp2; + gint realsize = 0; + guint8* rawstr; + guint8* tmpstr; + proto_item *ti; + proto_item *ti2; + proto_tree *rtpproxy_tree; + conversation_t *conversation; + rtpproxy_conv_info_t *rtpproxy_conv; + gchar* cookie = NULL; + /* For RT(C)P setup */ + address addr; + guint16 port; + guint32 ipaddr[4]; /* Enough room for IPv4 or IPv6 */ + rtpproxy_info_t *rtpproxy_info = NULL; + tvbuff_t *subtvb; + + /* If it does not start with a printable character it's not RTPProxy */ + if(!isprint(tvb_get_guint8(tvb, 0))) + return 0; + + /* Extract Cookie */ + offset = tvb_find_guint8(tvb, offset, -1, ' '); + if(offset == -1) + return 0; + + /* Clear out stuff in the info column - we''l set it later */ + col_clear(pinfo->cinfo, COL_INFO); + + ti = proto_tree_add_item(tree, proto_rtpproxy, tvb, 0, -1, ENC_NA); + rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy); + + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_cookie, tvb, 0, offset, ENC_ASCII | ENC_NA); + cookie = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, offset, ENC_ASCII); + + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, offset+1, -1); + + /* Calculate size to prevent recalculation in the future */ + realsize = tvb_reported_length(tvb); + + + /* Check for LF (required for TCP connection, optional for UDP) */ + if (tvb_get_guint8(tvb, realsize - 1) == '\n'){ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPproxy"); + /* Don't count trailing LF */ + realsize -= 1; + has_lf = TRUE; + } + else + col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPproxy (no LF)"); /* FIXME replace with expert info field */ + + + /* Try to create conversation */ + conversation = find_or_create_conversation(pinfo); + rtpproxy_conv = (rtpproxy_conv_info_t *)conversation_get_proto_data(conversation, proto_rtpproxy); + if (!rtpproxy_conv) { + rtpproxy_conv = wmem_new(wmem_file_scope(), rtpproxy_conv_info_t); + rtpproxy_conv->trans = wmem_tree_new(wmem_file_scope()); + conversation_add_proto_data(conversation, proto_rtpproxy, rtpproxy_conv); + } + + /* Get payload string */ + rawstr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, realsize - offset, ENC_ASCII); + + /* Extract command */ + tmp = g_ascii_tolower(tvb_get_guint8(tvb, offset)); + switch (tmp) + { + case 's': + /* A specific case - long statistics answer */ + /* %COOKIE% sessions created %NUM0% active sessions: %NUM1% */ + rtpproxy_add_tid(FALSE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie); + if ('e' == tvb_get_guint8(tvb, offset+1)){ + col_add_fstr(pinfo->cinfo, COL_INFO, "Reply: %s", rawstr); + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_reply, tvb, offset, -1, ENC_NA); + + rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_reply); + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_status, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA); + break; + } + case 'i': + case 'x': + case 'u': + case 'l': + case 'd': + tmp2 = tvb_get_guint8(tvb, offset+1); + if(('1' <= tmp2) && (tmp2 <= '9') && (tvb_get_guint8(tvb, offset+2) == ':')){ + col_add_fstr(pinfo->cinfo, COL_INFO, "RTPproxy-ng: %s", rawstr); + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ng_bencode, tvb, offset, -1, ENC_ASCII | ENC_NA); + rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_ng_bencode); + subtvb = tvb_new_subset_remaining(tvb, offset); + call_dissector(bencode_handle, subtvb, pinfo, rtpproxy_tree); + break; + } + case 'p': + case 'v': + case 'r': + case 'c': + case 'q': + rtpproxy_info = rtpproxy_add_tid(TRUE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie); + col_add_fstr(pinfo->cinfo, COL_INFO, "Request: %s", rawstr); + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_request, tvb, offset, -1, ENC_NA); + rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_request); + + /* A specific case - version request */ + if ((tmp == 'v') && (offset + (gint)strlen("VF YYYMMDD") + 1 == realsize)){ + /* Skip whitespace */ + new_offset = tvb_skip_wsp(tvb, offset + ((guint)strlen("VF") + 1), -1); + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_request, tvb, new_offset, (gint)strlen("YYYYMMDD"), ENC_ASCII | ENC_NA); + tmpstr = tvb_get_string_enc(wmem_packet_scope(), tvb, new_offset, (gint)strlen("YYYYMMDD"), ENC_ASCII); + proto_item_append_text(ti, " (%s)", str_to_str(tmpstr, versiontypenames, "Unknown")); + break; + } + + /* All other commands */ + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command, tvb, offset, 1, ENC_NA); + + /* A specific case - handshake/ping */ + if (tmp == 'v') + break; /* No more parameters */ + + /* A specific case - close all calls */ + if (tmp == 'x') + break; /* No more parameters */ + + /* Extract parameters */ + /* Parameters should be right after the command and before EOL (in case of Info command) or before whitespace */ + new_offset = (tmp == 'i' ? (realsize - 1 > offset ? offset + (gint)strlen("Ib") : offset + (gint)strlen("I")) : tvb_find_guint8(tvb, offset, -1, ' ')); + + if (new_offset != offset + 1){ + rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_command); + ti2 = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameters, tvb, offset+1, new_offset - (offset+1), ENC_ASCII | ENC_NA); + rtpproxy_add_parameter(tvb, pinfo, proto_item_add_subtree(ti2, ett_rtpproxy_command_parameters), offset+1, new_offset - (offset+1)); + rtpproxy_tree = proto_item_get_parent(ti); + } + + /* A specific case - query information */ + if (tmp == 'i') + break; /* No more parameters */ + + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + + /* Extract Call-ID */ + new_offset = tvb_find_guint8(tvb, offset, -1, ' '); + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_callid, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA); + if(rtpproxy_info && !rtpproxy_info->callid) + rtpproxy_info->callid = tvb_get_string_enc(wmem_file_scope(), tvb, offset, new_offset - offset, ENC_ASCII); + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + + /* Extract IP and Port in case of Offer/Answer */ + if ((tmp == 'u') || (tmp == 'l')){ + /* Extract IP */ + new_offset = tvb_find_guint8(tvb, offset, -1, ' '); + if (tvb_find_guint8(tvb, offset, new_offset - offset, ':') == -1){ + if(str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), ipaddr)) + proto_tree_add_ipv4(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, new_offset - offset, ipaddr[0]); + else + proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, offset, new_offset - offset); + } + else{ + if(str_to_ip6((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), ipaddr)) + proto_tree_add_ipv6(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, new_offset - offset, (const guint8 *)ipaddr); + else + proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv6, tvb, offset, new_offset - offset); + } + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + + /* Extract Port */ + new_offset = tvb_find_guint8(tvb, offset, -1, ' '); + proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset, + (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), NULL, 10)); + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + } + + /* Extract Copy target */ + if (tmp == 'c'){ + new_offset = tvb_find_guint8(tvb, offset, -1, ' '); + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_copy_target, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA); + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + } + + /* Extract Playback file and codecs */ + if (tmp == 'p'){ + /* Extract filename */ + new_offset = tvb_find_guint8(tvb, offset, -1, ' '); + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_playback_filename, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA); + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + + /* Extract codec */ + new_offset = tvb_find_guint8(tvb, offset, -1, ' '); + proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_playback_codec, tvb, offset, new_offset - offset, + (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), NULL, 10)); + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + } + + /* Extract first tag */ + new_offset = rtpproxy_add_tag(rtpproxy_tree, tvb, offset, realsize); + if(new_offset == -1) + break; /* No more parameters */ + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + + /* Extract second tag */ + new_offset = rtpproxy_add_tag(rtpproxy_tree, tvb, offset, realsize); + if(new_offset == -1) + break; /* No more parameters */ + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + + /* Extract Notification address */ + if (tmp == 'u'){ + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA); + proto_item_set_text(ti, "Notify"); + rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_notify); + + /* Check for NotifyTag parameter (separated by space) */ + new_offset = tvb_find_guint8(tvb, offset, -1, ' '); + if(new_offset == -1){ + /* NotifyTag wasn't found (we should re-use Call-ID instead) */ + rtpproxy_add_notify_addr(tvb, pinfo, rtpproxy_tree, offset, realsize); + break; /* No more parameters */ + } + + /* NotifyTag was found */ + rtpproxy_add_notify_addr(tvb, pinfo, rtpproxy_tree, offset, new_offset); + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_tag, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA); + } + break; + case 'a': + case 'e': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + rtpproxy_info = rtpproxy_add_tid(FALSE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie); + if (tmp == 'e') + col_add_fstr(pinfo->cinfo, COL_INFO, "Error reply: %s", rawstr); + else + col_add_fstr(pinfo->cinfo, COL_INFO, "Reply: %s", rawstr); + + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_reply, tvb, offset, -1, ENC_NA); + rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_reply); + + if(rtpproxy_info && rtpproxy_info->callid){ + ti = proto_tree_add_string(rtpproxy_tree, hf_rtpproxy_callid, tvb, offset, 0, rtpproxy_info->callid); + PROTO_ITEM_SET_GENERATED(ti); + } + + if (tmp == 'e'){ + tmp = tvb_find_line_end(tvb, offset, -1, &new_offset, FALSE); + tmpstr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tmp, ENC_ASCII); + ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_error, tvb, offset, (gint)strlen(tmpstr), ENC_ASCII | ENC_NA); + proto_item_append_text(ti, " (%s)", str_to_str(tmpstr, errortypenames, "Unknown")); + break; + } + + if (tmp == 'a'){ + /* A specific case - short statistics answer */ + /* %COOKIE% active sessions: %NUM1% */ + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_status, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA); + break; + } + if ((tmp == '0')&& ((tvb_reported_length(tvb) == (guint)(offset+1))||(tvb_reported_length(tvb) == (guint)(offset+2)))){ + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA); + break; + } + if ((tmp == '1') && ((tvb_reported_length(tvb) == (guint)(offset+1))||(tvb_reported_length(tvb) == (guint)(offset+2)))){ + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA); + break; + } + if (tvb_reported_length(tvb) == (guint)(offset+9)){ + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_supported, tvb, offset, 8, ENC_ASCII | ENC_NA); + break; + } + + /* Extract Port */ + new_offset = tvb_find_guint8(tvb, offset, -1, ' '); + /* Convert port to unsigned 16-bit number */ + port = (guint16) g_ascii_strtoull((gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, new_offset - offset, ENC_ASCII), NULL, 10); + proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset, port); + /* Skip whitespace */ + offset = tvb_skip_wsp(tvb, new_offset+1, -1); + + /* Extract IP */ + memset(&addr, 0, sizeof(address)); + + /* Try rtpengine bogus extension first. It appends 4 or + * 6 depending on type of the IP. See + * https://github.com/sipwise/rtpengine/blob/master/daemon/call_interfaces.c#L66 + * for further details */ + tmp = tvb_find_guint8(tvb, offset, -1, ' '); + if(tmp == (guint)(-1)){ + /* No extension - operate normally */ + tmp = tvb_find_line_end(tvb, offset, -1, &new_offset, FALSE); + } + else { + tmp -= offset; + } + + if (tvb_find_guint8(tvb, offset, -1, ':') == -1){ + if (str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tmp, ENC_ASCII), ipaddr)){ + addr.type = AT_IPv4; + addr.len = 4; + addr.data = wmem_memdup(wmem_packet_scope(), ipaddr, 4); + proto_tree_add_ipv4(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, tmp, ipaddr[0]); + } + else + proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv4, tvb, offset, tmp); + } + else{ + if (str_to_ip6((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tmp, ENC_ASCII), ipaddr)){ + addr.type = AT_IPv6; + addr.len = 16; + addr.data = wmem_memdup(wmem_packet_scope(), ipaddr, 16); + proto_tree_add_ipv6(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, tmp, (const guint8 *)ipaddr); + } + else + proto_tree_add_expert(rtpproxy_tree, pinfo, &ei_rtpproxy_bad_ipv6, tvb, offset, tmp); + } + + if(rtpproxy_establish_conversation){ + if (rtp_handle) { + /* FIXME tell if isn't a video stream, and setup codec mapping */ + if (addr.len) + rtp_add_address(pinfo, &addr, port, 0, "RTPproxy", pinfo->fd->num, 0, NULL); + } + if (rtcp_handle) { + if (addr.len) + rtcp_add_address(pinfo, &addr, port+1, 0, "RTPproxy", pinfo->fd->num); + } + } + break; + default: + break; + } + if (has_lf) + proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_lf, tvb, realsize, 1, ENC_NA); + + return tvb_length(tvb); } void proto_register_rtpproxy(void) { - module_t *rtpproxy_module; - expert_module_t* expert_rtpproxy_module; - - static hf_register_info hf[] = { - { - &hf_rtpproxy_cookie, - { - "Cookie", - "rtpproxy.cookie", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_version_request, - { - "Version Request", - "rtpproxy.version", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_version_supported, - { - "Version Supported", - "rtpproxy.version_supported", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_error, - { - "Error", - "rtpproxy.error", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_ok, - { - "Ok", - "rtpproxy.ok", - FT_UINT8, - BASE_DEC, - VALS(oktypenames), - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_status, - { - "Status", - "rtpproxy.status", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_ipv4, - { - "IPv4", - "rtpproxy.ipv4", - FT_IPv4, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_ipv6, - { - "IPv6", - "rtpproxy.ipv6", - FT_IPv6, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_port, - { - "Port", - "rtpproxy.port", - FT_UINT16, /* 0 - 65535 */ - BASE_DEC, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_request, - { - "Request", - "rtpproxy.request", - FT_NONE, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command, - { - "Command", - "rtpproxy.command", - FT_UINT8, - BASE_DEC, - VALS(commandtypenames), - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameters, - { - "Command parameters", - "rtpproxy.command_parameters", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter, - { - "Parameter", - "rtpproxy.command_parameter", - FT_UINT8, - BASE_DEC, - VALS(paramtypenames), - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter_codec, - { - "Allowed codec", - "rtpproxy.command_parameter_codec", - FT_UINT8, /* 0 - 127 */ - BASE_DEC, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter_local_ipv4, - { - "Local IPv4 address", - "rtpproxy.command_parameter_local_ipv4", - FT_IPv4, /* FIXME - is it ever possible to see IPv6 here? */ - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter_remote_ipv4, - { - "Remote IPv4 address", - "rtpproxy.command_parameter_remote_ipv4", - FT_IPv4, /* FIXME - is it ever possible to see IPv6 here? */ - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter_repacketize, - { - "Repacketize (ms)", - "rtpproxy.command_parameter_repacketize", - FT_UINT16, /* 0 - 1000 milliseconds */ - BASE_DEC, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter_dtmf, - { - "DTMF payload ID", - "rtpproxy.command_parameter_dtmf", - FT_UINT8, /* 0 - 127 */ - BASE_DEC, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter_proto, - { - "RTP tramsission protocol", - "rtpproxy.command_parameter_proto", - FT_UINT8, - BASE_DEC, - VALS(prototypenames), - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter_transcode, - { - "Transcode to", - "rtpproxy.command_parameter_transcode", - FT_UINT8, /* 0 - 127 */ - BASE_DEC, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_command_parameter_acc, - { - "Accounting", - "rtpproxy.command_parameter_acc", - FT_UINT8, - BASE_DEC, - VALS(acctypenames), - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_copy_target, - { - "Copy target", - "rtpproxy.copy_target", - FT_STRING, /* Filename or UDP address, e.g. /var/tmp/fileXXXX.yyy or IP:Port */ - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_playback_filename, - { - "Playback filename", - "rtpproxy.playback_filename", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_playback_codec, - { - "Playback codec", - "rtpproxy.playback_codec", - FT_UINT8, /* 0 - 127 */ - BASE_DEC, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_callid, - { - "Call-ID", - "rtpproxy.callid", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_notify, - { - "Notify", - "rtpproxy.notify", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_tag, - { - "Tag", - "rtpproxy.tag", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_mediaid, - { - "Media-ID", - "rtpproxy.mediaid", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_notify_ipv4, - { - "Notification IPv4", - "rtpproxy.notify_ipv4", - FT_IPv4, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_notify_ipv6, - { - "Notification IPv6", - "rtpproxy.notify_ipv6", - FT_IPv6, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_notify_port, - { - "Notification Port", - "rtpproxy.notify_port", - FT_UINT16, - BASE_DEC, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_notify_tag, - { - "Notification Tag", - "rtpproxy.notify_tag", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_reply, - { - "Reply", - "rtpproxy.reply", - FT_NONE, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_lf, - { - "LF", - "rtpproxy.lf", - FT_NONE, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_request_in, - { - "Request In", - "rtpproxy.request_in", - FT_FRAMENUM, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - - }, - { - &hf_rtpproxy_response_in, - { - "Response In", - "rtpproxy.response_in", - FT_FRAMENUM, - BASE_NONE, - NULL, - 0x0, - NULL, - HFILL - } - }, - { - &hf_rtpproxy_response_time, - { - "Response Time", - "rtpproxy.response_time", - FT_RELATIVE_TIME, - BASE_NONE, - NULL, - 0x0, - "The time between the Request and the Reply", - HFILL - } - }, - { - &hf_rtpproxy_ng_bencode, - { - "RTPproxy-ng bencode packet", - "rtpproxy.ng.bencode", - FT_STRING, - BASE_NONE, - NULL, - 0x0, - "Serialized structure of integers, dictionaries, strings and lists.", - HFILL - } - } - }; - - static ei_register_info ei[] = { - { &ei_rtpproxy_timeout, { "rtpproxy.response_timeout", PI_RESPONSE_CODE, PI_WARN, "TIMEOUT", EXPFILL }}, - { &ei_rtpproxy_notify_no_ip, { "rtpproxy.notify_no_ip", PI_RESPONSE_CODE, PI_COMMENT, "No notification IP address provided. Using ip.src or ipv6.src as a value.", EXPFILL }}, - { &ei_rtpproxy_bad_ipv4, { "rtpproxy.bad_ipv4", PI_MALFORMED, PI_ERROR, "Bad IPv4", EXPFILL }}, - { &ei_rtpproxy_bad_ipv6, { "rtpproxy.bad_ipv6", PI_MALFORMED, PI_ERROR, "Bad IPv6", EXPFILL }}, - }; - - /* Setup protocol subtree array */ - static gint *ett[] = { - &ett_rtpproxy, - &ett_rtpproxy_request, - &ett_rtpproxy_command, - &ett_rtpproxy_command_parameters, - &ett_rtpproxy_command_parameters_codecs, - &ett_rtpproxy_command_parameters_local, - &ett_rtpproxy_command_parameters_remote, - &ett_rtpproxy_command_parameters_repacketize, - &ett_rtpproxy_command_parameters_dtmf, - &ett_rtpproxy_command_parameters_cmap, - &ett_rtpproxy_command_parameters_proto, - &ett_rtpproxy_command_parameters_transcode, - &ett_rtpproxy_command_parameters_acc, - &ett_rtpproxy_tag, - &ett_rtpproxy_notify, - &ett_rtpproxy_reply, - &ett_rtpproxy_ng_bencode - }; - - proto_rtpproxy = proto_register_protocol ( - "Sippy RTPproxy Protocol", /* name */ - "RTPproxy", /* short name */ - "rtpproxy" /* abbrev */ - ); - - proto_register_field_array(proto_rtpproxy, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); - - expert_rtpproxy_module = expert_register_protocol(proto_rtpproxy); - expert_register_field_array(expert_rtpproxy_module, ei, array_length(ei)); - - rtpproxy_module = prefs_register_protocol(proto_rtpproxy, proto_reg_handoff_rtpproxy); - - prefs_register_uint_preference(rtpproxy_module, "tcp.port", - "RTPproxy TCP Port", /* Title */ - "RTPproxy TCP Port", /* Descr */ - 10, - &rtpproxy_tcp_port); - - prefs_register_uint_preference(rtpproxy_module, "udp.port", - "RTPproxy UDP Port", /* Title */ - "RTPproxy UDP Port", /* Descr */ - 10, - &rtpproxy_udp_port); - - prefs_register_bool_preference(rtpproxy_module, "establish_conversation", + module_t *rtpproxy_module; + expert_module_t* expert_rtpproxy_module; + + static hf_register_info hf[] = { + { + &hf_rtpproxy_cookie, + { + "Cookie", + "rtpproxy.cookie", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_version_request, + { + "Version Request", + "rtpproxy.version", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_version_supported, + { + "Version Supported", + "rtpproxy.version_supported", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_error, + { + "Error", + "rtpproxy.error", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_ok, + { + "Ok", + "rtpproxy.ok", + FT_UINT8, + BASE_DEC, + VALS(oktypenames), + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_status, + { + "Status", + "rtpproxy.status", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_ipv4, + { + "IPv4", + "rtpproxy.ipv4", + FT_IPv4, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_ipv6, + { + "IPv6", + "rtpproxy.ipv6", + FT_IPv6, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_port, + { + "Port", + "rtpproxy.port", + FT_UINT16, /* 0 - 65535 */ + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_request, + { + "Request", + "rtpproxy.request", + FT_NONE, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command, + { + "Command", + "rtpproxy.command", + FT_UINT8, + BASE_DEC, + VALS(commandtypenames), + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameters, + { + "Command parameters", + "rtpproxy.command_parameters", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter, + { + "Parameter", + "rtpproxy.command_parameter", + FT_UINT8, + BASE_DEC, + VALS(paramtypenames), + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter_codec, + { + "Allowed codec", + "rtpproxy.command_parameter_codec", + FT_UINT8, /* 0 - 127 */ + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter_local_ipv4, + { + "Local IPv4 address", + "rtpproxy.command_parameter_local_ipv4", + FT_IPv4, /* FIXME - is it ever possible to see IPv6 here? */ + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter_remote_ipv4, + { + "Remote IPv4 address", + "rtpproxy.command_parameter_remote_ipv4", + FT_IPv4, /* FIXME - is it ever possible to see IPv6 here? */ + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter_repacketize, + { + "Repacketize (ms)", + "rtpproxy.command_parameter_repacketize", + FT_UINT16, /* 0 - 1000 milliseconds */ + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter_dtmf, + { + "DTMF payload ID", + "rtpproxy.command_parameter_dtmf", + FT_UINT8, /* 0 - 127 */ + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter_proto, + { + "RTP tramsission protocol", + "rtpproxy.command_parameter_proto", + FT_UINT8, + BASE_DEC, + VALS(prototypenames), + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter_transcode, + { + "Transcode to", + "rtpproxy.command_parameter_transcode", + FT_UINT8, /* 0 - 127 */ + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_command_parameter_acc, + { + "Accounting", + "rtpproxy.command_parameter_acc", + FT_UINT8, + BASE_DEC, + VALS(acctypenames), + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_copy_target, + { + "Copy target", + "rtpproxy.copy_target", + FT_STRING, /* Filename or UDP address, e.g. /var/tmp/fileXXXX.yyy or IP:Port */ + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_playback_filename, + { + "Playback filename", + "rtpproxy.playback_filename", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_playback_codec, + { + "Playback codec", + "rtpproxy.playback_codec", + FT_UINT8, /* 0 - 127 */ + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_callid, + { + "Call-ID", + "rtpproxy.callid", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_notify, + { + "Notify", + "rtpproxy.notify", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_tag, + { + "Tag", + "rtpproxy.tag", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_mediaid, + { + "Media-ID", + "rtpproxy.mediaid", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_notify_ipv4, + { + "Notification IPv4", + "rtpproxy.notify_ipv4", + FT_IPv4, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_notify_ipv6, + { + "Notification IPv6", + "rtpproxy.notify_ipv6", + FT_IPv6, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_notify_port, + { + "Notification Port", + "rtpproxy.notify_port", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_notify_tag, + { + "Notification Tag", + "rtpproxy.notify_tag", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_reply, + { + "Reply", + "rtpproxy.reply", + FT_NONE, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_lf, + { + "LF", + "rtpproxy.lf", + FT_NONE, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_request_in, + { + "Request In", + "rtpproxy.request_in", + FT_FRAMENUM, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + + }, + { + &hf_rtpproxy_response_in, + { + "Response In", + "rtpproxy.response_in", + FT_FRAMENUM, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_rtpproxy_response_time, + { + "Response Time", + "rtpproxy.response_time", + FT_RELATIVE_TIME, + BASE_NONE, + NULL, + 0x0, + "The time between the Request and the Reply", + HFILL + } + }, + { + &hf_rtpproxy_ng_bencode, + { + "RTPproxy-ng bencode packet", + "rtpproxy.ng.bencode", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + "Serialized structure of integers, dictionaries, strings and lists.", + HFILL + } + } + }; + + static ei_register_info ei[] = { + { &ei_rtpproxy_timeout, + { "rtpproxy.response_timeout", PI_RESPONSE_CODE, PI_WARN, + "TIMEOUT", EXPFILL }}, + { &ei_rtpproxy_notify_no_ip, + { "rtpproxy.notify_no_ip", PI_RESPONSE_CODE, PI_COMMENT, + "No notification IP address provided. Using ip.src or ipv6.src as a value.", EXPFILL }}, + { &ei_rtpproxy_bad_ipv4, + { "rtpproxy.bad_ipv4", PI_MALFORMED, PI_ERROR, + "Bad IPv4", EXPFILL }}, + { &ei_rtpproxy_bad_ipv6, + { "rtpproxy.bad_ipv6", PI_MALFORMED, PI_ERROR, + "Bad IPv6", EXPFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_rtpproxy, + &ett_rtpproxy_request, + &ett_rtpproxy_command, + &ett_rtpproxy_command_parameters, + &ett_rtpproxy_command_parameters_codecs, + &ett_rtpproxy_command_parameters_local, + &ett_rtpproxy_command_parameters_remote, + &ett_rtpproxy_command_parameters_repacketize, + &ett_rtpproxy_command_parameters_dtmf, + &ett_rtpproxy_command_parameters_cmap, + &ett_rtpproxy_command_parameters_proto, + &ett_rtpproxy_command_parameters_transcode, + &ett_rtpproxy_command_parameters_acc, + &ett_rtpproxy_tag, + &ett_rtpproxy_notify, + &ett_rtpproxy_reply, + &ett_rtpproxy_ng_bencode + }; + + proto_rtpproxy = proto_register_protocol ( + "Sippy RTPproxy Protocol", /* name */ + "RTPproxy", /* short name */ + "rtpproxy" /* abbrev */ + ); + + proto_register_field_array(proto_rtpproxy, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + expert_rtpproxy_module = expert_register_protocol(proto_rtpproxy); + expert_register_field_array(expert_rtpproxy_module, ei, array_length(ei)); + + rtpproxy_module = prefs_register_protocol(proto_rtpproxy, proto_reg_handoff_rtpproxy); + + prefs_register_uint_preference(rtpproxy_module, "tcp.port", + "RTPproxy TCP Port", /* Title */ + "RTPproxy TCP Port", /* Descr */ + 10, + &rtpproxy_tcp_port); + + prefs_register_uint_preference(rtpproxy_module, "udp.port", + "RTPproxy UDP Port", /* Title */ + "RTPproxy UDP Port", /* Descr */ + 10, + &rtpproxy_udp_port); + + prefs_register_bool_preference(rtpproxy_module, "establish_conversation", "Establish Media Conversation", "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based " "upon port numbers found in RTPproxy answers", &rtpproxy_establish_conversation); - prefs_register_uint_preference(rtpproxy_module, "reply.timeout", - "RTPproxy reply timeout", /* Title */ - "Maximum timeout value in waiting for reply from RTPProxy (in milliseconds).", /* Descr */ - 10, - &rtpproxy_timeout); + prefs_register_uint_preference(rtpproxy_module, "reply.timeout", + "RTPproxy reply timeout", /* Title */ + "Maximum timeout value in waiting for reply from RTPProxy (in milliseconds).", /* Descr */ + 10, + &rtpproxy_timeout); } void proto_reg_handoff_rtpproxy(void) { - static guint old_rtpproxy_tcp_port = 0; - static guint old_rtpproxy_udp_port = 0; - - static gboolean rtpproxy_initialized = FALSE; - - static dissector_handle_t rtpproxy_tcp_handle, rtpproxy_udp_handle; - - if(!rtpproxy_initialized){ - rtpproxy_tcp_handle = new_create_dissector_handle(dissect_rtpproxy, proto_rtpproxy); - rtpproxy_udp_handle = new_create_dissector_handle(dissect_rtpproxy, proto_rtpproxy); - rtpproxy_initialized = TRUE; - } - - /* Register TCP port for dissection */ - if(old_rtpproxy_tcp_port != 0 && old_rtpproxy_tcp_port != rtpproxy_tcp_port) - dissector_delete_uint("tcp.port", old_rtpproxy_tcp_port, rtpproxy_tcp_handle); - if(rtpproxy_tcp_port != 0 && old_rtpproxy_tcp_port != rtpproxy_tcp_port) - dissector_add_uint("tcp.port", rtpproxy_tcp_port, rtpproxy_tcp_handle); - old_rtpproxy_tcp_port = rtpproxy_tcp_port; - - /* Register UDP port for dissection */ - if(old_rtpproxy_udp_port != 0 && old_rtpproxy_udp_port != rtpproxy_udp_port) - dissector_delete_uint("udp.port", old_rtpproxy_udp_port, rtpproxy_udp_handle); - if(rtpproxy_udp_port != 0 && old_rtpproxy_udp_port != rtpproxy_udp_port) - dissector_add_uint("udp.port", rtpproxy_udp_port, rtpproxy_udp_handle); - old_rtpproxy_udp_port = rtpproxy_udp_port; - - rtcp_handle = find_dissector("rtcp"); - rtp_events_handle = find_dissector("rtpevent"); - rtp_handle = find_dissector("rtp"); - bencode_handle = find_dissector("bencode"); - - /* Calculate nstime_t struct for the timeout from the rtpproxy_timeout value in milliseconds */ - rtpproxy_timeout_ns.secs = (rtpproxy_timeout - rtpproxy_timeout % 1000) / 1000; - rtpproxy_timeout_ns.nsecs = (rtpproxy_timeout % 1000) * 1000; + static guint old_rtpproxy_tcp_port = 0; + static guint old_rtpproxy_udp_port = 0; + + static gboolean rtpproxy_initialized = FALSE; + + static dissector_handle_t rtpproxy_tcp_handle, rtpproxy_udp_handle; + + if(!rtpproxy_initialized){ + rtpproxy_tcp_handle = new_create_dissector_handle(dissect_rtpproxy, proto_rtpproxy); + rtpproxy_udp_handle = new_create_dissector_handle(dissect_rtpproxy, proto_rtpproxy); + rtpproxy_initialized = TRUE; + } + + /* Register TCP port for dissection */ + if(old_rtpproxy_tcp_port != 0 && old_rtpproxy_tcp_port != rtpproxy_tcp_port) + dissector_delete_uint("tcp.port", old_rtpproxy_tcp_port, rtpproxy_tcp_handle); + if(rtpproxy_tcp_port != 0 && old_rtpproxy_tcp_port != rtpproxy_tcp_port) + dissector_add_uint("tcp.port", rtpproxy_tcp_port, rtpproxy_tcp_handle); + old_rtpproxy_tcp_port = rtpproxy_tcp_port; + + /* Register UDP port for dissection */ + if(old_rtpproxy_udp_port != 0 && old_rtpproxy_udp_port != rtpproxy_udp_port) + dissector_delete_uint("udp.port", old_rtpproxy_udp_port, rtpproxy_udp_handle); + if(rtpproxy_udp_port != 0 && old_rtpproxy_udp_port != rtpproxy_udp_port) + dissector_add_uint("udp.port", rtpproxy_udp_port, rtpproxy_udp_handle); + old_rtpproxy_udp_port = rtpproxy_udp_port; + + rtcp_handle = find_dissector("rtcp"); + rtp_events_handle = find_dissector("rtpevent"); + rtp_handle = find_dissector("rtp"); + bencode_handle = find_dissector("bencode"); + + /* Calculate nstime_t struct for the timeout from the rtpproxy_timeout value in milliseconds */ + rtpproxy_timeout_ns.secs = (rtpproxy_timeout - rtpproxy_timeout % 1000) / 1000; + rtpproxy_timeout_ns.nsecs = (rtpproxy_timeout % 1000) * 1000; } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: - * c-basic-offset: 8 + * c-basic-offset: 4 * tab-width: 8 - * indent-tabs-mode: t + * indent-tabs-mode: nil * End: * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: */ diff --git a/epan/dissectors/packet-ssh.c b/epan/dissectors/packet-ssh.c index 411a825f23..b52f0c6bb3 100644 --- a/epan/dissectors/packet-ssh.c +++ b/epan/dissectors/packet-ssh.c @@ -65,58 +65,58 @@ void proto_register_ssh(void); void proto_reg_handoff_ssh(void); /* SSH Version 1 definition , from openssh ssh1.h */ -#define SSH1_MSG_NONE 0 /* no message */ -#define SSH1_MSG_DISCONNECT 1 /* cause (string) */ -#define SSH1_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */ -#define SSH1_CMSG_SESSION_KEY 3 /* key (BIGNUM) */ -#define SSH1_CMSG_USER 4 /* user (string) */ +#define SSH1_MSG_NONE 0 /* no message */ +#define SSH1_MSG_DISCONNECT 1 /* cause (string) */ +#define SSH1_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */ +#define SSH1_CMSG_SESSION_KEY 3 /* key (BIGNUM) */ +#define SSH1_CMSG_USER 4 /* user (string) */ -#define SSH_VERSION_UNKNOWN 0 -#define SSH_VERSION_1 1 -#define SSH_VERSION_2 2 +#define SSH_VERSION_UNKNOWN 0 +#define SSH_VERSION_1 1 +#define SSH_VERSION_2 2 /* proto data */ struct ssh_peer_data { - guint counter; + guint counter; - guint32 frame_version_start; - guint32 frame_version_end; + guint32 frame_version_start; + guint32 frame_version_end; - guint32 frame_key_start; - guint32 frame_key_end; + guint32 frame_key_start; + guint32 frame_key_end; - gchar* kex_proposal; + gchar* kex_proposal; - /* For all subsequent proposals, - [0] is client-to-server and [1] is server-to-client. */ + /* For all subsequent proposals, + [0] is client-to-server and [1] is server-to-client. */ #define CLIENT_TO_SERVER_PROPOSAL 0 #define SERVER_TO_CLIENT_PROPOSAL 1 - gchar* mac_proposals[2]; - gchar* mac; - gint mac_length; + gchar* mac_proposals[2]; + gchar* mac; + gint mac_length; - gchar* enc_proposals[2]; - gchar* enc; + gchar* enc_proposals[2]; + gchar* enc; - gchar* comp_proposals[2]; - gchar* comp; + gchar* comp_proposals[2]; + gchar* comp; - gint length_is_plaintext; + gint length_is_plaintext; }; struct ssh_flow_data { - guint version; + guint version; - gchar* kex; - int (*kex_specific_dissector)(guint8 msg_code, tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree); + gchar* kex; + int (*kex_specific_dissector)(guint8 msg_code, tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree); - /* [0] is client's, [1] is server's */ + /* [0] is client's, [1] is server's */ #define CLIENT_PEER_DATA 0 #define SERVER_PEER_DATA 1 - struct ssh_peer_data peer_data[2]; + struct ssh_peer_data peer_data[2]; }; static int proto_ssh = -1; @@ -186,138 +186,138 @@ static dissector_handle_t ssh_handle; /* Message Numbers (from RFC 4250) (1-255) */ /* Transport layer protocol: generic (1-19) */ -#define SSH_MSG_DISCONNECT 1 -#define SSH_MSG_IGNORE 2 -#define SSH_MSG_UNIMPLEMENTED 3 -#define SSH_MSG_DEBUG 4 -#define SSH_MSG_SERVICE_REQUEST 5 -#define SSH_MSG_SERVICE_ACCEPT 6 +#define SSH_MSG_DISCONNECT 1 +#define SSH_MSG_IGNORE 2 +#define SSH_MSG_UNIMPLEMENTED 3 +#define SSH_MSG_DEBUG 4 +#define SSH_MSG_SERVICE_REQUEST 5 +#define SSH_MSG_SERVICE_ACCEPT 6 /* Transport layer protocol: Algorithm negotiation (20-29) */ -#define SSH_MSG_KEXINIT 20 -#define SSH_MSG_NEWKEYS 21 +#define SSH_MSG_KEXINIT 20 +#define SSH_MSG_NEWKEYS 21 /* Transport layer: Key exchange method specific (reusable) (30-49) */ -#define SSH_MSG_KEXDH_INIT 30 -#define SSH_MSG_KEXDH_REPLY 31 +#define SSH_MSG_KEXDH_INIT 30 +#define SSH_MSG_KEXDH_REPLY 31 -#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30 -#define SSH_MSG_KEX_DH_GEX_GROUP 31 -#define SSH_MSG_KEX_DH_GEX_INIT 32 -#define SSH_MSG_KEX_DH_GEX_REPLY 33 -#define SSH_MSG_KEX_DH_GEX_REQUEST 34 +#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30 +#define SSH_MSG_KEX_DH_GEX_GROUP 31 +#define SSH_MSG_KEX_DH_GEX_INIT 32 +#define SSH_MSG_KEX_DH_GEX_REPLY 33 +#define SSH_MSG_KEX_DH_GEX_REQUEST 34 /* User authentication protocol: generic (50-59) */ -#define SSH_MSG_USERAUTH_REQUEST 50 -#define SSH_MSG_USERAUTH_FAILURE 51 -#define SSH_MSG_USERAUTH_SUCCESS 52 -#define SSH_MSG_USERAUTH_BANNER 53 +#define SSH_MSG_USERAUTH_REQUEST 50 +#define SSH_MSG_USERAUTH_FAILURE 51 +#define SSH_MSG_USERAUTH_SUCCESS 52 +#define SSH_MSG_USERAUTH_BANNER 53 /* User authentication protocol: method specific (reusable) (50-79) */ /* Connection protocol: generic (80-89) */ -#define SSH_MSG_GLOBAL_REQUEST 80 -#define SSH_MSG_REQUEST_SUCCESS 81 -#define SSH_MSG_REQUEST_FAILURE 82 +#define SSH_MSG_GLOBAL_REQUEST 80 +#define SSH_MSG_REQUEST_SUCCESS 81 +#define SSH_MSG_REQUEST_FAILURE 82 /* Connection protocol: channel related messages (90-127) */ -#define SSH_MSG_CHANNEL_OPEN 90 -#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91 -#define SSH_MSG_CHANNEL_OPEN_FAILURE 92 -#define SSH_MSG_CHANNEL_WINDOW_ADJUST 93 -#define SSH_MSG_CHANNEL_DATA 94 -#define SSH_MSG_CHANNEL_EXTENDED_DATA 95 -#define SSH_MSG_CHANNEL_EOF 96 -#define SSH_MSG_CHANNEL_CLOSE 97 -#define SSH_MSG_CHANNEL_REQUEST 98 -#define SSH_MSG_CHANNEL_SUCCESS 99 -#define SSH_MSG_CHANNEL_FAILURE 100 +#define SSH_MSG_CHANNEL_OPEN 90 +#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91 +#define SSH_MSG_CHANNEL_OPEN_FAILURE 92 +#define SSH_MSG_CHANNEL_WINDOW_ADJUST 93 +#define SSH_MSG_CHANNEL_DATA 94 +#define SSH_MSG_CHANNEL_EXTENDED_DATA 95 +#define SSH_MSG_CHANNEL_EOF 96 +#define SSH_MSG_CHANNEL_CLOSE 97 +#define SSH_MSG_CHANNEL_REQUEST 98 +#define SSH_MSG_CHANNEL_SUCCESS 99 +#define SSH_MSG_CHANNEL_FAILURE 100 /* 128-191 reserved for client protocols */ /* 192-255 local extensions */ static const value_string ssh2_msg_vals[] = { - { SSH_MSG_DISCONNECT, "Disconnect" }, - { SSH_MSG_IGNORE, "Ignore" }, - { SSH_MSG_UNIMPLEMENTED, "Unimplemented" }, - { SSH_MSG_DEBUG, "Debug" }, - { SSH_MSG_SERVICE_REQUEST, "Service Request" }, - { SSH_MSG_SERVICE_ACCEPT, "Service Accept" }, - { SSH_MSG_KEXINIT, "Key Exchange Init" }, - { SSH_MSG_NEWKEYS, "New Keys" }, - { SSH_MSG_USERAUTH_REQUEST, "User Authentication Request" }, - { SSH_MSG_USERAUTH_FAILURE, "User Authentication Failure" }, - { SSH_MSG_USERAUTH_SUCCESS, "User Authentication Success" }, - { SSH_MSG_USERAUTH_BANNER, "User Authentication Banner" }, - { SSH_MSG_GLOBAL_REQUEST, "Global Request" }, - { SSH_MSG_REQUEST_SUCCESS, "Request Success" }, - { SSH_MSG_REQUEST_FAILURE, "Request Failure" }, - { SSH_MSG_CHANNEL_OPEN, "Channel Open" }, - { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" }, - { SSH_MSG_CHANNEL_OPEN_FAILURE, "Channel Open Failure" }, - { SSH_MSG_CHANNEL_WINDOW_ADJUST, "Window Adjust" }, - { SSH_MSG_CHANNEL_DATA, "Channel Data" }, - { SSH_MSG_CHANNEL_EXTENDED_DATA, "Channel Extended Data" }, - { SSH_MSG_CHANNEL_EOF, "Channel EOF" }, - { SSH_MSG_CHANNEL_CLOSE, "Channel Close" }, - { SSH_MSG_CHANNEL_REQUEST, "Channel Request" }, - { SSH_MSG_CHANNEL_SUCCESS, "Channel Success" }, - { SSH_MSG_CHANNEL_FAILURE, "Channel Failure" }, - { 0, NULL } + { SSH_MSG_DISCONNECT, "Disconnect" }, + { SSH_MSG_IGNORE, "Ignore" }, + { SSH_MSG_UNIMPLEMENTED, "Unimplemented" }, + { SSH_MSG_DEBUG, "Debug" }, + { SSH_MSG_SERVICE_REQUEST, "Service Request" }, + { SSH_MSG_SERVICE_ACCEPT, "Service Accept" }, + { SSH_MSG_KEXINIT, "Key Exchange Init" }, + { SSH_MSG_NEWKEYS, "New Keys" }, + { SSH_MSG_USERAUTH_REQUEST, "User Authentication Request" }, + { SSH_MSG_USERAUTH_FAILURE, "User Authentication Failure" }, + { SSH_MSG_USERAUTH_SUCCESS, "User Authentication Success" }, + { SSH_MSG_USERAUTH_BANNER, "User Authentication Banner" }, + { SSH_MSG_GLOBAL_REQUEST, "Global Request" }, + { SSH_MSG_REQUEST_SUCCESS, "Request Success" }, + { SSH_MSG_REQUEST_FAILURE, "Request Failure" }, + { SSH_MSG_CHANNEL_OPEN, "Channel Open" }, + { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" }, + { SSH_MSG_CHANNEL_OPEN_FAILURE, "Channel Open Failure" }, + { SSH_MSG_CHANNEL_WINDOW_ADJUST, "Window Adjust" }, + { SSH_MSG_CHANNEL_DATA, "Channel Data" }, + { SSH_MSG_CHANNEL_EXTENDED_DATA, "Channel Extended Data" }, + { SSH_MSG_CHANNEL_EOF, "Channel EOF" }, + { SSH_MSG_CHANNEL_CLOSE, "Channel Close" }, + { SSH_MSG_CHANNEL_REQUEST, "Channel Request" }, + { SSH_MSG_CHANNEL_SUCCESS, "Channel Success" }, + { SSH_MSG_CHANNEL_FAILURE, "Channel Failure" }, + { 0, NULL } }; static const value_string ssh2_kex_dh_msg_vals[] = { - { SSH_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init" }, - { SSH_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply" }, - { 0, NULL } + { SSH_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init" }, + { SSH_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply" }, + { 0, NULL } }; static const value_string ssh2_kex_dh_gex_msg_vals[] = { - { SSH_MSG_KEX_DH_GEX_REQUEST_OLD, "Diffie-Hellman Group Exchange Request (Old)" }, - { SSH_MSG_KEX_DH_GEX_GROUP, "Diffie-Hellman Group Exchange Group" }, - { SSH_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman Group Exchange Init" }, - { SSH_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman Group Exchange Reply" }, - { SSH_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman Group Exchange Request" }, - { 0, NULL } + { SSH_MSG_KEX_DH_GEX_REQUEST_OLD, "Diffie-Hellman Group Exchange Request (Old)" }, + { SSH_MSG_KEX_DH_GEX_GROUP, "Diffie-Hellman Group Exchange Group" }, + { SSH_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman Group Exchange Init" }, + { SSH_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman Group Exchange Reply" }, + { SSH_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman Group Exchange Request" }, + { 0, NULL } }; static const value_string ssh1_msg_vals[] = { - {SSH1_MSG_NONE, "No Message"}, - {SSH1_MSG_DISCONNECT, "Disconnect"}, - {SSH1_SMSG_PUBLIC_KEY, "Public Key"}, - {SSH1_CMSG_SESSION_KEY, "Session Key"}, - {SSH1_CMSG_USER, "User"}, - {0, NULL} + {SSH1_MSG_NONE, "No Message"}, + {SSH1_MSG_DISCONNECT, "Disconnect"}, + {SSH1_SMSG_PUBLIC_KEY, "Public Key"}, + {SSH1_CMSG_SESSION_KEY, "Session Key"}, + {SSH1_CMSG_USER, "User"}, + {0, NULL} }; static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree, - int is_response, - struct ssh_flow_data *global_data); + int is_response, + struct ssh_flow_data *global_data); static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree, - int hf_index_length, int hf_index_value, gchar **store); + int hf_index_length, int hf_index_value, gchar **store); static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_flow_data *global_data, - int offset, proto_tree *tree, int is_response, - gboolean *need_desegmentation); + struct ssh_flow_data *global_data, + int offset, proto_tree *tree, int is_response, + gboolean *need_desegmentation); static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_flow_data *global_data, - int offset, proto_tree *tree, int is_response, - gboolean *need_desegmentation); + struct ssh_flow_data *global_data, + int offset, proto_tree *tree, int is_response, + gboolean *need_desegmentation); static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_flow_data *global_data, - int offset, proto_tree *tree, int is_response, - gboolean *need_desegmentation); + struct ssh_flow_data *global_data, + int offset, proto_tree *tree, int is_response, + gboolean *need_desegmentation); static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb, - packet_info *pinfo, int offset, proto_tree *tree); + packet_info *pinfo, int offset, proto_tree *tree); static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb, - packet_info *pinfo, int offset, proto_tree *tree); + packet_info *pinfo, int offset, proto_tree *tree); static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_flow_data *global_data, - int offset, proto_tree *tree, int is_response, guint *version, - gboolean *need_desegmentation); + struct ssh_flow_data *global_data, + int offset, proto_tree *tree, int is_response, guint *version, + gboolean *need_desegmentation); static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_peer_data *peer_data, - int offset, proto_tree *tree); + struct ssh_peer_data *peer_data, + int offset, proto_tree *tree); static void ssh_choose_algo(gchar *client, gchar *server, gchar **result); static void ssh_set_mac_length(struct ssh_peer_data *peer_data); static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data); @@ -327,1103 +327,1103 @@ static void dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - proto_tree *ssh_tree = NULL; - proto_item *ti; - conversation_t *conversation; - int last_offset, offset = 0; - - gboolean is_response = (pinfo->destport != pinfo->match_uint), - need_desegmentation; - guint version; - - struct ssh_flow_data *global_data=NULL; - struct ssh_peer_data *peer_data; - - conversation = find_or_create_conversation(pinfo); - - global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh); - if (!global_data) { - global_data = (struct ssh_flow_data *)wmem_alloc0(wmem_file_scope(), sizeof(struct ssh_flow_data)); - global_data->version=SSH_VERSION_UNKNOWN; - global_data->kex_specific_dissector=ssh_dissect_kex_dh; - global_data->peer_data[CLIENT_PEER_DATA].mac_length=-1; - global_data->peer_data[SERVER_PEER_DATA].mac_length=-1; - - conversation_add_proto_data(conversation, proto_ssh, global_data); - } - - peer_data = &global_data->peer_data[is_response]; - - if (tree) { - ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA); - ssh_tree = proto_item_add_subtree(ti, ett_ssh); - } - - version = global_data->version; - - switch(version) { - case SSH_VERSION_UNKNOWN: - col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH"); - break; - case SSH_VERSION_1: - col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1"); - break; - case SSH_VERSION_2: - col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2"); - break; - - } - - col_clear(pinfo->cinfo, COL_INFO); - - while(tvb_reported_length_remaining(tvb, offset)> 0) { - gboolean after_version_start = (peer_data->frame_version_start == 0 || - pinfo->fd->num >= peer_data->frame_version_start); - gboolean before_version_end = (peer_data->frame_version_end == 0 || - pinfo->fd->num <= peer_data->frame_version_end); - - need_desegmentation = FALSE; - last_offset = offset; - - peer_data->counter++; - - if (after_version_start && before_version_end && - (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) { - if (peer_data->frame_version_start == 0) - peer_data->frame_version_start = pinfo->fd->num; - - offset = ssh_dissect_protocol(tvb, pinfo, - global_data, - offset, ssh_tree, is_response, - &version, &need_desegmentation); - - if (!need_desegmentation) { - peer_data->frame_version_end = pinfo->fd->num; - global_data->version = version; - } - } else { - switch(version) { - - case SSH_VERSION_UNKNOWN: - offset = ssh_dissect_encrypted_packet(tvb, pinfo, - &global_data->peer_data[is_response], offset, ssh_tree); - break; - - case SSH_VERSION_1: - offset = ssh_dissect_ssh1(tvb, pinfo, global_data, - offset, ssh_tree, is_response, - &need_desegmentation); - break; - - case SSH_VERSION_2: - offset = ssh_dissect_ssh2(tvb, pinfo, global_data, - offset, ssh_tree, is_response, - &need_desegmentation); - break; - } - } - - if (need_desegmentation) - return; - if (offset <= last_offset) - THROW(ReportedBoundsError); - } - - col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client"); + proto_tree *ssh_tree = NULL; + proto_item *ti; + conversation_t *conversation; + int last_offset, offset = 0; + + gboolean is_response = (pinfo->destport != pinfo->match_uint), + need_desegmentation; + guint version; + + struct ssh_flow_data *global_data=NULL; + struct ssh_peer_data *peer_data; + + conversation = find_or_create_conversation(pinfo); + + global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh); + if (!global_data) { + global_data = (struct ssh_flow_data *)wmem_alloc0(wmem_file_scope(), sizeof(struct ssh_flow_data)); + global_data->version=SSH_VERSION_UNKNOWN; + global_data->kex_specific_dissector=ssh_dissect_kex_dh; + global_data->peer_data[CLIENT_PEER_DATA].mac_length=-1; + global_data->peer_data[SERVER_PEER_DATA].mac_length=-1; + + conversation_add_proto_data(conversation, proto_ssh, global_data); + } + + peer_data = &global_data->peer_data[is_response]; + + if (tree) { + ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA); + ssh_tree = proto_item_add_subtree(ti, ett_ssh); + } + + version = global_data->version; + + switch(version) { + case SSH_VERSION_UNKNOWN: + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH"); + break; + case SSH_VERSION_1: + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1"); + break; + case SSH_VERSION_2: + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2"); + break; + + } + + col_clear(pinfo->cinfo, COL_INFO); + + while(tvb_reported_length_remaining(tvb, offset)> 0) { + gboolean after_version_start = (peer_data->frame_version_start == 0 || + pinfo->fd->num >= peer_data->frame_version_start); + gboolean before_version_end = (peer_data->frame_version_end == 0 || + pinfo->fd->num <= peer_data->frame_version_end); + + need_desegmentation = FALSE; + last_offset = offset; + + peer_data->counter++; + + if (after_version_start && before_version_end && + (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) { + if (peer_data->frame_version_start == 0) + peer_data->frame_version_start = pinfo->fd->num; + + offset = ssh_dissect_protocol(tvb, pinfo, + global_data, + offset, ssh_tree, is_response, + &version, &need_desegmentation); + + if (!need_desegmentation) { + peer_data->frame_version_end = pinfo->fd->num; + global_data->version = version; + } + } else { + switch(version) { + + case SSH_VERSION_UNKNOWN: + offset = ssh_dissect_encrypted_packet(tvb, pinfo, + &global_data->peer_data[is_response], offset, ssh_tree); + break; + + case SSH_VERSION_1: + offset = ssh_dissect_ssh1(tvb, pinfo, global_data, + offset, ssh_tree, is_response, + &need_desegmentation); + break; + + case SSH_VERSION_2: + offset = ssh_dissect_ssh2(tvb, pinfo, global_data, + offset, ssh_tree, is_response, + &need_desegmentation); + break; + } + } + + if (need_desegmentation) + return; + if (offset <= last_offset) + THROW(ReportedBoundsError); + } + + col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client"); } static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_flow_data *global_data, - int offset, proto_tree *tree, int is_response, - gboolean *need_desegmentation) + struct ssh_flow_data *global_data, + int offset, proto_tree *tree, int is_response, + gboolean *need_desegmentation) { - proto_item *ssh2_tree=NULL; - - struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; - - if (tree) { - wmem_strbuf_t *title=wmem_strbuf_new(wmem_packet_scope(), "SSH Version 2"); - - if (peer_data->enc || peer_data->mac || peer_data->comp) { - wmem_strbuf_append_printf(title, " ("); - if (peer_data->enc) - wmem_strbuf_append_printf(title, "encryption:%s%s", - peer_data->enc, - peer_data->mac || peer_data->comp - ? " " : ""); - if (peer_data->mac) - wmem_strbuf_append_printf(title, "mac:%s%s", - peer_data->mac, - peer_data->comp ? " " : ""); - if (peer_data->comp) - wmem_strbuf_append_printf(title, "compression:%s", - peer_data->comp); - wmem_strbuf_append_printf(title, ")"); - } - - ssh2_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh2, NULL, wmem_strbuf_get_str(title)); - } - - if ((peer_data->frame_key_start == 0) || - ((peer_data->frame_key_start <= pinfo->fd->num) && - ((peer_data->frame_key_end == 0) || (pinfo->fd->num <= peer_data->frame_key_end)))) { - offset = ssh_dissect_key_exchange(tvb, pinfo, global_data, - offset, ssh2_tree, is_response, - need_desegmentation); - } else { - offset = ssh_dissect_encrypted_packet(tvb, pinfo, - &global_data->peer_data[is_response], offset, ssh2_tree); - } - - return offset; + proto_item *ssh2_tree=NULL; + + struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; + + if (tree) { + wmem_strbuf_t *title=wmem_strbuf_new(wmem_packet_scope(), "SSH Version 2"); + + if (peer_data->enc || peer_data->mac || peer_data->comp) { + wmem_strbuf_append_printf(title, " ("); + if (peer_data->enc) + wmem_strbuf_append_printf(title, "encryption:%s%s", + peer_data->enc, + peer_data->mac || peer_data->comp + ? " " : ""); + if (peer_data->mac) + wmem_strbuf_append_printf(title, "mac:%s%s", + peer_data->mac, + peer_data->comp ? " " : ""); + if (peer_data->comp) + wmem_strbuf_append_printf(title, "compression:%s", + peer_data->comp); + wmem_strbuf_append_printf(title, ")"); + } + + ssh2_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh2, NULL, wmem_strbuf_get_str(title)); + } + + if ((peer_data->frame_key_start == 0) || + ((peer_data->frame_key_start <= pinfo->fd->num) && + ((peer_data->frame_key_end == 0) || (pinfo->fd->num <= peer_data->frame_key_end)))) { + offset = ssh_dissect_key_exchange(tvb, pinfo, global_data, + offset, ssh2_tree, is_response, + need_desegmentation); + } else { + offset = ssh_dissect_encrypted_packet(tvb, pinfo, + &global_data->peer_data[is_response], offset, ssh2_tree); + } + + return offset; } static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_flow_data *global_data, - int offset, proto_tree *tree, int is_response, - gboolean *need_desegmentation) + struct ssh_flow_data *global_data, + int offset, proto_tree *tree, int is_response, + gboolean *need_desegmentation) { - guint plen, padding_length, len; - guint8 msg_code; - guint remain_length; - - proto_item *ssh1_tree; - - struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; - - ssh1_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1"); - - /* - * We use "tvb_ensure_length_remaining()" to make sure there - * actually *is* data remaining. - * - * This means we're guaranteed that "remain_length" is positive. - */ - remain_length = tvb_ensure_length_remaining(tvb, offset); - /* - * Can we do reassembly? - */ - if (ssh_desegment && pinfo->can_desegment) { - /* - * Yes - would an SSH header starting at this offset be split - * across segment boundaries? - */ - if (remain_length < 4) { - /* - * Yes. Tell the TCP dissector where the data for - * this message starts in the data it handed us and - * that we need "some more data." Don't tell it - * exactly how many bytes we need because if/when we - * ask for even more (after the header) that will - * break reassembly. - */ - pinfo->desegment_offset = offset; - pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; - *need_desegmentation = TRUE; - return offset; - } - } - plen = tvb_get_ntohl(tvb, offset) ; - padding_length = 8 - plen%8; - - - if (ssh_desegment && pinfo->can_desegment) { - if (plen+4+padding_length > remain_length) { - pinfo->desegment_offset = offset; - pinfo->desegment_len = plen+padding_length - remain_length; - *need_desegmentation = TRUE; - return offset; - } - } - - if (plen >= 0xffff) { - if (ssh1_tree && plen > 0) { - proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb, - offset, 4, plen, "Overly large length %x", plen); - } - plen = remain_length-4-padding_length; - } else { - if (ssh1_tree && plen > 0) { - proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb, - offset, 4, plen); - } - } - offset+=4; + guint plen, padding_length, len; + guint8 msg_code; + guint remain_length; + + proto_item *ssh1_tree; + + struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; + + ssh1_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1"); + + /* + * We use "tvb_ensure_length_remaining()" to make sure there + * actually *is* data remaining. + * + * This means we're guaranteed that "remain_length" is positive. + */ + remain_length = tvb_ensure_length_remaining(tvb, offset); + /* + * Can we do reassembly? + */ + if (ssh_desegment && pinfo->can_desegment) { + /* + * Yes - would an SSH header starting at this offset be split + * across segment boundaries? + */ + if (remain_length < 4) { + /* + * Yes. Tell the TCP dissector where the data for + * this message starts in the data it handed us and + * that we need "some more data." Don't tell it + * exactly how many bytes we need because if/when we + * ask for even more (after the header) that will + * break reassembly. + */ + pinfo->desegment_offset = offset; + pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; + *need_desegmentation = TRUE; + return offset; + } + } + plen = tvb_get_ntohl(tvb, offset) ; + padding_length = 8 - plen%8; + + + if (ssh_desegment && pinfo->can_desegment) { + if (plen+4+padding_length > remain_length) { + pinfo->desegment_offset = offset; + pinfo->desegment_len = plen+padding_length - remain_length; + *need_desegmentation = TRUE; + return offset; + } + } + + if (plen >= 0xffff) { + if (ssh1_tree && plen > 0) { + proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb, + offset, 4, plen, "Overly large length %x", plen); + } + plen = remain_length-4-padding_length; + } else { + if (ssh1_tree && plen > 0) { + proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb, + offset, 4, plen); + } + } + offset+=4; /* padding length */ - if (tree) { - proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb, - offset, padding_length, padding_length); - } - offset += padding_length; - - /* msg_code */ - if ((peer_data->frame_key_start == 0) || - ((peer_data->frame_key_start >= pinfo->fd->num) && (pinfo->fd->num <= peer_data->frame_key_end))) { - msg_code = tvb_get_guint8(tvb, offset); - - proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_NA); - col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, - val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)")); - offset += 1; - len = plen -1; - if (!pinfo->fd->flags.visited) { - if (peer_data->frame_key_start == 0) - peer_data->frame_key_start = pinfo->fd->num; - peer_data->frame_key_end = pinfo->fd->num; - } - } else { - len = plen; - col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len); - } - /* payload */ - if (ssh1_tree) { - proto_tree_add_item(ssh1_tree, hf_ssh_payload, - tvb, offset, len, ENC_NA); - } - offset+=len; - - return offset; + if (tree) { + proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb, + offset, padding_length, padding_length); + } + offset += padding_length; + + /* msg_code */ + if ((peer_data->frame_key_start == 0) || + ((peer_data->frame_key_start >= pinfo->fd->num) && (pinfo->fd->num <= peer_data->frame_key_end))) { + msg_code = tvb_get_guint8(tvb, offset); + + proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_NA); + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, + val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)")); + offset += 1; + len = plen -1; + if (!pinfo->fd->flags.visited) { + if (peer_data->frame_key_start == 0) + peer_data->frame_key_start = pinfo->fd->num; + peer_data->frame_key_end = pinfo->fd->num; + } + } else { + len = plen; + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len); + } + /* payload */ + if (ssh1_tree) { + proto_tree_add_item(ssh1_tree, hf_ssh_payload, + tvb, offset, len, ENC_NA); + } + offset+=len; + + return offset; } static int ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree, - int hf_ssh_mpint_selection) + int hf_ssh_mpint_selection) { - guint len = tvb_get_ntohl(tvb, offset); - if (tree) { - proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb, - offset, 4, len); - } - offset+=4; - if (tree) { - proto_tree_add_item(tree, hf_ssh_mpint_selection, - tvb, offset, len, ENC_NA); - } - return 4+len; + guint len = tvb_get_ntohl(tvb, offset); + if (tree) { + proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb, + offset, 4, len); + } + offset+=4; + if (tree) { + proto_tree_add_item(tree, hf_ssh_mpint_selection, + tvb, offset, len, ENC_NA); + } + return 4+len; } static int ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree, - int hf_ssh_string, int hf_ssh_string_length) + int hf_ssh_string, int hf_ssh_string_length) { - guint len = tvb_get_ntohl(tvb, offset); - if (tree) { - proto_tree_add_uint(tree, hf_ssh_string_length, tvb, - offset, 4, len); - } - offset+=4; - if (tree) { - proto_tree_add_item(tree, hf_ssh_string, - tvb, offset, len, ENC_NA); - } - return 4+len; + guint len = tvb_get_ntohl(tvb, offset); + if (tree) { + proto_tree_add_uint(tree, hf_ssh_string_length, tvb, + offset, 4, len); + } + offset+=4; + if (tree) { + proto_tree_add_item(tree, hf_ssh_string, + tvb, offset, len, ENC_NA); + } + return 4+len; } static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_flow_data *global_data, - int offset, proto_tree *tree, int is_response, - gboolean *need_desegmentation) + struct ssh_flow_data *global_data, + int offset, proto_tree *tree, int is_response, + gboolean *need_desegmentation) { - guint plen, len; - guint8 padding_length; - guint remain_length; - int last_offset=offset; - guint msg_code; - - proto_item *ti; - proto_item *key_ex_tree =NULL; - - struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; - - /* - * We use "tvb_ensure_length_remaining()" to make sure there - * actually *is* data remaining. - * - * This means we're guaranteed that "remain_length" is positive. - */ - remain_length = tvb_ensure_length_remaining(tvb, offset); - /* - * Can we do reassembly? - */ - if (ssh_desegment && pinfo->can_desegment) { - /* - * Yes - would an SSH header starting at this offset - * be split across segment boundaries? - */ - if (remain_length < 4) { - /* - * Yes. Tell the TCP dissector where the data for - * this message starts in the data it handed us and - * that we need "some more data." Don't tell it - * exactly how many bytes we need because if/when we - * ask for even more (after the header) that will - * break reassembly. - */ - pinfo->desegment_offset = offset; - pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; - *need_desegmentation = TRUE; - return offset; - } - } - plen = tvb_get_ntohl(tvb, offset) ; - - if (ssh_desegment && pinfo->can_desegment) { - if (plen +4 > remain_length) { - pinfo->desegment_offset = offset; - pinfo->desegment_len = plen+4 - remain_length; - *need_desegmentation = TRUE; - return offset; - } - } - /* - * Need to check plen > 0x80000000 here - */ - - ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, - offset, 4, plen); - if (plen >= 0xffff) { - expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen); - plen = remain_length-4; - } - offset+=4; - - /* padding length */ - padding_length = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length); - offset += 1; - - key_ex_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_exchange, NULL, "Key Exchange"); - - /* msg_code */ - msg_code = tvb_get_guint8(tvb, offset); - - if (msg_code >= 30 && msg_code < 40) { - offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo, offset, key_ex_tree); - } else { - proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_NA); - offset += 1; - - col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, - val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)")); - - /* 16 bytes cookie */ - switch(msg_code) - { - case SSH_MSG_KEXINIT: - if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->fd->num)) { - offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data); - peer_data->frame_key_start = pinfo->fd->num; - } - break; - case SSH_MSG_NEWKEYS: - if (peer_data->frame_key_end == 0) { - peer_data->frame_key_end = pinfo->fd->num; - ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[is_response], - global_data->peer_data[SERVER_PEER_DATA].enc_proposals[is_response], - &peer_data->enc); - - /* some ciphers have their own MAC so the "negotiated" one is meaningless */ - if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") || - 0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) { - peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>"); - peer_data->mac_length = 16; - peer_data->length_is_plaintext = 1; - } - else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) { - peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>"); - peer_data->mac_length = 16; - } - else { - ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[is_response], - global_data->peer_data[SERVER_PEER_DATA].mac_proposals[is_response], - &peer_data->mac); - ssh_set_mac_length(peer_data); - } - - ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[is_response], - global_data->peer_data[SERVER_PEER_DATA].comp_proposals[is_response], - &peer_data->comp); - } - break; - } - } - - len = plen+4-padding_length-(offset-last_offset); - if (len > 0) { - proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA); - } - offset +=len; - - /* padding */ - proto_tree_add_item(key_ex_tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA); - offset+= padding_length; - - return offset; + guint plen, len; + guint8 padding_length; + guint remain_length; + int last_offset=offset; + guint msg_code; + + proto_item *ti; + proto_item *key_ex_tree =NULL; + + struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; + + /* + * We use "tvb_ensure_length_remaining()" to make sure there + * actually *is* data remaining. + * + * This means we're guaranteed that "remain_length" is positive. + */ + remain_length = tvb_ensure_length_remaining(tvb, offset); + /* + * Can we do reassembly? + */ + if (ssh_desegment && pinfo->can_desegment) { + /* + * Yes - would an SSH header starting at this offset + * be split across segment boundaries? + */ + if (remain_length < 4) { + /* + * Yes. Tell the TCP dissector where the data for + * this message starts in the data it handed us and + * that we need "some more data." Don't tell it + * exactly how many bytes we need because if/when we + * ask for even more (after the header) that will + * break reassembly. + */ + pinfo->desegment_offset = offset; + pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; + *need_desegmentation = TRUE; + return offset; + } + } + plen = tvb_get_ntohl(tvb, offset) ; + + if (ssh_desegment && pinfo->can_desegment) { + if (plen +4 > remain_length) { + pinfo->desegment_offset = offset; + pinfo->desegment_len = plen+4 - remain_length; + *need_desegmentation = TRUE; + return offset; + } + } + /* + * Need to check plen > 0x80000000 here + */ + + ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, + offset, 4, plen); + if (plen >= 0xffff) { + expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen); + plen = remain_length-4; + } + offset+=4; + + /* padding length */ + padding_length = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length); + offset += 1; + + key_ex_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_exchange, NULL, "Key Exchange"); + + /* msg_code */ + msg_code = tvb_get_guint8(tvb, offset); + + if (msg_code >= 30 && msg_code < 40) { + offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo, offset, key_ex_tree); + } else { + proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_NA); + offset += 1; + + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, + val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)")); + + /* 16 bytes cookie */ + switch(msg_code) + { + case SSH_MSG_KEXINIT: + if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->fd->num)) { + offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data); + peer_data->frame_key_start = pinfo->fd->num; + } + break; + case SSH_MSG_NEWKEYS: + if (peer_data->frame_key_end == 0) { + peer_data->frame_key_end = pinfo->fd->num; + ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[is_response], + global_data->peer_data[SERVER_PEER_DATA].enc_proposals[is_response], + &peer_data->enc); + + /* some ciphers have their own MAC so the "negotiated" one is meaningless */ + if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") || + 0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) { + peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>"); + peer_data->mac_length = 16; + peer_data->length_is_plaintext = 1; + } + else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) { + peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>"); + peer_data->mac_length = 16; + } + else { + ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[is_response], + global_data->peer_data[SERVER_PEER_DATA].mac_proposals[is_response], + &peer_data->mac); + ssh_set_mac_length(peer_data); + } + + ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[is_response], + global_data->peer_data[SERVER_PEER_DATA].comp_proposals[is_response], + &peer_data->comp); + } + break; + } + } + + len = plen+4-padding_length-(offset-last_offset); + if (len > 0) { + proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA); + } + offset +=len; + + /* padding */ + proto_tree_add_item(key_ex_tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA); + offset+= padding_length; + + return offset; } static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb, - packet_info *pinfo, int offset, proto_tree *tree) + packet_info *pinfo, int offset, proto_tree *tree) { - proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_NA); - offset += 1; + proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_NA); + offset += 1; - col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, - val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)")); + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, + val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)")); - switch (msg_code) { - case SSH_MSG_KEXDH_INIT: - offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e); - break; + switch (msg_code) { + case SSH_MSG_KEXDH_INIT: + offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e); + break; - case SSH_MSG_KEXDH_REPLY: - offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length); - offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f); - offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length); - break; - } + case SSH_MSG_KEXDH_REPLY: + offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length); + offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f); + offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length); + break; + } - return offset; + return offset; } static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb, - packet_info *pinfo, int offset, proto_tree *tree) + packet_info *pinfo, int offset, proto_tree *tree) { - proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_NA); - offset += 1; - - col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, - val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)")); - - switch (msg_code) { - case SSH_MSG_KEX_DH_GEX_REQUEST_OLD: - proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - break; - - case SSH_MSG_KEX_DH_GEX_GROUP: - offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_p); - offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_g); - break; - - case SSH_MSG_KEX_DH_GEX_INIT: - offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e); - break; - - case SSH_MSG_KEX_DH_GEX_REPLY: - offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length); - offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f); - offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length); - break; - - case SSH_MSG_KEX_DH_GEX_REQUEST: - proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - break; - } - - return offset; + proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_NA); + offset += 1; + + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, + val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)")); + + switch (msg_code) { + case SSH_MSG_KEX_DH_GEX_REQUEST_OLD: + proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + break; + + case SSH_MSG_KEX_DH_GEX_GROUP: + offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_p); + offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_g); + break; + + case SSH_MSG_KEX_DH_GEX_INIT: + offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e); + break; + + case SSH_MSG_KEX_DH_GEX_REPLY: + offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length); + offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f); + offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length); + break; + + case SSH_MSG_KEX_DH_GEX_REQUEST: + proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + break; + } + + return offset; } static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_peer_data *peer_data, - int offset, proto_tree *tree) + struct ssh_peer_data *peer_data, + int offset, proto_tree *tree) { - gint len; - guint plen; - - len = tvb_reported_length_remaining(tvb, offset); - col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len); - - if (tree) { - gint encrypted_len = len; - - if (len > 4 && peer_data->length_is_plaintext) { - plen = tvb_get_ntohl(tvb, offset) ; - proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen); - encrypted_len -= 4; - } - else if (len > 4) { - proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA); - encrypted_len -= 4; - } - - if (peer_data->mac_length>0) - encrypted_len -= peer_data->mac_length; - - proto_tree_add_item(tree, hf_ssh_encrypted_packet, - tvb, offset+4, encrypted_len, ENC_NA); - - if (peer_data->mac_length>0) - proto_tree_add_item(tree, hf_ssh_mac_string, - tvb, offset+4+encrypted_len, - peer_data->mac_length, ENC_NA); - } - offset+=len; - return offset; + gint len; + guint plen; + + len = tvb_reported_length_remaining(tvb, offset); + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len); + + if (tree) { + gint encrypted_len = len; + + if (len > 4 && peer_data->length_is_plaintext) { + plen = tvb_get_ntohl(tvb, offset) ; + proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen); + encrypted_len -= 4; + } + else if (len > 4) { + proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA); + encrypted_len -= 4; + } + + if (peer_data->mac_length>0) + encrypted_len -= peer_data->mac_length; + + proto_tree_add_item(tree, hf_ssh_encrypted_packet, + tvb, offset+4, encrypted_len, ENC_NA); + + if (peer_data->mac_length>0) + proto_tree_add_item(tree, hf_ssh_mac_string, + tvb, offset+4+encrypted_len, + peer_data->mac_length, ENC_NA); + } + offset+=len; + return offset; } static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo, - struct ssh_flow_data *global_data, - int offset, proto_tree *tree, int is_response, guint * version, - gboolean *need_desegmentation) + struct ssh_flow_data *global_data, + int offset, proto_tree *tree, int is_response, guint * version, + gboolean *need_desegmentation) { - guint remain_length; - gint linelen, protolen; - - /* - * If the first packet do not contain the banner, - * it is dump in the middle of a flow or not a ssh at all - */ - if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) { - offset = ssh_dissect_encrypted_packet(tvb, pinfo, - &global_data->peer_data[is_response], offset, tree); - return offset; - } - - if (!is_response) { - if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) { - *(version) = SSH_VERSION_2; - } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) { - *(version) = SSH_VERSION_2; - } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) { - *(version) = SSH_VERSION_1; - } - } - - /* - * We use "tvb_ensure_length_remaining()" to make sure there - * actually *is* data remaining. - * - * This means we're guaranteed that "remain_length" is positive. - */ - remain_length = tvb_ensure_length_remaining(tvb, offset); - /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); - */ - linelen = tvb_find_guint8(tvb, offset, -1, '\n'); - - if (ssh_desegment && pinfo->can_desegment) { - if (linelen == -1 || remain_length < (guint)linelen-offset) { - pinfo->desegment_offset = offset; - pinfo->desegment_len = linelen-remain_length; - *need_desegmentation = TRUE; - return offset; - } - } - if (linelen == -1) { - /* XXX - reassemble across segment boundaries? */ - linelen = remain_length; - protolen = linelen; - } else { - linelen = linelen - offset + 1; - - if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r') - protolen = linelen - 2; - else - protolen = linelen - 1; - } - - col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)", - tvb_format_text(tvb, offset, protolen)); - - proto_tree_add_item(tree, hf_ssh_protocol, - tvb, offset, linelen, ENC_ASCII|ENC_NA); - offset+=linelen; - return offset; + guint remain_length; + gint linelen, protolen; + + /* + * If the first packet do not contain the banner, + * it is dump in the middle of a flow or not a ssh at all + */ + if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) { + offset = ssh_dissect_encrypted_packet(tvb, pinfo, + &global_data->peer_data[is_response], offset, tree); + return offset; + } + + if (!is_response) { + if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) { + *(version) = SSH_VERSION_2; + } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) { + *(version) = SSH_VERSION_2; + } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) { + *(version) = SSH_VERSION_1; + } + } + + /* + * We use "tvb_ensure_length_remaining()" to make sure there + * actually *is* data remaining. + * + * This means we're guaranteed that "remain_length" is positive. + */ + remain_length = tvb_ensure_length_remaining(tvb, offset); + /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); + */ + linelen = tvb_find_guint8(tvb, offset, -1, '\n'); + + if (ssh_desegment && pinfo->can_desegment) { + if (linelen == -1 || remain_length < (guint)linelen-offset) { + pinfo->desegment_offset = offset; + pinfo->desegment_len = linelen-remain_length; + *need_desegmentation = TRUE; + return offset; + } + } + if (linelen == -1) { + /* XXX - reassemble across segment boundaries? */ + linelen = remain_length; + protolen = linelen; + } else { + linelen = linelen - offset + 1; + + if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r') + protolen = linelen - 2; + else + protolen = linelen - 1; + } + + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)", + tvb_format_text(tvb, offset, protolen)); + + proto_tree_add_item(tree, hf_ssh_protocol, + tvb, offset, linelen, ENC_ASCII|ENC_NA); + offset+=linelen; + return offset; } static void ssh_set_mac_length(struct ssh_peer_data *peer_data) { - char *size_str; - guint size=0; - char *mac_name = peer_data->mac; - char *strip; - - if (!mac_name) return; - mac_name = wmem_strdup(NULL, (const gchar *)mac_name); - if (!mac_name) return; - - /* strip trailing "-etm@openssh.com" or "@openssh.com" */ - strip = strstr(mac_name, "-etm@openssh.com"); - if (strip) { - peer_data->length_is_plaintext = 1; - *strip = '\0'; - } - else { - strip = strstr(mac_name, "@openssh.com"); - if (strip) *strip = '\0'; - } - - if ((size_str=g_strrstr(mac_name, "-")) && ((size=atoi(size_str+1)))) { - peer_data->mac_length = (size > 0) ? size / 8 : 0; - } - else if (strcmp(mac_name, "hmac-sha1") == 0) { - peer_data->mac_length = 20; - } - else if (strcmp(mac_name, "hmac-md5") == 0) { - peer_data->mac_length = 16; - } - else if (strcmp(mac_name, "hmac-ripemd160") == 0) { - peer_data->mac_length = 20; - } - else if (strcmp(mac_name, "none") == 0) { - peer_data->mac_length = 0; - } - - wmem_free(NULL, mac_name); + char *size_str; + guint size=0; + char *mac_name = peer_data->mac; + char *strip; + + if (!mac_name) return; + mac_name = wmem_strdup(NULL, (const gchar *)mac_name); + if (!mac_name) return; + + /* strip trailing "-etm@openssh.com" or "@openssh.com" */ + strip = strstr(mac_name, "-etm@openssh.com"); + if (strip) { + peer_data->length_is_plaintext = 1; + *strip = '\0'; + } + else { + strip = strstr(mac_name, "@openssh.com"); + if (strip) *strip = '\0'; + } + + if ((size_str=g_strrstr(mac_name, "-")) && ((size=atoi(size_str+1)))) { + peer_data->mac_length = (size > 0) ? size / 8 : 0; + } + else if (strcmp(mac_name, "hmac-sha1") == 0) { + peer_data->mac_length = 20; + } + else if (strcmp(mac_name, "hmac-md5") == 0) { + peer_data->mac_length = 16; + } + else if (strcmp(mac_name, "hmac-ripemd160") == 0) { + peer_data->mac_length = 20; + } + else if (strcmp(mac_name, "none") == 0) { + peer_data->mac_length = 0; + } + + wmem_free(NULL, mac_name); } static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data) { - const char *kex_name = global_data->kex; + const char *kex_name = global_data->kex; - if (!kex_name) return; + if (!kex_name) return; - if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 || - strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0) - { - global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex; - } + if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 || + strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0) + { + global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex; + } } static gint ssh_gslist_compare_strings(gconstpointer a, gconstpointer b) { - if (a == NULL && b == NULL) - return 0; - if (a == NULL) - return -1; - if (b == NULL) - return 1; - return strcmp((const char*)a, (const char*)b); + if (a == NULL && b == NULL) + return 0; + if (a == NULL) + return -1; + if (b == NULL) + return 1; + return strcmp((const char*)a, (const char*)b); } /* expects that *result is NULL */ static void ssh_choose_algo(gchar *client, gchar *server, gchar **result) { - gchar **server_strings=NULL; - gchar **client_strings=NULL; - gchar **step; - GSList *server_list = NULL; - - if (!client || !server || !result || *result) - return; - - server_strings = g_strsplit(server, ",", 0); - for (step = server_strings; *step; step++) { - server_list = g_slist_append(server_list, *step); - } - - client_strings = g_strsplit(client, ",", 0); - for (step = client_strings; *step; step++) { - GSList *agreed; - if ((agreed=g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) { - *result = wmem_strdup(wmem_file_scope(), (const gchar *)agreed->data); - break; - } - } - - g_strfreev(client_strings); - g_slist_free(server_list); - g_strfreev(server_strings); + gchar **server_strings=NULL; + gchar **client_strings=NULL; + gchar **step; + GSList *server_list = NULL; + + if (!client || !server || !result || *result) + return; + + server_strings = g_strsplit(server, ",", 0); + for (step = server_strings; *step; step++) { + server_list = g_slist_append(server_list, *step); + } + + client_strings = g_strsplit(client, ",", 0); + for (step = client_strings; *step; step++) { + GSList *agreed; + if ((agreed=g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) { + *result = wmem_strdup(wmem_file_scope(), (const gchar *)agreed->data); + break; + } + } + + g_strfreev(client_strings); + g_slist_free(server_list); + g_strfreev(server_strings); } static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree, - int is_response, struct ssh_flow_data *global_data) + int is_response, struct ssh_flow_data *global_data) { - int start_offset = offset; + int start_offset = offset; - proto_item *tf; + proto_item *tf; proto_tree *key_init_tree; - struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; - - key_init_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms"); - proto_tree_add_item(key_init_tree, hf_ssh_cookie, - tvb, offset, 16, ENC_NA); - offset += 16; - - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms, - &peer_data->kex_proposal); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_server_host_key_algorithms_length, - hf_ssh_server_host_key_algorithms, NULL); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_encryption_algorithms_client_to_server_length, - hf_ssh_encryption_algorithms_client_to_server, - &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_encryption_algorithms_server_to_client_length, - hf_ssh_encryption_algorithms_server_to_client, - &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_mac_algorithms_client_to_server_length, - hf_ssh_mac_algorithms_client_to_server, - &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_mac_algorithms_server_to_client_length, - hf_ssh_mac_algorithms_server_to_client, - &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_compression_algorithms_client_to_server_length, - hf_ssh_compression_algorithms_client_to_server, - &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_compression_algorithms_server_to_client_length, - hf_ssh_compression_algorithms_server_to_client, - &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_languages_client_to_server_length, - hf_ssh_languages_client_to_server, NULL); - offset = ssh_dissect_proposal(tvb, offset, key_init_tree, - hf_ssh_languages_server_to_client_length, - hf_ssh_languages_server_to_client, NULL); - - proto_tree_add_item(key_init_tree, hf_ssh_kex_first_packet_follows, - tvb, offset, 1, ENC_BIG_ENDIAN); - offset+=1; - - proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved, - tvb, offset, 4, ENC_NA); - offset+=4; - - if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal && - global_data->peer_data[SERVER_PEER_DATA].kex_proposal && - !global_data->kex) - { - /* Note: we're ignoring first_kex_packet_follows. */ - ssh_choose_algo( - global_data->peer_data[CLIENT_PEER_DATA].kex_proposal, - global_data->peer_data[SERVER_PEER_DATA].kex_proposal, - &global_data->kex); - ssh_set_kex_specific_dissector(global_data); - } - - if (tf != NULL) { - proto_item_set_len(tf, offset-start_offset); - } - - return offset; + struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; + + key_init_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms"); + proto_tree_add_item(key_init_tree, hf_ssh_cookie, + tvb, offset, 16, ENC_NA); + offset += 16; + + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms, + &peer_data->kex_proposal); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_server_host_key_algorithms_length, + hf_ssh_server_host_key_algorithms, NULL); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_encryption_algorithms_client_to_server_length, + hf_ssh_encryption_algorithms_client_to_server, + &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_encryption_algorithms_server_to_client_length, + hf_ssh_encryption_algorithms_server_to_client, + &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_mac_algorithms_client_to_server_length, + hf_ssh_mac_algorithms_client_to_server, + &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_mac_algorithms_server_to_client_length, + hf_ssh_mac_algorithms_server_to_client, + &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_compression_algorithms_client_to_server_length, + hf_ssh_compression_algorithms_client_to_server, + &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_compression_algorithms_server_to_client_length, + hf_ssh_compression_algorithms_server_to_client, + &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_languages_client_to_server_length, + hf_ssh_languages_client_to_server, NULL); + offset = ssh_dissect_proposal(tvb, offset, key_init_tree, + hf_ssh_languages_server_to_client_length, + hf_ssh_languages_server_to_client, NULL); + + proto_tree_add_item(key_init_tree, hf_ssh_kex_first_packet_follows, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved, + tvb, offset, 4, ENC_NA); + offset+=4; + + if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal && + global_data->peer_data[SERVER_PEER_DATA].kex_proposal && + !global_data->kex) + { + /* Note: we're ignoring first_kex_packet_follows. */ + ssh_choose_algo( + global_data->peer_data[CLIENT_PEER_DATA].kex_proposal, + global_data->peer_data[SERVER_PEER_DATA].kex_proposal, + &global_data->kex); + ssh_set_kex_specific_dissector(global_data); + } + + if (tf != NULL) { + proto_item_set_len(tf, offset-start_offset); + } + + return offset; } static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree, - int hf_index_length, int hf_index_value, gchar **store) + int hf_index_length, int hf_index_value, gchar **store) { - guint32 len = tvb_get_ntohl(tvb, offset); - proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len); - offset += 4; + guint32 len = tvb_get_ntohl(tvb, offset); + proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len); + offset += 4; - proto_tree_add_item(tree, hf_index_value, tvb, offset, len, - ENC_ASCII); - if (store) - *store = tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII); - offset += len; + proto_tree_add_item(tree, hf_index_value, tvb, offset, len, + ENC_ASCII); + if (store) + *store = tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII); + offset += len; - return offset; + return offset; } void proto_register_ssh(void) { - static hf_register_info hf[] = { - { &hf_ssh_packet_length, - { "Packet Length", "ssh.packet_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH packet length", HFILL }}, - - { &hf_ssh_packet_length_encrypted, - { "Packet Length (encrypted)", "ssh.packet_length_encrypted", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH packet length (encrypted)", HFILL }}, - - { &hf_ssh_padding_length, - { "Padding Length", "ssh.padding_length", - FT_UINT8, BASE_DEC, NULL, 0x0, - "SSH Packet Number", HFILL }}, - - { &hf_ssh_msg_code, - { "Message Code", "ssh.message_code", - FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0, - "SSH Message Code", HFILL }}, - - { &hf_ssh2_msg_code, - { "Message Code", "ssh.message_code", - FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0, - "SSH Message Code", HFILL }}, - - { &hf_ssh2_kex_dh_msg_code, - { "Message Code", "ssh.message_code", - FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0, - "SSH Message Code", HFILL }}, - - { &hf_ssh2_kex_dh_gex_msg_code, - { "Message Code", "ssh.message_code", - FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0, - "SSH Message Code", HFILL }}, - - { &hf_ssh_mpint_g, - { "DH base (G)", "ssh.dh.g", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH DH base (G)", HFILL }}, - - { &hf_ssh_mpint_p, - { "DH modulus (P)", "ssh.dh.p", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH DH modulus (P)", HFILL }}, - - { &hf_ssh_mpint_e, - { "DH client e", "ssh.dh.e", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH DH client e", HFILL }}, - - { &hf_ssh_mpint_f, - { "DH server f", "ssh.dh.f", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH DH server f", HFILL }}, - - { &hf_ssh_mpint_length, - { "Multi Precision Integer Length", "ssh.mpint_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH mpint length", HFILL }}, - - { &hf_ssh_kexdh_host_key, - { "KEX DH host key", "ssh.kexdh.host_key", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH KEX DH host key", HFILL }}, - - { &hf_ssh_kexdh_h_sig, - { "KEX DH H signature", "ssh.kexdh.h_sig", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH KEX DH H signature", HFILL }}, - - { &hf_ssh_kexdh_host_key_length, - { "KEX DH host key length", "ssh.kexdh.host_key_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH KEX DH host key length", HFILL }}, - - { &hf_ssh_kexdh_h_sig_length, - { "KEX DH H signature length", "ssh.kexdh.h_sig_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH KEX DH H signature length", HFILL }}, - - { &hf_ssh_encrypted_packet, - { "Encrypted Packet", "ssh.encrypted_packet", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH Protocol Packet", HFILL }}, - - { &hf_ssh_protocol, - { "Protocol", "ssh.protocol", - FT_STRING, BASE_NONE, NULL, 0x0, - "SSH Protocol", HFILL }}, - - { &hf_ssh_cookie, - { "Cookie", "ssh.cookie", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH Cookie", HFILL }}, - - { &hf_ssh_kex_first_packet_follows, - { "KEX First Packet Follows", "ssh.kex.first_packet_follows", - FT_UINT8, BASE_DEC, NULL, 0x0, - "SSH KEX Fist Packet Follows", HFILL }}, - - { &hf_ssh_kex_reserved, - { "Reserved", "ssh.kex.reserved", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH Protocol KEX Reserved", HFILL }}, - - { &hf_ssh_dh_gex_min, - { "DH GEX Min", "ssh.dh_gex.min", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH DH GEX Minimum", HFILL }}, - - { &hf_ssh_dh_gex_nbits, - { "DH GEX Number of Bits", "ssh.dh_gex.nbits", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH DH GEX Number of Bits", HFILL }}, - - { &hf_ssh_dh_gex_max, - { "DH GEX Max", "ssh.dh_gex.max", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH DH GEX Maximum", HFILL }}, - - { &hf_ssh_payload, - { "Payload", "ssh.payload", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH Payload", HFILL }}, - - { &hf_ssh_padding_string, - { "Padding String", "ssh.padding_string", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH Padding String", HFILL }}, - - { &hf_ssh_mac_string, - { "MAC", "ssh.mac", - FT_BYTES, BASE_NONE, NULL, 0x0, - "SSH Protocol Packet MAC", HFILL }}, - - { &hf_ssh_kex_algorithms, - { "kex_algorithms string", "ssh.kex_algorithms", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH kex_algorithms string", HFILL }}, - - { &hf_ssh_server_host_key_algorithms, - { "server_host_key_algorithms string", "ssh.server_host_key_algorithms", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH server_host_key_algorithms string", HFILL }}, - - { &hf_ssh_encryption_algorithms_client_to_server, - { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH encryption_algorithms_client_to_server string", HFILL }}, - - { &hf_ssh_encryption_algorithms_server_to_client, - { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH encryption_algorithms_server_to_client string", HFILL }}, - - { &hf_ssh_mac_algorithms_client_to_server, - { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH mac_algorithms_client_to_server string", HFILL }}, - - { &hf_ssh_mac_algorithms_server_to_client, - { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH mac_algorithms_server_to_client string", HFILL }}, - - { &hf_ssh_compression_algorithms_client_to_server, - { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH compression_algorithms_client_to_server string", HFILL }}, - - { &hf_ssh_compression_algorithms_server_to_client, - { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH compression_algorithms_server_to_client string", HFILL }}, - - { &hf_ssh_languages_client_to_server, - { "languages_client_to_server string", "ssh.languages_client_to_server", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH languages_client_to_server string", HFILL }}, - - { &hf_ssh_languages_server_to_client, - { "languages_server_to_client string", "ssh.languages_server_to_client", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "SSH languages_server_to_client string", HFILL }}, - - { &hf_ssh_kex_algorithms_length, - { "kex_algorithms length", "ssh.kex_algorithms_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH kex_algorithms length", HFILL }}, - - { &hf_ssh_server_host_key_algorithms_length, - { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH server_host_key_algorithms length", HFILL }}, - - { &hf_ssh_encryption_algorithms_client_to_server_length, - { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH encryption_algorithms_client_to_server length", HFILL }}, - - { &hf_ssh_encryption_algorithms_server_to_client_length, - { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH encryption_algorithms_server_to_client length", HFILL }}, - - { &hf_ssh_mac_algorithms_client_to_server_length, - { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH mac_algorithms_client_to_server length", HFILL }}, - - { &hf_ssh_mac_algorithms_server_to_client_length, - { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH mac_algorithms_server_to_client length", HFILL }}, - - { &hf_ssh_compression_algorithms_client_to_server_length, - { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH compression_algorithms_client_to_server length", HFILL }}, - - { &hf_ssh_compression_algorithms_server_to_client_length, - { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH compression_algorithms_server_to_client length", HFILL }}, - - { &hf_ssh_languages_client_to_server_length, - { "languages_client_to_server length", "ssh.languages_client_to_server_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH languages_client_to_server length", HFILL }}, - - { &hf_ssh_languages_server_to_client_length, - { "languages_server_to_client length", "ssh.languages_server_to_client_length", - FT_UINT32, BASE_DEC, NULL, 0x0, - "SSH languages_server_to_client length", HFILL }}, - }; - - static gint *ett[] = { - &ett_ssh, - &ett_key_exchange, - &ett_ssh1, - &ett_ssh2, - &ett_key_init - }; - - static ei_register_info ei[] = { - { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }}, - }; - - module_t *ssh_module; - expert_module_t *expert_ssh; - - proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh"); - proto_register_field_array(proto_ssh, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); - expert_ssh = expert_register_protocol(proto_ssh); - expert_register_field_array(expert_ssh, ei, array_length(ei)); - - ssh_module = prefs_register_protocol(proto_ssh, NULL); - prefs_register_bool_preference(ssh_module, "desegment_buffers", - "Reassemble SSH buffers spanning multiple TCP segments", - "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. " - "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", - &ssh_desegment); - - ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh); + static hf_register_info hf[] = { + { &hf_ssh_packet_length, + { "Packet Length", "ssh.packet_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH packet length", HFILL }}, + + { &hf_ssh_packet_length_encrypted, + { "Packet Length (encrypted)", "ssh.packet_length_encrypted", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH packet length (encrypted)", HFILL }}, + + { &hf_ssh_padding_length, + { "Padding Length", "ssh.padding_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "SSH Packet Number", HFILL }}, + + { &hf_ssh_msg_code, + { "Message Code", "ssh.message_code", + FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0, + "SSH Message Code", HFILL }}, + + { &hf_ssh2_msg_code, + { "Message Code", "ssh.message_code", + FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0, + "SSH Message Code", HFILL }}, + + { &hf_ssh2_kex_dh_msg_code, + { "Message Code", "ssh.message_code", + FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0, + "SSH Message Code", HFILL }}, + + { &hf_ssh2_kex_dh_gex_msg_code, + { "Message Code", "ssh.message_code", + FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0, + "SSH Message Code", HFILL }}, + + { &hf_ssh_mpint_g, + { "DH base (G)", "ssh.dh.g", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH DH base (G)", HFILL }}, + + { &hf_ssh_mpint_p, + { "DH modulus (P)", "ssh.dh.p", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH DH modulus (P)", HFILL }}, + + { &hf_ssh_mpint_e, + { "DH client e", "ssh.dh.e", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH DH client e", HFILL }}, + + { &hf_ssh_mpint_f, + { "DH server f", "ssh.dh.f", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH DH server f", HFILL }}, + + { &hf_ssh_mpint_length, + { "Multi Precision Integer Length", "ssh.mpint_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH mpint length", HFILL }}, + + { &hf_ssh_kexdh_host_key, + { "KEX DH host key", "ssh.kexdh.host_key", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH KEX DH host key", HFILL }}, + + { &hf_ssh_kexdh_h_sig, + { "KEX DH H signature", "ssh.kexdh.h_sig", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH KEX DH H signature", HFILL }}, + + { &hf_ssh_kexdh_host_key_length, + { "KEX DH host key length", "ssh.kexdh.host_key_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH KEX DH host key length", HFILL }}, + + { &hf_ssh_kexdh_h_sig_length, + { "KEX DH H signature length", "ssh.kexdh.h_sig_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH KEX DH H signature length", HFILL }}, + + { &hf_ssh_encrypted_packet, + { "Encrypted Packet", "ssh.encrypted_packet", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH Protocol Packet", HFILL }}, + + { &hf_ssh_protocol, + { "Protocol", "ssh.protocol", + FT_STRING, BASE_NONE, NULL, 0x0, + "SSH Protocol", HFILL }}, + + { &hf_ssh_cookie, + { "Cookie", "ssh.cookie", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH Cookie", HFILL }}, + + { &hf_ssh_kex_first_packet_follows, + { "KEX First Packet Follows", "ssh.kex.first_packet_follows", + FT_UINT8, BASE_DEC, NULL, 0x0, + "SSH KEX Fist Packet Follows", HFILL }}, + + { &hf_ssh_kex_reserved, + { "Reserved", "ssh.kex.reserved", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH Protocol KEX Reserved", HFILL }}, + + { &hf_ssh_dh_gex_min, + { "DH GEX Min", "ssh.dh_gex.min", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH DH GEX Minimum", HFILL }}, + + { &hf_ssh_dh_gex_nbits, + { "DH GEX Number of Bits", "ssh.dh_gex.nbits", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH DH GEX Number of Bits", HFILL }}, + + { &hf_ssh_dh_gex_max, + { "DH GEX Max", "ssh.dh_gex.max", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH DH GEX Maximum", HFILL }}, + + { &hf_ssh_payload, + { "Payload", "ssh.payload", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH Payload", HFILL }}, + + { &hf_ssh_padding_string, + { "Padding String", "ssh.padding_string", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH Padding String", HFILL }}, + + { &hf_ssh_mac_string, + { "MAC", "ssh.mac", + FT_BYTES, BASE_NONE, NULL, 0x0, + "SSH Protocol Packet MAC", HFILL }}, + + { &hf_ssh_kex_algorithms, + { "kex_algorithms string", "ssh.kex_algorithms", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH kex_algorithms string", HFILL }}, + + { &hf_ssh_server_host_key_algorithms, + { "server_host_key_algorithms string", "ssh.server_host_key_algorithms", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH server_host_key_algorithms string", HFILL }}, + + { &hf_ssh_encryption_algorithms_client_to_server, + { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH encryption_algorithms_client_to_server string", HFILL }}, + + { &hf_ssh_encryption_algorithms_server_to_client, + { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH encryption_algorithms_server_to_client string", HFILL }}, + + { &hf_ssh_mac_algorithms_client_to_server, + { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH mac_algorithms_client_to_server string", HFILL }}, + + { &hf_ssh_mac_algorithms_server_to_client, + { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH mac_algorithms_server_to_client string", HFILL }}, + + { &hf_ssh_compression_algorithms_client_to_server, + { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH compression_algorithms_client_to_server string", HFILL }}, + + { &hf_ssh_compression_algorithms_server_to_client, + { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH compression_algorithms_server_to_client string", HFILL }}, + + { &hf_ssh_languages_client_to_server, + { "languages_client_to_server string", "ssh.languages_client_to_server", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH languages_client_to_server string", HFILL }}, + + { &hf_ssh_languages_server_to_client, + { "languages_server_to_client string", "ssh.languages_server_to_client", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "SSH languages_server_to_client string", HFILL }}, + + { &hf_ssh_kex_algorithms_length, + { "kex_algorithms length", "ssh.kex_algorithms_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH kex_algorithms length", HFILL }}, + + { &hf_ssh_server_host_key_algorithms_length, + { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH server_host_key_algorithms length", HFILL }}, + + { &hf_ssh_encryption_algorithms_client_to_server_length, + { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH encryption_algorithms_client_to_server length", HFILL }}, + + { &hf_ssh_encryption_algorithms_server_to_client_length, + { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH encryption_algorithms_server_to_client length", HFILL }}, + + { &hf_ssh_mac_algorithms_client_to_server_length, + { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH mac_algorithms_client_to_server length", HFILL }}, + + { &hf_ssh_mac_algorithms_server_to_client_length, + { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH mac_algorithms_server_to_client length", HFILL }}, + + { &hf_ssh_compression_algorithms_client_to_server_length, + { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH compression_algorithms_client_to_server length", HFILL }}, + + { &hf_ssh_compression_algorithms_server_to_client_length, + { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH compression_algorithms_server_to_client length", HFILL }}, + + { &hf_ssh_languages_client_to_server_length, + { "languages_client_to_server length", "ssh.languages_client_to_server_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH languages_client_to_server length", HFILL }}, + + { &hf_ssh_languages_server_to_client_length, + { "languages_server_to_client length", "ssh.languages_server_to_client_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "SSH languages_server_to_client length", HFILL }}, + }; + + static gint *ett[] = { + &ett_ssh, + &ett_key_exchange, + &ett_ssh1, + &ett_ssh2, + &ett_key_init + }; + + static ei_register_info ei[] = { + { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }}, + }; + + module_t *ssh_module; + expert_module_t *expert_ssh; + + proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh"); + proto_register_field_array(proto_ssh, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_ssh = expert_register_protocol(proto_ssh); + expert_register_field_array(expert_ssh, ei, array_length(ei)); + + ssh_module = prefs_register_protocol(proto_ssh, NULL); + prefs_register_bool_preference(ssh_module, "desegment_buffers", + "Reassemble SSH buffers spanning multiple TCP segments", + "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. " + "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", + &ssh_desegment); + + ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh); } void proto_reg_handoff_ssh(void) { - dissector_add_uint("tcp.port", TCP_PORT_SSH, ssh_handle); - dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle); - dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle); + dissector_add_uint("tcp.port", TCP_PORT_SSH, ssh_handle); + dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle); + dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle); } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: - * c-basic-offset: 8 + * c-basic-offset: 4 * tab-width: 8 - * indent-tabs-mode: t + * indent-tabs-mode: nil * End: * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: */ |