static int proto_tree_add_tacplus_common_fields( tvbuff_t *tvb, proto_tree *tree, int offset, int var_off ) { int val; guint8 buff[257]; /* priv_lvl */ proto_tree_add_text( tree, tvb, offset, 1, "Privilege Level: %d", tvb_get_guint8(tvb,offset) ); offset++; /* authen_type */ val=tvb_get_guint8(tvb,offset); proto_tree_add_text( tree, tvb, offset, 1, "Authentication type: %s", val_to_str( val, tacplus_authen_type_vals, "Unknown Packet" ) ); offset++; /* service */ val=tvb_get_guint8(tvb,offset); proto_tree_add_text( tree, tvb, offset, 1, "Service: %s", val_to_str( val, tacplus_authen_service_vals, "Unknown Packet" ) ); offset++; /* user_len && user */ val=tvb_get_guint8(tvb,offset); proto_tree_add_text( tree, tvb, offset, 1, "User len: %d", val ); if( val ){ tvb_get_nstringz0(tvb, var_off, val+1, buff); proto_tree_add_text( tree, tvb, var_off, val, "User: %s", buff ); var_off+=val; } offset++; /* port_len && port */ val=tvb_get_guint8(tvb,offset); proto_tree_add_text( tree, tvb, offset, 1, "Port len: %d", val ); if( val ){ tvb_get_nstringz0(tvb, var_off, val+1, buff); proto_tree_add_text( tree, tvb, var_off, val, "Port: %s", buff ); var_off+=val; } offset++; /* rem_addr_len && rem_addr */ val=tvb_get_guint8(tvb,offset); proto_tree_add_text( tree, tvb, offset, 1, "Remaddr len: %d", val ); if( val ){ tvb_get_nstringz0(tvb, var_off, val+1, buff); proto_tree_add_text( tree, tvb, var_off, val, "Remote Address: %s", buff ); var_off+=val; } return var_off; }
static void dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree) { proto_tree *whoent_tree = NULL; proto_item *whoent_ti = NULL; int line_offset = offset; gchar out_line[9]; gchar out_name[9]; nstime_t ts; int whoent_num = 0; guint32 idle_secs; /* say that out loud... */ ts.nsecs = 0; while (tvb_reported_length_remaining(tvb, line_offset) > 0 && whoent_num < MAX_NUM_WHOENTS) { whoent_ti = proto_tree_add_item(tree, hf_who_whoent, tvb, line_offset, SIZE_OF_WHOENT, ENC_NA); whoent_tree = proto_item_add_subtree(whoent_ti, ett_whoent); tvb_get_nstringz0(tvb, line_offset, sizeof(out_line), (guint8*)out_line); proto_tree_add_string(whoent_tree, hf_who_tty, tvb, line_offset, 8, out_line); line_offset += 8; tvb_get_nstringz0(tvb, line_offset, sizeof(out_name), (guint8*)out_name); proto_tree_add_string(whoent_tree, hf_who_uid, tvb, line_offset, 8, out_name); line_offset += 8; ts.secs = tvb_get_ntohl(tvb, line_offset); proto_tree_add_time(whoent_tree, hf_who_timeon, tvb, line_offset, 4, &ts); line_offset += 4; idle_secs = tvb_get_ntohl(tvb, line_offset); proto_tree_add_uint_format(whoent_tree, hf_who_idle, tvb, line_offset, 4, idle_secs, "Idle: %s", time_secs_to_ep_str(idle_secs)); line_offset += 4; whoent_num++; } }
static void dissect_tacplus_args_list( tvbuff_t *tvb, proto_tree *tree, int data_off, int len_off, int arg_cnt ) { int i; guint8 buff[257]; for(i=0;i<arg_cnt;i++){ int len=tvb_get_guint8(tvb,len_off+i); proto_tree_add_text( tree, tvb, len_off+i, 1, "Arg[%d] length: %d", i, len ); tvb_get_nstringz0(tvb, data_off, len+1, buff); proto_tree_add_text( tree, tvb, data_off, len, "Arg[%d] value: %s", i, buff ); data_off+=len; } }
static void dissect_rsync_version_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *rsync_tree, enum rsync_who me) { int offset = 0; gchar version[5]; /* 2 digits for main version; '.'; 1 digit for sub version; NULL */ proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, RSYNCD_MAGIC_HEADER_LEN, ENC_ASCII|ENC_NA); offset += RSYNCD_MAGIC_HEADER_LEN; offset++; /* skip the space */ proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, sizeof(version)-1, ENC_ASCII|ENC_NA); tvb_get_nstringz0(tvb, offset, sizeof(version), version); col_add_fstr(pinfo->cinfo, COL_INFO, "%s Initialisation (Version %s)", (me == SERVER ? "Server" : "Client"), version); }
static void dissect_tacplus_body_authen_req_login( tvbuff_t* tvb, proto_tree *tree, int var_off ) { guint8 buff[257]; guint8 val; val=tvb_get_guint8( tvb, AUTHEN_S_DATA_LEN_OFF ); switch ( tvb_get_guint8(tvb, AUTHEN_S_AUTHEN_TYPE_OFF ) ) { /* authen_type */ case TAC_PLUS_AUTHEN_TYPE_ASCII: proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "Data: %d (not used)", val ); if( val ) proto_tree_add_text( tree, tvb, var_off, val, "Data" ); break; case TAC_PLUS_AUTHEN_TYPE_PAP: proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "Password Length %d", val ); if( val ) { tvb_get_nstringz0( tvb, var_off, val+1, buff ); proto_tree_add_text( tree, tvb, var_off, val, "Password: %s", buff ); } break; case TAC_PLUS_AUTHEN_TYPE_CHAP: proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "CHAP Data Length %d", val ); if( val ) { proto_item *pi; proto_tree *pt; guint8 chal_len=val-(1+16); /* Response field alwayes 16 octets */ pi = proto_tree_add_text(tree, tvb, var_off, val, "CHAP Data" ); pt = proto_item_add_subtree( pi, ett_tacplus_body_chap ); val= tvb_get_guint8( tvb, var_off ); proto_tree_add_text( pt, tvb, var_off, 1, "ID: %d", val ); var_off++; tvb_get_nstringz0( tvb, var_off, chal_len+1, buff ); proto_tree_add_text( pt, tvb, var_off, chal_len, "Challenge: %s", buff ); var_off+=chal_len; tvb_get_nstringz0( tvb, var_off, 16+1, buff ); proto_tree_add_text( pt, tvb, var_off, 16 , "Response: %s", buff ); } break; case TAC_PLUS_AUTHEN_TYPE_MSCHAP: proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "MSCHAP Data Length %d", val ); if( val ) { proto_item *pi; proto_tree *pt; guint8 chal_len=val-(1+49); /* Response field alwayes 49 octets */ pi = proto_tree_add_text(tree, tvb, var_off, val, "MSCHAP Data" ); pt = proto_item_add_subtree( pi, ett_tacplus_body_chap ); val= tvb_get_guint8( tvb, var_off ); proto_tree_add_text( pt, tvb, var_off, 1, "ID: %d", val ); var_off++; tvb_get_nstringz0( tvb, var_off, chal_len+1, buff ); proto_tree_add_text( pt, tvb, var_off, chal_len, "Challenge: %s", buff ); var_off+=chal_len; tvb_get_nstringz0( tvb, var_off, 49+1, buff ); proto_tree_add_text( pt, tvb, var_off, 49 , "Response: %s", buff ); } break; case TAC_PLUS_AUTHEN_TYPE_ARAP: proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "ARAP Data Length %d", val ); if( val ) { proto_item *pi; proto_tree *pt; pi = proto_tree_add_text(tree, tvb, var_off, val, "ARAP Data" ); pt = proto_item_add_subtree( pi, ett_tacplus_body_chap ); tvb_get_nstringz0( tvb, var_off, 8+1, buff ); proto_tree_add_text( pt, tvb, var_off, 8, "Nas Challenge: %s", buff ); var_off+=8; tvb_get_nstringz0( tvb, var_off, 8+1, buff ); proto_tree_add_text( pt, tvb, var_off, 8, "Remote Challenge: %s", buff ); var_off+=8; tvb_get_nstringz0( tvb, var_off, 8+1, buff ); proto_tree_add_text( pt, tvb, var_off, 8, "Remote Response: %s", buff ); var_off+=8; } break; default: /* Should not be reached */ proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "Data: %d", val ); if( val ){ proto_tree_add_text( tree, tvb, var_off, val, "Data" ); } } }
static void dissect_tacacs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *tacacs_tree; proto_item *ti; guint8 txt_buff[255+1],version,type,userlen,passlen; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TACACS"); col_clear(pinfo->cinfo, COL_INFO); version = tvb_get_guint8(tvb,0); if (version != 0) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "XTACACS"); } type = tvb_get_guint8(tvb,1); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, tacacs_type_vals, "Unknown (0x%02x)")); if (tree) { ti = proto_tree_add_protocol_format(tree, proto_tacacs, tvb, 0, -1, version==0?"TACACS":"XTACACS"); tacacs_tree = proto_item_add_subtree(ti, ett_tacacs); proto_tree_add_uint(tacacs_tree, hf_tacacs_version, tvb, 0, 1, version); proto_tree_add_uint(tacacs_tree, hf_tacacs_type, tvb, 1, 1, type); proto_tree_add_item(tacacs_tree, hf_tacacs_nonce, tvb, 2, 2, ENC_BIG_ENDIAN); if (version==0) { if (type!=TACACS_RESPONSE) { userlen=tvb_get_guint8(tvb,4); proto_tree_add_uint(tacacs_tree, hf_tacacs_userlen, tvb, 4, 1, userlen); passlen=tvb_get_guint8(tvb,5); proto_tree_add_uint(tacacs_tree, hf_tacacs_passlen, tvb, 5, 1, passlen); tvb_get_nstringz0(tvb,6,userlen+1,txt_buff); proto_tree_add_text(tacacs_tree, tvb, 6, userlen, "Username: %s",txt_buff); tvb_get_nstringz0(tvb,6+userlen,passlen+1,txt_buff); proto_tree_add_text(tacacs_tree, tvb, 6+userlen, passlen, "Password: %s",txt_buff); } else { proto_tree_add_item(tacacs_tree, hf_tacacs_response, tvb, 4, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tacacs_tree, hf_tacacs_reason, tvb, 5, 1, ENC_BIG_ENDIAN); } } else { userlen=tvb_get_guint8(tvb,4); proto_tree_add_uint(tacacs_tree, hf_tacacs_userlen, tvb, 4, 1, userlen); passlen=tvb_get_guint8(tvb,5); proto_tree_add_uint(tacacs_tree, hf_tacacs_passlen, tvb, 5, 1, passlen); proto_tree_add_item(tacacs_tree, hf_tacacs_response, tvb, 6, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tacacs_tree, hf_tacacs_reason, tvb, 7, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tacacs_tree, hf_tacacs_result1, tvb, 8, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tacacs_tree, hf_tacacs_destaddr, tvb, 12, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tacacs_tree, hf_tacacs_destport, tvb, 16, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tacacs_tree, hf_tacacs_line, tvb, 18, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tacacs_tree, hf_tacacs_result2, tvb, 20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tacacs_tree, hf_tacacs_result3, tvb, 24, 2, ENC_BIG_ENDIAN); if (type!=TACACS_RESPONSE) { tvb_get_nstringz0(tvb,26,userlen+1,txt_buff); proto_tree_add_text(tacacs_tree, tvb, 26, userlen, "Username: %s",txt_buff); tvb_get_nstringz0(tvb,26+userlen,passlen+1,txt_buff); proto_tree_add_text(tacacs_tree, tvb, 26+userlen, passlen, "Password; %s",txt_buff); } } } }
static void dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int direction) { proto_tree *cl_tree = NULL; proto_tree *text_tree = NULL; guint8 text[MAX_TEXT_SIZE+1]; int len; int offset; guint32 marker; int command_len; const char *command = ""; gboolean command_finished = FALSE; marker = tvb_get_ntohl(tvb, 0); if (tree) { proto_item *cl_item; cl_item = proto_tree_add_text(tree, tvb, 0, -1, "Connectionless"); cl_tree = proto_item_add_subtree(cl_item, ett_quakeworld_connectionless); proto_tree_add_uint(cl_tree, hf_quakeworld_connectionless_marker, tvb, 0, 4, marker); } /* all the rest of the packet is just text */ offset = 4; len = tvb_get_nstringz0(tvb, offset, sizeof(text), text); /* actually, we should look for a eol char and stop already there */ if (cl_tree) { proto_item *text_item; text_item = proto_tree_add_string(cl_tree, hf_quakeworld_connectionless_text, tvb, offset, len + 1, text); text_tree = proto_item_add_subtree(text_item, ett_quakeworld_connectionless_text); } if (direction == DIR_C2S) { /* client to server commands */ const char *c; Cmd_TokenizeString(text); c = Cmd_Argv(0); /* client to sever commands */ if (strcmp(c,"ping") == 0) { command = "Ping"; command_len = 4; } else if (strcmp(c,"status") == 0) { command = "Status"; command_len = 6; } else if (strcmp(c,"log") == 0) { command = "Log"; command_len = 3; } else if (strcmp(c,"connect") == 0) { int version; int qport; int challenge; const char *infostring; proto_tree *argument_tree = NULL; command = "Connect"; command_len = Cmd_Argv_length(0); if (text_tree) { proto_item *argument_item; proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); command_finished=TRUE; } version = atoi(Cmd_Argv(1)); qport = atoi(Cmd_Argv(2)); challenge = atoi(Cmd_Argv(3)); infostring = Cmd_Argv(4); if (argument_tree) { proto_item *info_item; proto_tree *info_tree; proto_tree_add_uint(argument_tree, hf_quakeworld_connectionless_connect_version, tvb, offset + Cmd_Argv_start(1), Cmd_Argv_length(1), version); proto_tree_add_uint(argument_tree, hf_quakeworld_connectionless_connect_qport, tvb, offset + Cmd_Argv_start(2), Cmd_Argv_length(2), qport); proto_tree_add_int(argument_tree, hf_quakeworld_connectionless_connect_challenge, tvb, offset + Cmd_Argv_start(3), Cmd_Argv_length(3), challenge); info_item = proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_connect_infostring, tvb, offset + Cmd_Argv_start(4), Cmd_Argv_length(4), infostring); info_tree = proto_item_add_subtree( info_item, ett_quakeworld_connectionless_connect_infostring); dissect_id_infostring(tvb, info_tree, offset + Cmd_Argv_start(4), ep_strdup(infostring), ett_quakeworld_connectionless_connect_infostring_key_value, hf_quakeworld_connectionless_connect_infostring_key_value, hf_quakeworld_connectionless_connect_infostring_key, hf_quakeworld_connectionless_connect_infostring_value); } } else if (strcmp(c,"getchallenge") == 0) { command = "Get Challenge"; command_len = Cmd_Argv_length(0); } else if (strcmp(c,"rcon") == 0) { const char* password; int i; char remaining[MAX_TEXT_SIZE+1]; proto_tree *argument_tree = NULL; command = "Remote Command"; command_len = Cmd_Argv_length(0); if (text_tree) { proto_item *argument_item; proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); command_finished=TRUE; } password = Cmd_Argv(1); if (argument_tree) { proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_rcon_password, tvb, offset + Cmd_Argv_start(1), Cmd_Argv_length(1), password); } remaining[0] = '\0'; for (i=2; i<Cmd_Argc() ; i++) { g_strlcat (remaining, Cmd_Argv(i), MAX_TEXT_SIZE+1); g_strlcat (remaining, " ", MAX_TEXT_SIZE+1); } if (text_tree) { proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_rcon_command, tvb, offset + Cmd_Argv_start(2), Cmd_Argv_start(Cmd_Argc()-1) + Cmd_Argv_length(Cmd_Argc()-1) - Cmd_Argv_start(2), remaining); } } else if (c[0]==A2A_PING && ( c[1]=='\0' || c[1]=='\n')) { command = "Ping"; command_len = 1; } else if (c[0]==A2A_ACK && ( c[1]=='\0' || c[1]=='\n')) { command = "Ack"; command_len = 1; } else { command = "Unknown"; command_len = len; } } else { /* server to client commands */ if (text[0] == S2C_CONNECTION) { command = "Connected"; command_len = 1; } else if (text[0] == A2C_CLIENT_COMMAND) { command = "Client Command"; command_len = 1; /* stringz (command), stringz (localid) */ } else if (text[0] == A2C_PRINT) { command = "Print"; command_len = 1; /* string */ } else if (text[0] == A2A_PING) { command = "Ping"; command_len = 1; } else if (text[0] == S2C_CHALLENGE) { command = "Challenge"; command_len = 1; /* string, atoi */ } else { command = "Unknown"; command_len = len; } } if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command); } if (text_tree && !command_finished) { proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); } offset += len + 1; }
static void dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request; proto_tree *ftp_tree = NULL; proto_tree *reqresp_tree = NULL; proto_item *ti, *hidden_item; gint offset = 0; const guchar *line; guint32 code; gchar code_str[4]; gboolean is_port_request = FALSE; gboolean is_pasv_response = FALSE; gboolean is_epasv_response = FALSE; gint next_offset; int linelen; int tokenlen; const guchar *next_token; guint32 pasv_ip; guint32 ftp_ip; guint16 ftp_port; address ftp_ip_address; gboolean ftp_nat; conversation_t *conversation; ftp_ip_address = pinfo->src; if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTP"); /* * Find the end of the first line. * * Note that "tvb_find_line_end()" will return a value that is * not longer than what's in the buffer, so the "tvb_get_ptr()" * call won't throw an exception. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); /* * Put the first line from the buffer into the summary * (but leave out the line terminator). */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); if (tree) { ti = proto_tree_add_item(tree, proto_ftp, tvb, offset, -1, ENC_NA); ftp_tree = proto_item_add_subtree(ti, ett_ftp); if (is_request) { hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_request, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_response, tvb, 0, 0, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); } else { hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_request, tvb, 0, 0, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_response, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } /* * Put the line into the protocol tree. */ ti = proto_tree_add_text(ftp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); reqresp_tree = proto_item_add_subtree(ti, ett_ftp_reqresp); } if (is_request) { /* * Extract the first token, and, if there is a first * token, add it as the request. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { if (tree) { proto_tree_add_item(reqresp_tree, hf_ftp_request_command, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); } if (strncmp(line, "PORT", tokenlen) == 0) is_port_request = TRUE; } } else { /* * This is a response; the response code is 3 digits, * followed by a space or hyphen, possibly followed by * text. * * If the line doesn't start with 3 digits, it's part of * a continuation. * * XXX - keep track of state in the first pass, and * treat non-continuation lines not beginning with digits * as errors? */ if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1]) && isdigit(line[2])) { /* * One-line reply, or first or last line * of a multi-line reply. */ tvb_get_nstringz0(tvb, offset, sizeof(code_str), code_str); code = strtoul(code_str, NULL, 10); if (tree) { proto_tree_add_uint(reqresp_tree, hf_ftp_response_code, tvb, offset, 3, code); } /* * See if it's a passive-mode response. * * XXX - does anybody do FOOBAR, as per RFC * 1639, or has that been supplanted by RFC 2428? */ if (code == 227) is_pasv_response = TRUE; /* * Responses to EPSV command, as per RFC 2428 * XXX - handle IPv6? */ if (code == 229) is_epasv_response = TRUE; /* * Skip the 3 digits and, if present, the * space or hyphen. */ if (linelen >= 4) next_token = line + 4; else next_token = line + linelen; } else { /* * Line doesn't start with 3 digits; assume it's * a line in the middle of a multi-line reply. */ next_token = line; } } offset += (gint) (next_token - line); linelen -= (int) (next_token - line); line = next_token; if (tree) { /* * Add the rest of the first line as request or * reply data. */ if (linelen != 0) { if (is_request) { proto_tree_add_item(reqresp_tree, hf_ftp_request_arg, tvb, offset, linelen, ENC_ASCII|ENC_NA); } else { proto_tree_add_item(reqresp_tree, hf_ftp_response_arg, tvb, offset, linelen, ENC_ASCII|ENC_NA); } } offset = next_offset; } /* * If this is a PORT request or a PASV response, handle it. */ if (is_port_request) { if (parse_port_pasv(line, linelen, &ftp_ip, &ftp_port)) { if (tree) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_active_ip, tvb, 0, 0, ftp_ip); proto_tree_add_uint(reqresp_tree, hf_ftp_active_port, tvb, 0, 0, ftp_port); } SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&ftp_ip); ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address); if (ftp_nat) { if (tree) { proto_tree_add_boolean( reqresp_tree, hf_ftp_active_nat, tvb, 0, 0, ftp_nat); } } } } if (is_pasv_response) { if (linelen != 0) { /* * This frame contains a PASV response; set up a * conversation for the data. */ if (parse_port_pasv(line, linelen, &pasv_ip, &ftp_port)) { if (tree) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_pasv_ip, tvb, 0, 0, pasv_ip); proto_tree_add_uint(reqresp_tree, hf_ftp_pasv_port, tvb, 0, 0, ftp_port); } SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&pasv_ip); ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address); if (ftp_nat) { if (tree) { proto_tree_add_boolean(reqresp_tree, hf_ftp_pasv_nat, tvb, 0, 0, ftp_nat); } } /* * We use "ftp_ip_address", so that if * we're NAT'd we look for the un-NAT'd * connection. * * XXX - should this call to * "find_conversation()" just use * "ftp_ip_address" and "server_port", and * wildcard everything else? */ conversation = find_conversation(pinfo->fd->num, &ftp_ip_address, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT_B); if (conversation == NULL) { /* * XXX - should this call to "conversation_new()" * just use "ftp_ip_address" and "server_port", * and wildcard everything else? * * XXX - what if we did find a conversation? As * we create it only on the first pass through the * packets, if we find one, it's presumably an * unrelated conversation. Should we remove the * old one from the hash table and put this one in * its place? Can the conversation code handle * conversations not in the hash table? Or should * we make conversations support start and end * frames, as circuits do, and treat this as an * indication that one conversation was closed and * a new one was opened? */ conversation = conversation_new( pinfo->fd->num, &ftp_ip_address, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT2); conversation_set_dissector(conversation, ftpdata_handle); } } } } if (is_epasv_response) { if (linelen != 0) { /* * This frame contains an EPSV response; set up a * conversation for the data. */ if (parse_extended_pasv_response(line, linelen, &ftp_port)) { /* Add port number to tree */ if (tree) { proto_tree_add_uint(reqresp_tree, hf_ftp_pasv_port, tvb, 0, 0, ftp_port); } /* Find/create conversation for data */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT_B); if (conversation == NULL) { conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT2); conversation_set_dissector(conversation, ftpdata_handle); } } } } if (tree) { /* * Show the rest of the request or response as text, * a line at a time. * XXX - only if there's a continuation indicator? */ while (tvb_offset_exists(tvb, offset)) { /* * Find the end of the line. */ tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); /* * Put this line. */ proto_tree_add_text(ftp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; } } }
static void dissect_fw1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *volatile fh_tree = NULL; char direction; char chain; char *interface_name; guint32 iface_len = 10; wmem_strbuf_t *header; int i; gboolean found; static const char fw1_header[] = "FW1 Monitor"; ethertype_data_t ethertype_data; header = wmem_strbuf_new_label(wmem_epan_scope()); wmem_strbuf_append(header, fw1_header); /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FW1"); col_clear(pinfo->cinfo, COL_INFO); /* g_snprintf(header, sizeof(header), fw1_header); */ /* fetch info to local variable */ direction = tvb_get_guint8(tvb, 0); if (!fw1_iflist_with_chain) chain = ' '; else chain = tvb_get_guint8(tvb, 1); if (fw1_with_uuid) iface_len = 6; interface_name=(char *)wmem_alloc(wmem_packet_scope(), iface_len+1); tvb_get_nstringz0(tvb, 2, iface_len+1, interface_name); /* Known interface name - if not, remember it */ found=FALSE; for (i=0; i<interface_anzahl; i++) { if ( strcmp(p_interfaces[i], interface_name) == 0 ) { found=TRUE; break; } } if (!found && interface_anzahl < MAX_INTERFACES) { p_interfaces[interface_anzahl] = wmem_strdup(wmem_file_scope(), interface_name); interface_anzahl++; } /* display all interfaces always in the same order */ for (i=0; i<interface_anzahl; i++) { if ( strcmp(p_interfaces[i], interface_name) == 0 ) { wmem_strbuf_append_printf(header, " %c%c %s %c%c", direction == 'i' ? 'i' : (direction == 'O' ? 'O' : ' '), (direction == 'i' || direction == 'O') ? chain : ' ', p_interfaces[i], direction == 'I' ? 'I' : (direction == 'o' ? 'o' : ' '), (direction == 'I' || direction == 'o') ? chain : ' ' ); } else { wmem_strbuf_append_printf(header, " %s ", p_interfaces[i]); } } col_add_str(pinfo->cinfo, COL_IF_DIR, wmem_strbuf_get_str(header) + sizeof(fw1_header) + 1); if (tree) { if (!fw1_summary_in_tree) /* Do not show the summary in Protocol Tree */ ti = proto_tree_add_protocol_format(tree, proto_fw1, tvb, 0, ETH_HEADER_SIZE, "%s", fw1_header); else ti = proto_tree_add_protocol_format(tree, proto_fw1, tvb, 0, ETH_HEADER_SIZE, "%s", wmem_strbuf_get_str(header)); /* create display subtree for the protocol */ fh_tree = proto_item_add_subtree(ti, ett_fw1); proto_tree_add_item(fh_tree, hf_fw1_direction, tvb, 0, 1, ENC_ASCII|ENC_NA); if (fw1_iflist_with_chain) proto_tree_add_item(fh_tree, hf_fw1_chain, tvb, 1, 1, ENC_ASCII|ENC_NA); proto_tree_add_item(fh_tree, hf_fw1_interface, tvb, 2, iface_len, ENC_ASCII|ENC_NA); if (fw1_with_uuid) proto_tree_add_item(fh_tree, hf_fw1_uuid, tvb, 8, 4, ENC_BIG_ENDIAN); } ethertype_data.etype = tvb_get_ntohs(tvb, 12); ethertype_data.offset_after_ethertype = ETH_HEADER_SIZE; ethertype_data.fh_tree = fh_tree; ethertype_data.etype_id = hf_fw1_type; ethertype_data.trailer_id = hf_fw1_trailer; ethertype_data.fcs_len = 0; call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, ðertype_data); }
/* Packet dissection routine called by tcp (& udp) when port 873 detected */ static void dissect_rsync_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean desegment _U_) { conversation_t *conversation; struct rsync_conversation_data *conversation_data; struct rsync_frame_data *rsync_frame_data_p; proto_item *ti; proto_tree *rsync_tree; int offset = 0; gchar version[5]; gchar auth_string[10]; guint buff_length; gchar magic_string[14]; gchar *version_out; col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSYNC"); col_clear(pinfo->cinfo, COL_INFO); conversation = find_or_create_conversation(pinfo); conversation_data = conversation_get_proto_data(conversation, proto_rsync); if (conversation_data == NULL) { conversation_data = se_alloc(sizeof(struct rsync_conversation_data)); conversation_data->state = RSYNC_INIT; conversation_add_proto_data(conversation, proto_rsync, conversation_data); } conversation_set_dissector(conversation, rsync_handle); ti = proto_tree_add_item(tree, proto_rsync, tvb, 0, -1, ENC_NA); rsync_tree = proto_item_add_subtree(ti, ett_rsync); rsync_frame_data_p = p_get_proto_data(pinfo->fd, proto_rsync); if (!rsync_frame_data_p) { /* then we haven't seen this frame before */ rsync_frame_data_p = se_alloc(sizeof(struct rsync_frame_data)); rsync_frame_data_p->state = conversation_data->state; p_add_proto_data(pinfo->fd, proto_rsync, rsync_frame_data_p); } switch (rsync_frame_data_p->state) { case RSYNC_INIT: proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, 8, ENC_ASCII|ENC_NA); offset += 8; proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, 4, ENC_ASCII|ENC_NA); tvb_get_nstringz0(tvb, offset, sizeof(version), version); offset += 4; if (check_col(pinfo->cinfo, COL_INFO)) { /* XXX - is this really a string? */ version_out = format_text(version, 4); col_append_fstr(pinfo->cinfo, COL_INFO, "Client Initialisation (Version %s)", version_out); } conversation_data->state = RSYNC_SERV_INIT; break; case RSYNC_SERV_INIT: proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, 8, ENC_ASCII|ENC_NA); offset += 8; proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, 4, ENC_ASCII|ENC_NA); tvb_get_nstringz0(tvb, offset, sizeof(version), version); offset += 4; if (check_col(pinfo->cinfo, COL_INFO)) { /* XXX - is this really a string? */ version_out = format_text(version, 4); col_append_fstr(pinfo->cinfo, COL_INFO, "Server Initialisation (Version %s)", version_out); } conversation_data->state = RSYNC_CLIENT_QUERY; break; case RSYNC_CLIENT_QUERY: proto_tree_add_item(rsync_tree, hf_rsync_query_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Client Query"); conversation_data->state = RSYNC_SERV_MOTD; break; case RSYNC_SERV_MOTD: proto_tree_add_item(rsync_tree, hf_rsync_motd_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Server MOTD"); conversation_data->state = RSYNC_SERV_RESPONSE; break; case RSYNC_SERV_RESPONSE: /* there are two cases - file list, or authentication */ tvb_get_nstringz0(tvb, offset, sizeof(auth_string), auth_string); if (0 == strncmp("@RSYNCD:", auth_string, 8)) { /* matches, so we assume its an authentication message */ /* needs to handle the AUTHREQD case, but doesn't - FIXME */ proto_tree_add_item(rsync_tree, hf_rsync_rsyncdok_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Authentication"); conversation_data->state = RSYNC_COMMAND; } else { /* it didn't match, so it is probably a module list */ proto_tree_add_item(rsync_tree, hf_rsync_response_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Module list"); /* we need to check the end of the buffer for magic string */ buff_length = tvb_length_remaining(tvb, offset); tvb_get_nstringz0(tvb, buff_length-14, sizeof(magic_string), magic_string); if (0 == strncmp("@RSYNCD: EXIT", magic_string, 14)) { /* that's all, folks */ conversation_data->state = RSYNC_COMMAND; } else { /* there must be more data */ conversation_data->state = RSYNC_SERV_RESPONSE; } } break; case RSYNC_COMMAND: if (pinfo->destport == glb_rsync_tcp_port) { /* then we are still sending commands */ proto_tree_add_item(rsync_tree, hf_rsync_command_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Command"); conversation_data->state = RSYNC_COMMAND; break; } /* else we fall through to the data phase */ case RSYNC_DATA: /* then we are still sending commands */ proto_tree_add_item(rsync_tree, hf_rsync_data, tvb, offset, -1, ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Data"); conversation_data->state = RSYNC_DATA; break; } }
static void dissect_mailslot_browse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { int offset = 0; guint8 cmd; proto_tree *tree = NULL; proto_item *item = NULL; guint32 periodicity; gchar host_name[17]; gchar *utf8_host_name; gint namelen; guint8 server_count, reset_cmd; guint8 os_major_ver, os_minor_ver; const gchar *windows_version = NULL; int i; guint32 uptime; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BROWSER"); col_clear(pinfo->cinfo, COL_INFO); cmd = tvb_get_guint8(tvb, offset); /* Put in something, and replace it later */ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, commands, "Unknown command:0x%02x")); item = proto_tree_add_item(parent_tree, proto_smb_browse, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_browse); /* command */ proto_tree_add_uint(tree, hf_command, tvb, offset, 1, cmd); offset += 1; switch (cmd) { case BROWSE_DOMAIN_ANNOUNCEMENT: case BROWSE_LOCAL_MASTER_ANNOUNCEMENT: case BROWSE_HOST_ANNOUNCE: { /* update count */ proto_tree_add_item(tree, hf_update_count, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* periodicity (in milliseconds) */ periodicity = tvb_get_letohl(tvb, offset); proto_tree_add_uint_format(tree, hf_periodicity, tvb, offset, 4, periodicity, "Update Periodicity: %s", time_msecs_to_str(periodicity)); offset += 4; /* server name */ tvb_get_nstringz0(tvb, offset, sizeof(host_name), host_name); utf8_host_name = g_convert(host_name, strlen(host_name), "UTF-8", "CP437", NULL, NULL, NULL); if (utf8_host_name == NULL) utf8_host_name = host_name; col_append_fstr(pinfo->cinfo, COL_INFO, " %s", utf8_host_name); proto_tree_add_string_format(tree, hf_server_name, tvb, offset, 16, utf8_host_name, (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)? "Domain/Workgroup: %s": "Host Name: %s", utf8_host_name); if (utf8_host_name != host_name) g_free(utf8_host_name); offset += 16; /* Windows version (See "OSVERSIONINFO Structure" on MSDN) */ os_major_ver = tvb_get_guint8(tvb, offset); os_minor_ver = tvb_get_guint8(tvb, offset+1); SET_WINDOWS_VERSION_STRING(os_major_ver, os_minor_ver, windows_version); if(windows_version) proto_tree_add_text(tree, tvb, offset, 2, "Windows version: %s", windows_version); /* OS major version */ proto_tree_add_item(tree, hf_os_major, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* OS minor version */ proto_tree_add_item(tree, hf_os_minor, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* server type flags */ offset = dissect_smb_server_type_flags( tvb, offset, pinfo, tree, NULL, TRUE); if (cmd == BROWSE_DOMAIN_ANNOUNCEMENT && tvb_get_letohs (tvb, offset + 2) != 0xAA55) { /* * Network Monitor claims this is a "Comment * Pointer". I don't believe it. * * It's not a browser protocol major/minor * version number, and signature constant, * however. */ proto_tree_add_text(tree, tvb, offset, 4, "Mysterious Field: 0x%08x", tvb_get_letohl(tvb, offset)); offset += 4; } else { /* browser protocol major version */ proto_tree_add_item(tree, hf_proto_major, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* browser protocol minor version */ proto_tree_add_item(tree, hf_proto_minor, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* signature constant */ proto_tree_add_item(tree, hf_sig_const, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } /* master browser server name or server comment */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)? hf_mb_server_name : hf_server_comment, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; } case BROWSE_REQUEST_ANNOUNCE: { guint8 *computer_name; /* unused/unknown flags */ proto_tree_add_item(tree, hf_unused_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* name of computer to which to send reply */ computer_name = tvb_get_ephemeral_stringz(tvb, offset, &namelen); proto_tree_add_string(tree, hf_response_computer_name, tvb, offset, namelen, computer_name); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", computer_name); break; } case BROWSE_ELECTION_REQUEST: /* election version */ proto_tree_add_item(tree, hf_election_version, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* criterion */ dissect_election_criterion(tvb, tree, offset); offset += 4; /* server uptime */ uptime = tvb_get_letohl(tvb, offset); proto_tree_add_uint_format(tree, hf_server_uptime, tvb, offset, 4, uptime, "Uptime: %s", time_msecs_to_str(uptime)); offset += 4; /* next 4 bytes must be zero */ offset += 4; /* server name */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_server_name, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; case BROWSE_BACKUP_LIST_REQUEST: /* backup list requested count */ proto_tree_add_item(tree, hf_backup_count, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* backup requested token */ proto_tree_add_item(tree, hf_backup_token, tvb, offset, 4, ENC_LITTLE_ENDIAN); break; case BROWSE_BACKUP_LIST_RESPONSE: /* backup list requested count */ server_count = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_backup_count, tvb, offset, 1, server_count); offset += 1; /* backup requested token */ proto_tree_add_item(tree, hf_backup_token, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* backup server names */ for (i = 0; i < server_count; i++) { namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_backup_server, tvb, offset, namelen, ENC_ASCII|ENC_NA); offset += namelen; } break; case BROWSE_MASTER_ANNOUNCEMENT: /* master browser server name */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_mb_server_name, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; case BROWSE_RESETBROWSERSTATE_ANNOUNCEMENT: { proto_tree *sub_tree; proto_item *reset_item; /* the subcommand follows ... one of three values */ reset_cmd = tvb_get_guint8(tvb, offset); reset_item = proto_tree_add_uint(tree, hf_mb_reset_command, tvb, offset, 1, reset_cmd); sub_tree = proto_item_add_subtree(reset_item, ett_browse_reset_cmd_flags); proto_tree_add_boolean(sub_tree, hf_mb_reset_demote, tvb, offset, 1, reset_cmd); proto_tree_add_boolean(sub_tree, hf_mb_reset_flush, tvb, offset, 1, reset_cmd); proto_tree_add_boolean(sub_tree, hf_mb_reset_stop, tvb, offset, 1, reset_cmd); break; } case BROWSE_BECOME_BACKUP: /* name of browser to promote */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_browser_to_promote, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; } }
static int dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *subtree; proto_item *ti; gint offset = 0, next_offset; gint len; const char *data_name; guint8 word[6]; int length = tvb_length(tvb); /* Check if this is actually xml * If there is less than 38 characters this is not XML * <?xml version="1.0" encoding="UTF-8"?> */ if(length > 38){ tvb_get_nstringz0(tvb, 0, sizeof(word),word); if (g_ascii_strncasecmp(word, "<?xml", 5) == 0){ call_dissector(xml_handle, tvb, pinfo, tree); return tvb_length(tvb); } } data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ data_name = (char *)data; if (! (data_name && data_name[0])) { /* * No information from dissector data */ data_name = (char *)(pinfo->private_data); if (! (data_name && data_name[0])) { /* * No information from "private_data" */ data_name = NULL; } } } if (data_name) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); if (tree) { ti = proto_tree_add_item(tree, proto_text_lines, tvb, 0, -1, ENC_NA); if (data_name) proto_item_append_text(ti, ": %s", data_name); subtree = proto_item_add_subtree(ti, ett_text_lines); /* Read the media line by line */ while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * XXX - we need to be passed the parameters * of the content type via "pinfo->private_data", * so that we know the character set. We'd * have to handle that character set, which * might be a multibyte character set such * as "iso-10646-ucs-2", or might require other * special processing. */ len = tvb_find_line_end(tvb, offset, tvb_ensure_length_remaining(tvb, offset), &next_offset, FALSE); if (len == -1) break; /* We use next_offset - offset instead of len in the * call to tvb_format_text() so it will include the * line terminator(s) (\r and/or \n) in the display. */ proto_tree_add_text(subtree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; } } return tvb_length(tvb); }
static void dissect_who(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; proto_tree *who_tree = NULL; proto_item *who_ti = NULL; gchar server_name[33]; double loadav_5 = 0.0, loadav_10 = 0.0, loadav_15 = 0.0; nstime_t ts; /* Summary information */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WHO"); col_clear(pinfo->cinfo, COL_INFO); ts.nsecs = 0; if (tree) { who_ti = proto_tree_add_item(tree, proto_who, tvb, offset, -1, ENC_NA); who_tree = proto_item_add_subtree(who_ti, ett_who); } if (tree) proto_tree_add_item(who_tree, hf_who_vers, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (tree) proto_tree_add_item(who_tree, hf_who_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* 2 filler bytes */ offset += 2; if (tree) { ts.secs = tvb_get_ntohl(tvb, offset); proto_tree_add_time(who_tree, hf_who_sendtime, tvb, offset, 4, &ts); } offset += 4; if (tree) { ts.secs = tvb_get_ntohl(tvb, offset); proto_tree_add_time(who_tree, hf_who_recvtime, tvb, offset, 4, &ts); } offset += 4; tvb_get_nstringz0(tvb, offset, sizeof(server_name), (guint8*)server_name); if (tree) proto_tree_add_string(who_tree, hf_who_hostname, tvb, offset, 32, server_name); offset += 32; loadav_5 = (double) tvb_get_ntohl(tvb, offset) / 100.0; if (tree) proto_tree_add_double(who_tree, hf_who_loadav_5, tvb, offset, 4, loadav_5); offset += 4; loadav_10 = (double) tvb_get_ntohl(tvb, offset) / 100.0; if (tree) proto_tree_add_double(who_tree, hf_who_loadav_10, tvb, offset, 4, loadav_10); offset += 4; loadav_15 = (double) tvb_get_ntohl(tvb, offset) / 100.0; if (tree) proto_tree_add_double(who_tree, hf_who_loadav_15, tvb, offset, 4, loadav_15); offset += 4; /* Summary information */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %.02f %.02f %.02f", server_name, loadav_5, loadav_10, loadav_15); if (tree) { ts.secs = tvb_get_ntohl(tvb, offset); proto_tree_add_time(who_tree, hf_who_boottime, tvb, offset, 4, &ts); offset += 4; dissect_whoent(tvb, offset, who_tree); } }