/builds/wireshark/wireshark/epan/dissectors/packet-tcp.c (2024)

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-tcp.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-17/lib/clang/17 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-error=stringop-overflow= -Wno-error=deprecated-declarations -Wno-format-truncation -Wno-pointer-sign -std=gnu11 -fdebug-compilation-dir=/builds/wireshark/wireshark/build -ferror-limit 19 -fvisibility=hidden -fwrapv -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-04-20-100240-3130-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-tcp.c

1/* packet-tcp.c2 * Routines for TCP packet disassembly3 *4 * Wireshark - Network traffic analyzer5 * By Gerald Combs <[emailprotected]>6 * Copyright 1998 Gerald Combs7 *8 * SPDX-License-Identifier: GPL-2.0-or-later9 */10 11#include "config.h"12 13#include <epan/packet.h>14#include <epan/capture_dissectors.h>15#include <epan/exceptions.h>16#include <epan/addr_resolv.h>17#include <epan/ipproto.h>18#include <epan/expert.h>19#include <epan/ip_opts.h>20#include <epan/follow.h>21#include <epan/prefs.h>22#include <epan/show_exception.h>23#include <epan/conversation_table.h>24#include <epan/conversation_filter.h>25#include <epan/sequence_analysis.h>26#include <epan/reassemble.h>27#include <epan/decode_as.h>28#include <epan/exported_pdu.h>29#include <epan/in_cksum.h>30#include <epan/proto_data.h>31 32#include <wsutil/utf8_entities.h>33#include <wsutil/str_util.h>34#include <wsutil/wsgcrypt.h>35#include <wsutil/pint.h>36#include <wsutil/ws_assert.h>37 38#include "packet-tcp.h"39#include "packet-ip.h"40#include "packet-icmp.h"41 42void proto_register_tcp(void);43void proto_reg_handoff_tcp(void);44static void conversation_completeness_fill(gchar*, guint32);45 46static int tcp_tap;47static int tcp_follow_tap;48static int mptcp_tap;49static int exported_pdu_tap;50 51/* Place TCP summary in proto tree */52static bool_Bool tcp_summary_in_tree = true1;53 54static inline guint64 KEEP_32MSB_OF_GUINT64(guint64 nb) {55 return (nb >> 32) << 32;56}57 58#define MPTCP_DSS_FLAG_DATA_ACK_PRESENT0x01 0x0159#define MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02 0x0260#define MPTCP_DSS_FLAG_MAPPING_PRESENT0x04 0x0461#define MPTCP_DSS_FLAG_DSN_8BYTES0x08 0x0862#define MPTCP_DSS_FLAG_DATA_FIN_PRESENT0x10 0x1063 64/*65 * Flag to control whether to check the TCP checksum.66 *67 * In at least some Solaris network traces, there are packets with bad68 * TCP checksums, but the traffic appears to indicate that the packets69 * *were* received; the packets were probably sent by the host on which70 * the capture was being done, on a network interface to which71 * checksumming was offloaded, so that DLPI supplied an un-checksummed72 * packet to the capture program but a checksummed packet got put onto73 * the wire.74 */75static bool_Bool tcp_check_checksum;76 77/*78 * Window scaling values to be used when not known (set as a preference) */79 enum scaling_window_value {80 WindowScaling_NotKnown=-1,81 WindowScaling_0=0,82 WindowScaling_1,83 WindowScaling_2,84 WindowScaling_3,85 WindowScaling_4,86 WindowScaling_5,87 WindowScaling_6,88 WindowScaling_7,89 WindowScaling_8,90 WindowScaling_9,91 WindowScaling_10,92 WindowScaling_11,93 WindowScaling_12,94 WindowScaling_13,95 WindowScaling_1496};97 98/*99 * Analysis overriding values to be used when not satisfied by the automatic100 * result. (Accessed through preferences but not stored as a preference)101 */102 enum override_analysis_value {103 OverrideAnalysis_0=0,104 OverrideAnalysis_1,105 OverrideAnalysis_2,106 OverrideAnalysis_3,107 OverrideAnalysis_4108};109 110/*111 * Using enum instead of boolean make API easier112 */113enum mptcp_dsn_conversion {114 DSN_CONV_64_TO_32,115 DSN_CONV_32_TO_64,116 DSN_CONV_NONE117} ;118 119#define MPTCP_TCPRST_FLAG_T_PRESENT0x1 0x1120#define MPTCP_TCPRST_FLAG_W_PRESENT0x2 0x2121#define MPTCP_TCPRST_FLAG_V_PRESENT0x4 0x4122#define MPTCP_TCPRST_FLAG_U_PRESENT0x8 0x8123 124static const value_string mp_tcprst_reasons[] = {125 { 0x0, "Unspecified error" },126 { 0x1, "MPTCP-specific error" },127 { 0x2, "Lack of resources" },128 { 0x3, "Administratively prohibited" },129 { 0x4, "Too much outstanding data" },130 { 0x5, "Unacceptable performance" },131 { 0x6, "Middlebox interference" },132 { 0, NULL((void*)0) },133};134 135static gint tcp_default_window_scaling = (gint)WindowScaling_NotKnown;136 137static gint tcp_default_override_analysis = (gint)OverrideAnalysis_0;138 139static int proto_tcp;140static int proto_ip;141static int proto_icmp;142 143static int proto_tcp_option_nop;144static int proto_tcp_option_eol;145static int proto_tcp_option_timestamp;146static int proto_tcp_option_mss;147static int proto_tcp_option_wscale;148static int proto_tcp_option_sack_perm;149static int proto_tcp_option_sack;150static int proto_tcp_option_echo;151static int proto_tcp_option_echoreply;152static int proto_tcp_option_cc;153static int proto_tcp_option_cc_new;154static int proto_tcp_option_cc_echo;155static int proto_tcp_option_md5;156static int proto_tcp_option_ao;157static int proto_tcp_option_scps;158static int proto_tcp_option_snack;159static int proto_tcp_option_scpsrec;160static int proto_tcp_option_scpscor;161static int proto_tcp_option_qs;162static int proto_tcp_option_user_to;163static int proto_tcp_option_tfo;164static int proto_tcp_option_acc_ecn;165static int proto_tcp_option_rvbd_probe;166static int proto_tcp_option_rvbd_trpy;167static int proto_tcp_option_exp;168static int proto_tcp_option_unknown;169static int proto_mptcp;170 171static int hf_tcp_srcport;172static int hf_tcp_dstport;173static int hf_tcp_port;174static int hf_tcp_stream;175static int hf_tcp_stream_pnum;176static int hf_tcp_completeness;177static int hf_tcp_completeness_syn;178static int hf_tcp_completeness_syn_ack;179static int hf_tcp_completeness_ack;180static int hf_tcp_completeness_data;181static int hf_tcp_completeness_fin;182static int hf_tcp_completeness_rst;183static int hf_tcp_completeness_str;184static int hf_tcp_seq;185static int hf_tcp_seq_abs;186static int hf_tcp_nxtseq;187static int hf_tcp_ack;188static int hf_tcp_ack_abs;189static int hf_tcp_hdr_len;190static int hf_tcp_flags;191static int hf_tcp_flags_res;192static int hf_tcp_flags_ae;193static int hf_tcp_flags_cwr;194static int hf_tcp_flags_ece;195static int hf_tcp_flags_ace;196static int hf_tcp_flags_urg;197static int hf_tcp_flags_ack;198static int hf_tcp_flags_push;199static int hf_tcp_flags_reset;200static int hf_tcp_flags_syn;201static int hf_tcp_flags_fin;202static int hf_tcp_flags_str;203static int hf_tcp_window_size_value;204static int hf_tcp_window_size;205static int hf_tcp_window_size_scalefactor;206static int hf_tcp_checksum;207static int hf_tcp_checksum_status;208static int hf_tcp_checksum_calculated;209static int hf_tcp_len;210static int hf_tcp_urgent_pointer;211static int hf_tcp_analysis;212static int hf_tcp_analysis_flags;213static int hf_tcp_analysis_bytes_in_flight;214static int hf_tcp_analysis_push_bytes_sent;215static int hf_tcp_analysis_acks_frame;216static int hf_tcp_analysis_ack_rtt;217static int hf_tcp_analysis_first_rtt;218static int hf_tcp_analysis_rto;219static int hf_tcp_analysis_rto_frame;220static int hf_tcp_analysis_duplicate_ack;221static int hf_tcp_analysis_duplicate_ack_num;222static int hf_tcp_analysis_duplicate_ack_frame;223static int hf_tcp_continuation_to;224static int hf_tcp_pdu_time;225static int hf_tcp_pdu_size;226static int hf_tcp_pdu_last_frame;227static int hf_tcp_reassembled_in;228static int hf_tcp_reassembled_length;229static int hf_tcp_reassembled_data;230static int hf_tcp_segments;231static int hf_tcp_segment;232static int hf_tcp_segment_overlap;233static int hf_tcp_segment_overlap_conflict;234static int hf_tcp_segment_multiple_tails;235static int hf_tcp_segment_too_long_fragment;236static int hf_tcp_segment_error;237static int hf_tcp_segment_count;238static int hf_tcp_options;239static int hf_tcp_option_kind;240static int hf_tcp_option_len;241static int hf_tcp_option_mss_val;242static int hf_tcp_option_wscale_shift;243static int hf_tcp_option_wscale_multiplier;244static int hf_tcp_option_sack_sle;245static int hf_tcp_option_sack_sre;246static int hf_tcp_option_sack_range_count;247static int hf_tcp_option_sack_dsack_le;248static int hf_tcp_option_sack_dsack_re;249static int hf_tcp_option_echo;250static int hf_tcp_option_timestamp_tsval;251static int hf_tcp_option_timestamp_tsecr;252static int hf_tcp_option_cc;253static int hf_tcp_option_md5_digest;254static int hf_tcp_option_ao_keyid;255static int hf_tcp_option_ao_rnextkeyid;256static int hf_tcp_option_ao_mac;257static int hf_tcp_option_qs_rate;258static int hf_tcp_option_qs_ttl_diff;259static int hf_tcp_option_tarr_rate;260static int hf_tcp_option_tarr_reserved;261static int hf_tcp_option_acc_ecn_ee0b;262static int hf_tcp_option_acc_ecn_eceb;263static int hf_tcp_option_acc_ecn_ee1b;264static int hf_tcp_option_exp_data;265static int hf_tcp_option_exp_exid;266static int hf_tcp_option_unknown_payload;267 268static int hf_tcp_option_rvbd_probe_version1;269static int hf_tcp_option_rvbd_probe_version2;270static int hf_tcp_option_rvbd_probe_type1;271static int hf_tcp_option_rvbd_probe_type2;272static int hf_tcp_option_rvbd_probe_prober;273static int hf_tcp_option_rvbd_probe_proxy;274static int hf_tcp_option_rvbd_probe_client;275static int hf_tcp_option_rvbd_probe_proxy_port;276static int hf_tcp_option_rvbd_probe_appli_ver;277static int hf_tcp_option_rvbd_probe_storeid;278static int hf_tcp_option_rvbd_probe_flags;279static int hf_tcp_option_rvbd_probe_flag_last_notify;280static int hf_tcp_option_rvbd_probe_flag_server_connected;281static int hf_tcp_option_rvbd_probe_flag_not_cfe;282static int hf_tcp_option_rvbd_probe_flag_sslcert;283static int hf_tcp_option_rvbd_probe_flag_probe_cache;284 285static int hf_tcp_option_rvbd_trpy_flags;286static int hf_tcp_option_rvbd_trpy_flag_mode;287static int hf_tcp_option_rvbd_trpy_flag_oob;288static int hf_tcp_option_rvbd_trpy_flag_chksum;289static int hf_tcp_option_rvbd_trpy_flag_fw_rst;290static int hf_tcp_option_rvbd_trpy_flag_fw_rst_inner;291static int hf_tcp_option_rvbd_trpy_flag_fw_rst_probe;292static int hf_tcp_option_rvbd_trpy_src;293static int hf_tcp_option_rvbd_trpy_dst;294static int hf_tcp_option_rvbd_trpy_src_port;295static int hf_tcp_option_rvbd_trpy_dst_port;296static int hf_tcp_option_rvbd_trpy_client_port;297 298static int hf_tcp_option_mptcp_flags;299static int hf_tcp_option_mptcp_backup_flag;300static int hf_tcp_option_mptcp_checksum_flag;301static int hf_tcp_option_mptcp_B_flag;302static int hf_tcp_option_mptcp_C_flag;303static int hf_tcp_option_mptcp_H_v0_flag;304static int hf_tcp_option_mptcp_H_v1_flag;305static int hf_tcp_option_mptcp_F_flag;306static int hf_tcp_option_mptcp_m_flag;307static int hf_tcp_option_mptcp_M_flag;308static int hf_tcp_option_mptcp_a_flag;309static int hf_tcp_option_mptcp_A_flag;310static int hf_tcp_option_mptcp_U_flag;311static int hf_tcp_option_mptcp_V_flag;312static int hf_tcp_option_mptcp_W_flag;313static int hf_tcp_option_mptcp_T_flag;314static int hf_tcp_option_mptcp_tcprst_reason;315static int hf_tcp_option_mptcp_reserved_v0_flag;316static int hf_tcp_option_mptcp_reserved_v1_flag;317static int hf_tcp_option_mptcp_subtype;318static int hf_tcp_option_mptcp_version;319static int hf_tcp_option_mptcp_reserved;320static int hf_tcp_option_mptcp_address_id;321static int hf_tcp_option_mptcp_recv_token;322static int hf_tcp_option_mptcp_sender_key;323static int hf_tcp_option_mptcp_recv_key;324static int hf_tcp_option_mptcp_sender_rand;325static int hf_tcp_option_mptcp_sender_trunc_hmac;326static int hf_tcp_option_mptcp_sender_hmac;327static int hf_tcp_option_mptcp_addaddr_trunc_hmac;328static int hf_tcp_option_mptcp_data_ack_raw;329static int hf_tcp_option_mptcp_data_seq_no_raw;330static int hf_tcp_option_mptcp_subflow_seq_no;331static int hf_tcp_option_mptcp_data_lvl_len;332static int hf_tcp_option_mptcp_checksum;333static int hf_tcp_option_mptcp_ipver;334static int hf_tcp_option_mptcp_echo;335static int hf_tcp_option_mptcp_ipv4;336static int hf_tcp_option_mptcp_ipv6;337static int hf_tcp_option_mptcp_port;338static int hf_mptcp_expected_idsn;339 340static int hf_mptcp_dsn;341static int hf_mptcp_rawdsn64;342static int hf_mptcp_dss_dsn;343static int hf_mptcp_ack;344static int hf_mptcp_stream;345static int hf_mptcp_expected_token;346static int hf_mptcp_analysis;347static int hf_mptcp_analysis_master;348static int hf_mptcp_analysis_subflows;349static int hf_mptcp_number_of_removed_addresses;350static int hf_mptcp_related_mapping;351static int hf_mptcp_reinjection_of;352static int hf_mptcp_reinjected_in;353 354 355static int hf_tcp_option_fast_open_cookie_request;356static int hf_tcp_option_fast_open_cookie;357 358static int hf_tcp_ts_relative;359static int hf_tcp_ts_delta;360static int hf_tcp_option_scps_vector;361static int hf_tcp_option_scps_binding;362static int hf_tcp_option_scps_binding_len;363static int hf_tcp_scpsoption_flags_bets;364static int hf_tcp_scpsoption_flags_snack1;365static int hf_tcp_scpsoption_flags_snack2;366static int hf_tcp_scpsoption_flags_compress;367static int hf_tcp_scpsoption_flags_nlts;368static int hf_tcp_scpsoption_flags_reserved;369static int hf_tcp_scpsoption_connection_id;370static int hf_tcp_option_snack_offset;371static int hf_tcp_option_snack_size;372static int hf_tcp_option_snack_le;373static int hf_tcp_option_snack_re;374static int hf_tcp_option_user_to_granularity;375static int hf_tcp_option_user_to_val;376static int hf_tcp_proc_src_uid;377static int hf_tcp_proc_src_pid;378static int hf_tcp_proc_src_uname;379static int hf_tcp_proc_src_cmd;380static int hf_tcp_proc_dst_uid;381static int hf_tcp_proc_dst_pid;382static int hf_tcp_proc_dst_uname;383static int hf_tcp_proc_dst_cmd;384static int hf_tcp_segment_data;385static int hf_tcp_payload;386static int hf_tcp_reset_cause;387static int hf_tcp_fin_retransmission;388static int hf_tcp_option_rvbd_probe_reserved;389static int hf_tcp_option_scps_binding_data;390static int hf_tcp_syncookie_time;391static int hf_tcp_syncookie_mss;392static int hf_tcp_syncookie_hash;393static int hf_tcp_syncookie_option_timestamp;394static int hf_tcp_syncookie_option_ecn;395static int hf_tcp_syncookie_option_sack;396static int hf_tcp_syncookie_option_wscale;397 398static gint ett_tcp;399static gint ett_tcp_completeness;400static gint ett_tcp_flags;401static gint ett_tcp_options;402static gint ett_tcp_option_timestamp;403static gint ett_tcp_option_mss;404static gint ett_tcp_option_wscale;405static gint ett_tcp_option_sack;406static gint ett_tcp_option_snack;407static gint ett_tcp_option_scps;408static gint ett_tcp_scpsoption_flags;409static gint ett_tcp_option_scps_extended;410static gint ett_tcp_option_user_to;411static gint ett_tcp_option_exp;412static gint ett_tcp_option_acc_ecn;413static gint ett_tcp_option_sack_perm;414static gint ett_tcp_analysis;415static gint ett_tcp_analysis_faults;416static gint ett_tcp_timestamps;417static gint ett_tcp_segments;418static gint ett_tcp_segment;419static gint ett_tcp_checksum;420static gint ett_tcp_process_info;421static gint ett_tcp_option_mptcp;422static gint ett_tcp_opt_rvbd_probe;423static gint ett_tcp_opt_rvbd_probe_flags;424static gint ett_tcp_opt_rvbd_trpy;425static gint ett_tcp_opt_rvbd_trpy_flags;426static gint ett_tcp_opt_echo;427static gint ett_tcp_opt_cc;428static gint ett_tcp_opt_md5;429static gint ett_tcp_opt_ao;430static gint ett_tcp_opt_qs;431static gint ett_tcp_opt_recbound;432static gint ett_tcp_opt_scpscor;433static gint ett_tcp_unknown_opt;434static gint ett_tcp_option_other;435static gint ett_tcp_syncookie;436static gint ett_tcp_syncookie_option;437static gint ett_mptcp_analysis;438static gint ett_mptcp_analysis_subflows;439 440static expert_field ei_tcp_opt_len_invalid;441static expert_field ei_tcp_analysis_retransmission;442static expert_field ei_tcp_analysis_fast_retransmission;443static expert_field ei_tcp_analysis_spurious_retransmission;444static expert_field ei_tcp_analysis_out_of_order;445static expert_field ei_tcp_analysis_reused_ports;446static expert_field ei_tcp_analysis_lost_packet;447static expert_field ei_tcp_analysis_ack_lost_packet;448static expert_field ei_tcp_analysis_window_update;449static expert_field ei_tcp_analysis_window_full;450static expert_field ei_tcp_analysis_keep_alive;451static expert_field ei_tcp_analysis_keep_alive_ack;452static expert_field ei_tcp_analysis_duplicate_ack;453static expert_field ei_tcp_analysis_zero_window_probe;454static expert_field ei_tcp_analysis_zero_window;455static expert_field ei_tcp_analysis_zero_window_probe_ack;456static expert_field ei_tcp_analysis_tfo_syn;457static expert_field ei_tcp_analysis_tfo_ack;458static expert_field ei_tcp_analysis_tfo_ignored;459static expert_field ei_tcp_analysis_partial_ack;460static expert_field ei_tcp_scps_capable;461static expert_field ei_tcp_option_sack_dsack;462static expert_field ei_tcp_option_snack_sequence;463static expert_field ei_tcp_option_wscale_shift_invalid;464static expert_field ei_tcp_option_mss_absent;465static expert_field ei_tcp_option_mss_present;466static expert_field ei_tcp_option_sack_perm_absent;467static expert_field ei_tcp_option_sack_perm_present;468static expert_field ei_tcp_short_segment;469static expert_field ei_tcp_ack_nonzero;470static expert_field ei_tcp_connection_synack;471static expert_field ei_tcp_connection_syn;472static expert_field ei_tcp_connection_fin;473static expert_field ei_tcp_connection_rst;474static expert_field ei_tcp_connection_fin_active;475static expert_field ei_tcp_connection_fin_passive;476static expert_field ei_tcp_checksum_ffff;477static expert_field ei_tcp_checksum_partial;478static expert_field ei_tcp_checksum_bad;479static expert_field ei_tcp_urgent_pointer_non_zero;480static expert_field ei_tcp_suboption_malformed;481static expert_field ei_tcp_nop;482static expert_field ei_tcp_non_zero_bytes_after_eol;483static expert_field ei_tcp_bogus_header_length;484 485/* static expert_field ei_mptcp_analysis_unexpected_idsn; */486static expert_field ei_mptcp_analysis_echoed_key_mismatch;487static expert_field ei_mptcp_analysis_missing_algorithm;488static expert_field ei_mptcp_analysis_unsupported_algorithm;489static expert_field ei_mptcp_infinite_mapping;490static expert_field ei_mptcp_mapping_missing;491/* static expert_field ei_mptcp_stream_incomplete; */492/* static expert_field ei_mptcp_analysis_dsn_out_of_order; */493 494/* Some protocols such as encrypted DCE/RPCoverHTTP have dependencies495 * from one PDU to the next PDU and require that they are called in sequence.496 * These protocols would not be able to handle PDUs coming out of order497 * or for example when a PDU is seen twice, like for retransmissions.498 * This preference can be set for such protocols to make sure that we don't499 * invoke the subdissectors for retransmitted or out-of-order segments.500 */501static bool_Bool tcp_no_subdissector_on_error = true1;502 503/* Enable buffering of out-of-order TCP segments before passing it to a504 * subdissector (depends on "tcp_desegment"). */505static bool_Bool tcp_reassemble_out_of_order;506 507/*508 * FF: https://www.rfc-editor.org/rfc/rfc6994.html509 * With this flag set we assume the option structure for experimental510 * codepoints (253, 254) has an Experiment Identifier (ExID), which is511 * the first 16-bit field after the Kind and Length.512 * The ExID is used to differentiate different experiments and thus will513 * be used in data dissection.514 */515static bool_Bool tcp_exp_options_rfc6994 = true1;516 517/*518 * This flag indicates which of Fast Retransmission or Out-of-Order519 * interpretation should supersede when analyzing an ambiguous packet as520 * things are not always clear. The user is authorized to change this521 * behavior.522 * When set, we keep the historical interpretation (Fast RT > OOO)523 */524static bool_Bool tcp_fastrt_precedence = true1;525 526/* Process info, currently discovered via IPFIX */527static bool_Bool tcp_display_process_info;528 529/* Read the sequence number as syn cookie */530static bool_Bool read_seq_as_syn_cookie;531 532/*533 * TCP option534 */535#define TCPOPT_NOP1 1 /* Padding */536#define TCPOPT_EOL0 0 /* End of options */537#define TCPOPT_MSS2 2 /* Segment size negotiating */538#define TCPOPT_WINDOW3 3 /* Window scaling */539#define TCPOPT_SACK_PERM4 4 /* SACK Permitted */540#define TCPOPT_SACK5 5 /* SACK Block */541#define TCPOPT_ECHO6 6542#define TCPOPT_ECHOREPLY7 7543#define TCPOPT_TIMESTAMP8 8 /* Better RTT estimations/PAWS */544#define TCPOPT_CC11 11545#define TCPOPT_CCNEW12 12546#define TCPOPT_CCECHO13 13547#define TCPOPT_MD519 19 /* RFC2385 */548#define TCPOPT_SCPS20 20 /* SCPS Capabilities */549#define TCPOPT_SNACK21 21 /* SCPS SNACK */550#define TCPOPT_RECBOUND22 22 /* SCPS Record Boundary */551#define TCPOPT_CORREXP23 23 /* SCPS Corruption Experienced */552#define TCPOPT_QS27 27 /* RFC4782 Quick-Start Response */553#define TCPOPT_USER_TO28 28 /* RFC5482 User Timeout Option */554#define TCPOPT_AO29 29 /* RFC5925 The TCP Authentication Option */555#define TCPOPT_MPTCP30 30 /* RFC6824 Multipath TCP */556#define TCPOPT_TFO34 34 /* RFC7413 TCP Fast Open Cookie */557#define TCPOPT_ACC_ECN_00xac 0xac /* draft-ietf-tcpm-accurate-ecn */558#define TCPOPT_ACC_ECN_10xae 0xae /* draft-ietf-tcpm-accurate-ecn */559#define TCPOPT_EXP_FD0xfd 0xfd /* Experimental, reserved */560#define TCPOPT_EXP_FE0xfe 0xfe /* Experimental, reserved */561/* Non IANA registered option numbers */562#define TCPOPT_RVBD_PROBE76 76 /* Riverbed probe option */563#define TCPOPT_RVBD_TRPY78 78 /* Riverbed transparency option */564 565/*566 * TCP option lengths567 */568#define TCPOLEN_MSS4 4569#define TCPOLEN_WINDOW3 3570#define TCPOLEN_SACK_PERM2 2571#define TCPOLEN_SACK_MIN2 2572#define TCPOLEN_ECHO6 6573#define TCPOLEN_ECHOREPLY6 6574#define TCPOLEN_TIMESTAMP10 10575#define TCPOLEN_CC6 6576#define TCPOLEN_CCNEW6 6577#define TCPOLEN_CCECHO6 6578#define TCPOLEN_MD518 18579#define TCPOLEN_SCPS4 4580#define TCPOLEN_SNACK6 6581#define TCPOLEN_RECBOUND2 2582#define TCPOLEN_CORREXP2 2583#define TCPOLEN_QS8 8584#define TCPOLEN_USER_TO4 4585#define TCPOLEN_MPTCP_MIN3 3586#define TCPOLEN_TFO_MIN2 2587#define TCPOLEN_RVBD_PROBE_MIN3 3588#define TCPOLEN_RVBD_TRPY_MIN16 16589#define TCPOLEN_EXP_MIN4 4590 591/*592 * TCP Experimental Option Experiment Identifiers (TCP ExIDs)593 * See: https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-exids594 * Wireshark only supports 16-bit ExIDs595 */596 597#define TCPEXID_TARR0x00ac 0x00ac598#define TCPEXID_HOST_ID0x0348 0x0348599#define TCPEXID_ASC0x0a0d 0x0a0d600#define TCPEXID_CAPABILITY0x0ca0 0x0ca0601#define TCPEXID_EDO0x0ed0 0x0ed0602#define TCPEXID_ENO0x454e 0x454e603#define TCPEXID_SNO0x5323 0x5323604#define TCPEXID_TS_INTERVAL0x75ec 0x75ec /* 32-bit ExID: 0x75ecffee */605#define TCPEXID_ACC_ECN_00xacc0 0xacc0606#define TCPEXID_ACC_ECN_10xacc1 0xacc1607#define TCPEXID_ACC_ECN0xacce 0xacce608#define TCPEXID_SMC_R0xe2d4 0xe2d4 /* 32-bit ExID: 0xe2d4c3d9 */609#define TCPEXID_FO0xf989 0xf989610#define TCPEXID_LOW_LATENCY0xf990 0xf990611 612/*613 * Multipath TCP subtypes614 */615#define TCPOPT_MPTCP_MP_CAPABLE0x0 0x0 /* Multipath TCP Multipath Capable */616#define TCPOPT_MPTCP_MP_JOIN0x1 0x1 /* Multipath TCP Join Connection */617#define TCPOPT_MPTCP_DSS0x2 0x2 /* Multipath TCP Data Sequence Signal */618#define TCPOPT_MPTCP_ADD_ADDR0x3 0x3 /* Multipath TCP Add Address */619#define TCPOPT_MPTCP_REMOVE_ADDR0x4 0x4 /* Multipath TCP Remove Address */620#define TCPOPT_MPTCP_MP_PRIO0x5 0x5 /* Multipath TCP Change Subflow Priority */621#define TCPOPT_MPTCP_MP_FAIL0x6 0x6 /* Multipath TCP Fallback */622#define TCPOPT_MPTCP_MP_FASTCLOSE0x7 0x7 /* Multipath TCP Fast Close */623#define TCPOPT_MPTCP_MP_TCPRST0x8 0x8 /* Multipath TCP Reset */624 625/*626 * Conversation Completeness values627 */628#define TCP_COMPLETENESS_SYNSENT0x01 0x01 /* TCP SYN SENT */629#define TCP_COMPLETENESS_SYNACK0x02 0x02 /* TCP SYN ACK */630#define TCP_COMPLETENESS_ACK0x04 0x04 /* TCP ACK */631#define TCP_COMPLETENESS_DATA0x08 0x08 /* TCP data */632#define TCP_COMPLETENESS_FIN0x10 0x10 /* TCP FIN */633#define TCP_COMPLETENESS_RST0x20 0x20 /* TCP RST */634 635static const true_false_string tcp_option_user_to_granularity = {636 "Minutes", "Seconds"637};638 639static const value_string tcp_option_kind_vs[] = {640 { TCPOPT_EOL0, "End of Option List" },641 { TCPOPT_NOP1, "No-Operation" },642 { TCPOPT_MSS2, "Maximum Segment Size" },643 { TCPOPT_WINDOW3, "Window Scale" },644 { TCPOPT_SACK_PERM4, "SACK Permitted" },645 { TCPOPT_SACK5, "SACK" },646 { TCPOPT_ECHO6, "Echo" },647 { TCPOPT_ECHOREPLY7, "Echo Reply" },648 { TCPOPT_TIMESTAMP8, "Time Stamp Option" },649 { 9, "Partial Order Connection Permitted" },650 { 10, "Partial Order Service Profile" },651 { TCPOPT_CC11, "CC" },652 { TCPOPT_CCNEW12, "CC.NEW" },653 { TCPOPT_CCECHO13, "CC.ECHO" },654 { 14, "TCP Alternate Checksum Request" },655 { 15, "TCP Alternate Checksum Data" },656 { 16, "Skeeter" },657 { 17, "Bubba" },658 { 18, "Trailer Checksum Option" },659 { TCPOPT_MD519, "MD5 Signature Option" },660 { TCPOPT_SCPS20, "SCPS Capabilities" },661 { TCPOPT_SNACK21, "Selective Negative Acknowledgements" },662 { TCPOPT_RECBOUND22, "Record Boundaries" },663 { TCPOPT_CORREXP23, "Corruption experienced" },664 { 24, "SNAP" },665 { 25, "Unassigned" },666 { 26, "TCP Compression Filter" },667 { TCPOPT_QS27, "Quick-Start Response" },668 { TCPOPT_USER_TO28, "User Timeout Option" },669 { TCPOPT_AO29, "The TCP Authentication Option" },670 { TCPOPT_MPTCP30, "Multipath TCP" },671 { TCPOPT_TFO34, "TCP Fast Open Cookie" },672 { TCPOPT_RVBD_PROBE76, "Riverbed Probe" },673 { TCPOPT_RVBD_TRPY78, "Riverbed Transparency" },674 { TCPOPT_ACC_ECN_00xac, "Accurate ECN Order 0" },675 { TCPOPT_ACC_ECN_10xae, "Accurate ECN Order 1" },676 { TCPOPT_EXP_FD0xfd, "RFC3692-style Experiment 1" },677 { TCPOPT_EXP_FE0xfe, "RFC3692-style Experiment 2" },678 { 0, NULL((void*)0) }679};680static value_string_ext tcp_option_kind_vs_ext = VALUE_STRING_EXT_INIT(tcp_option_kind_vs){ _try_val_to_str_ext_init, 0, (sizeof (tcp_option_kind_vs) /
sizeof ((tcp_option_kind_vs)[0]))-1, tcp_option_kind_vs, "tcp_option_kind_vs"
}
;681 682static const value_string tcp_exid_vs[] = {683 { TCPEXID_TARR0x00ac, "TCP ACK Rate Request" },684 { TCPEXID_HOST_ID0x0348, "Host ID" },685 { TCPEXID_ASC0x0a0d, "Autonomous System Compensation" },686 { TCPEXID_CAPABILITY0x0ca0, "Capability Option" },687 { TCPEXID_EDO0x0ed0, "Extended Data Offset" },688 { TCPEXID_ENO0x454e, "Encryption Negotiation" },689 { TCPEXID_SNO0x5323, "Service Number" },690 { TCPEXID_TS_INTERVAL0x75ec, "Timestamp Interval" },691 { TCPEXID_ACC_ECN_00xacc0, "Accurate ECN - Order 0" },692 { TCPEXID_ACC_ECN_10xacc1, "Accurate ECN - Order 1" },693 { TCPEXID_ACC_ECN0xacce, "Accurate ECN" },694 { TCPEXID_SMC_R0xe2d4, "Shared Memory communications over RMDA protocol" },695 { TCPEXID_FO0xf989, "Fast Open" },696 { TCPEXID_LOW_LATENCY0xf990, "Low Latency" },697 { 0, NULL((void*)0) }698};699 700/* not all of the hf_fields below make sense for TCP but we have to provide701 them anyways to comply with the API (which was aimed for IP fragment702 reassembly) */703static const fragment_items tcp_segment_items = {704 &ett_tcp_segment,705 &ett_tcp_segments,706 &hf_tcp_segments,707 &hf_tcp_segment,708 &hf_tcp_segment_overlap,709 &hf_tcp_segment_overlap_conflict,710 &hf_tcp_segment_multiple_tails,711 &hf_tcp_segment_too_long_fragment,712 &hf_tcp_segment_error,713 &hf_tcp_segment_count,714 &hf_tcp_reassembled_in,715 &hf_tcp_reassembled_length,716 &hf_tcp_reassembled_data,717 "Segments"718};719 720 721static const value_string mptcp_subtype_vs[] = {722 { TCPOPT_MPTCP_MP_CAPABLE0x0, "Multipath Capable" },723 { TCPOPT_MPTCP_MP_JOIN0x1, "Join Connection" },724 { TCPOPT_MPTCP_DSS0x2, "Data Sequence Signal" },725 { TCPOPT_MPTCP_ADD_ADDR0x3, "Add Address"},726 { TCPOPT_MPTCP_REMOVE_ADDR0x4, "Remove Address" },727 { TCPOPT_MPTCP_MP_PRIO0x5, "Change Subflow Priority" },728 { TCPOPT_MPTCP_MP_FAIL0x6, "TCP Fallback" },729 { TCPOPT_MPTCP_MP_FASTCLOSE0x7, "Fast Close" },730 { TCPOPT_MPTCP_MP_TCPRST0x8, "TCP Reset" },731 { 0, NULL((void*)0) }732};733 734static dissector_table_t subdissector_table;735static dissector_table_t tcp_option_table;736static heur_dissector_list_t heur_subdissector_list;737static dissector_handle_t data_handle;738static dissector_handle_t tcp_handle;739static dissector_handle_t sport_handle;740static dissector_handle_t tcp_opt_unknown_handle;741static capture_dissector_handle_t tcp_cap_handle;742 743static guint32 tcp_stream_count;744static guint32 mptcp_stream_count;745 746 747 748/*749 * Maps an MPTCP token to a mptcp_analysis structure750 * Collisions are not handled751 */752static wmem_tree_t *mptcp_tokens;753 754static int * const tcp_option_mptcp_capable_v0_flags[] = {755 &hf_tcp_option_mptcp_checksum_flag,756 &hf_tcp_option_mptcp_B_flag,757 &hf_tcp_option_mptcp_H_v0_flag,758 &hf_tcp_option_mptcp_reserved_v0_flag,759 NULL((void*)0)760};761 762static int * const tcp_option_mptcp_capable_v1_flags[] = {763 &hf_tcp_option_mptcp_checksum_flag,764 &hf_tcp_option_mptcp_B_flag,765 &hf_tcp_option_mptcp_C_flag,766 &hf_tcp_option_mptcp_H_v1_flag,767 &hf_tcp_option_mptcp_reserved_v1_flag,768 NULL((void*)0)769};770 771static int * const tcp_option_mptcp_join_flags[] = {772 &hf_tcp_option_mptcp_backup_flag,773 NULL((void*)0)774};775 776static int * const tcp_option_mptcp_dss_flags[] = {777 &hf_tcp_option_mptcp_F_flag,778 &hf_tcp_option_mptcp_m_flag,779 &hf_tcp_option_mptcp_M_flag,780 &hf_tcp_option_mptcp_a_flag,781 &hf_tcp_option_mptcp_A_flag,782 NULL((void*)0)783};784 785static int * const tcp_option_mptcp_tcprst_flags[] = {786 &hf_tcp_option_mptcp_U_flag,787 &hf_tcp_option_mptcp_V_flag,788 &hf_tcp_option_mptcp_W_flag,789 &hf_tcp_option_mptcp_T_flag,790 NULL((void*)0)791};792 793static const unit_name_string units_64bit_version = { " (64bits version)", NULL((void*)0) };794 795static guint8796tcp_get_ace(const struct tcpheader *tcph)797{798 guint8 ace;799 800 ace = 0;801 if (tcph->th_flags & TH_AE0x0100) {802 ace += 4;803 }804 if (tcph->th_flags & TH_CWR0x0080) {805 ace += 2;806 }807 if (tcph->th_flags & TH_ECE0x0040) {808 ace += 1;809 }810 return ace;811}812 813static char *814tcp_flags_to_str(wmem_allocator_t *scope, const struct tcpheader *tcph)815{816 static const char flags[][4] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECE", "CWR", "AE" };817 static const char digit[][2] = { "0", "1", "2", "3", "4", "5", "6", "7" };818 const int maxlength = 64; /* upper bounds, max 53B: 8 * 3 + 2 + strlen("Reserved") + 9 * 2 + 1 */819 820 char *pbuf;821 char *buf;822 guint8 ace;823 int i;824 825 buf = pbuf = (char *) wmem_alloc(scope, maxlength);826 *pbuf = '\0';827 828 for (i = 0; i < (tcph->th_use_ace ? 6 : 9); i++) {829 if (tcph->th_flags & (1 << i)) {830 if (buf[0])831 pbuf = g_stpcpy(pbuf, ", ");832 pbuf = g_stpcpy(pbuf, flags[i]);833 }834 }835 if (tcph->th_use_ace) {836 ace = tcp_get_ace(tcph);837 pbuf = g_stpcpy(pbuf, ", ACE=");838 pbuf = g_stpcpy(pbuf, digit[ace]);839 }840 841 if (tcph->th_flags & TH_RES0x0E00) {842 if (buf[0])843 pbuf = g_stpcpy(pbuf, ", ");844 g_stpcpy(pbuf, "Reserved");845 }846 847 if (buf[0] == '\0')848 g_stpcpy(pbuf, "<None>");849 850 return buf;851}852 853static char *854tcp_flags_to_str_first_letter(wmem_allocator_t *scope, const struct tcpheader *tcph)855{856 wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");857 unsigned i;858 const unsigned flags_count = 12;859 const char first_letters[] = "RRRACEUAPRSF";860 const char digits[] = "01234567";861 862 /* upper three bytes are marked as reserved ('R'). */863 for (i = 0; i < flags_count; i++) {864 if (tcph->th_use_ace && 3 <= i && i <= 5) {865 if (i == 4) {866 wmem_strbuf_append_c(buf, digits[tcp_get_ace(tcph)]);867 } else {868 wmem_strbuf_append_c(buf, '-');869 }870 } else {871 if (((tcph->th_flags >> (flags_count - 1 - i)) & 1)) {872 wmem_strbuf_append_c(buf, first_letters[i]);873 } else {874 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7");875 }876 }877 }878 879 return wmem_strbuf_finalize(buf);880}881 882/*883 * Print the first letter of each flag set, or the dot character otherwise884 */885static char *886completeness_flags_to_str_first_letter(wmem_allocator_t *scope, guint8 flags)887{888 wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");889 890 if( flags & TCP_COMPLETENESS_RST0x20 )891 wmem_strbuf_append(buf, "R");892 else893 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7");894 895 if( flags & TCP_COMPLETENESS_FIN0x10 )896 wmem_strbuf_append(buf, "F");897 else898 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7");899 900 if( flags & TCP_COMPLETENESS_DATA0x08 )901 wmem_strbuf_append(buf, "D");902 else903 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7");904 905 if( flags & TCP_COMPLETENESS_ACK0x04 )906 wmem_strbuf_append(buf, "A");907 else908 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7");909 910 if( flags & TCP_COMPLETENESS_SYNACK0x02 )911 wmem_strbuf_append(buf, "S");912 else913 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7");914 915 if( flags & TCP_COMPLETENESS_SYNSENT0x01 )916 wmem_strbuf_append(buf, "S");917 else918 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7");919 920 return wmem_strbuf_finalize(buf);921}922 923static void924tcp_src_prompt(packet_info *pinfo, gchar *result)925{926 guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport
, pinfo->curr_layer_num)))
;927 928 snprintf(result, MAX_DECODE_AS_PROMPT_LEN200, "source (%u%s)", port, UTF8_RIGHTWARDS_ARROW"\xe2\x86\x92");929}930 931static gpointer932tcp_src_value(packet_info *pinfo)933{934 return p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num);935}936 937static void938tcp_dst_prompt(packet_info *pinfo, gchar *result)939{940 guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport
, pinfo->curr_layer_num)))
;941 942 snprintf(result, MAX_DECODE_AS_PROMPT_LEN200, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW"\xe2\x86\x92", port);943}944 945static gpointer946tcp_dst_value(packet_info *pinfo)947{948 return p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num);949}950 951static void952tcp_both_prompt(packet_info *pinfo, gchar *result)953{954 guint32 srcport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport
, pinfo->curr_layer_num)))
,955 destport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport
, pinfo->curr_layer_num)))
;956 snprintf(result, MAX_DECODE_AS_PROMPT_LEN200, "both (%u%s%u)", srcport, UTF8_LEFT_RIGHT_ARROW"\xe2\x86\x94", destport);957}958 959static const char* tcp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)960{961 962 if (filter == CONV_FT_SRC_PORT)963 return "tcp.srcport";964 965 if (filter == CONV_FT_DST_PORT)966 return "tcp.dstport";967 968 if (filter == CONV_FT_ANY_PORT)969 return "tcp.port";970 971 if(!conv) {972 return CONV_FILTER_INVALID"INVALID";973 }974 975 if (filter == CONV_FT_SRC_ADDRESS) {976 if (conv->src_address.type == AT_IPv4)977 return "ip.src";978 if (conv->src_address.type == AT_IPv6)979 return "ipv6.src";980 }981 982 if (filter == CONV_FT_DST_ADDRESS) {983 if (conv->dst_address.type == AT_IPv4)984 return "ip.dst";985 if (conv->dst_address.type == AT_IPv6)986 return "ipv6.dst";987 }988 989 if (filter == CONV_FT_ANY_ADDRESS) {990 if (conv->src_address.type == AT_IPv4)991 return "ip.addr";992 if (conv->src_address.type == AT_IPv6)993 return "ipv6.addr";994 }995 996 return CONV_FILTER_INVALID"INVALID";997}998 999static ct_dissector_info_t tcp_ct_dissector_info = {&tcp_conv_get_filter_type};1000 1001/*1002 * callback function for conversation stats1003 */1004static int tcp_conv_cb_update(conversation_t *conv)1005{1006 struct tcp_analysis *tcpd;1007 tcpd=get_tcp_conversation_data_idempotent(conv);1008 if(tcpd)1009 return tcpd->flow1.flow_count + tcpd->flow2.flow_count;1010 else1011 return 0;1012}1013 1014static tap_packet_status1015tcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *vip, tap_flags_t flags)1016{1017 conv_hash_t *hash = (conv_hash_t*) pct;1018 hash->flags = flags;1019 1020 const struct tcpheader *tcphdr=(const struct tcpheader *)vip;1021 1022 add_conversation_table_data_extended(hash, &tcphdr->ip_src, &tcphdr->ip_dst, tcphdr->th_sport, tcphdr->th_dport, (conv_id_t) tcphdr->th_stream, 1, pinfo->fd->pkt_len,1023 &pinfo->rel_ts, &pinfo->abs_ts, &tcp_ct_dissector_info, CONVERSATION_TCP, (guint32)pinfo->num, tcp_conv_cb_update);1024 1025 1026 return TAP_PACKET_REDRAW;1027}1028 1029static tap_packet_status1030mptcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *vip, tap_flags_t flags)1031{1032 conv_hash_t *hash = (conv_hash_t*) pct;1033 hash->flags = flags;1034 1035 const struct tcp_analysis *tcpd=(const struct tcp_analysis *)vip;1036 const mptcp_meta_flow_t *meta=(const mptcp_meta_flow_t *)tcpd->fwd->mptcp_subflow->meta;1037 1038 add_conversation_table_data_with_conv_id(hash, &meta->ip_src, &meta->ip_dst,1039 meta->sport, meta->dport, (conv_id_t) tcpd->mptcp_analysis->stream, 1, pinfo->fd->pkt_len,1040 &pinfo->rel_ts, &pinfo->abs_ts, &tcp_ct_dissector_info, CONVERSATION_TCP);1041 1042 return TAP_PACKET_REDRAW;1043}1044 1045static const char* tcp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter)1046{1047 if (filter == CONV_FT_SRC_PORT)1048 return "tcp.srcport";1049 1050 if (filter == CONV_FT_DST_PORT)1051 return "tcp.dstport";1052 1053 if (filter == CONV_FT_ANY_PORT)1054 return "tcp.port";1055 1056 if(!endpoint) {1057 return CONV_FILTER_INVALID"INVALID";1058 }1059 1060 if (filter == CONV_FT_SRC_ADDRESS) {1061 if (endpoint->myaddress.type == AT_IPv4)1062 return "ip.src";1063 if (endpoint->myaddress.type == AT_IPv6)1064 return "ipv6.src";1065 }1066 1067 if (filter == CONV_FT_DST_ADDRESS) {1068 if (endpoint->myaddress.type == AT_IPv4)1069 return "ip.dst";1070 if (endpoint->myaddress.type == AT_IPv6)1071 return "ipv6.dst";1072 }1073 1074 if (filter == CONV_FT_ANY_ADDRESS) {1075 if (endpoint->myaddress.type == AT_IPv4)1076 return "ip.addr";1077 if (endpoint->myaddress.type == AT_IPv6)1078 return "ipv6.addr";1079 }1080 1081 return CONV_FILTER_INVALID"INVALID";1082}1083 1084static et_dissector_info_t tcp_endpoint_dissector_info = {&tcp_endpoint_get_filter_type};1085 1086static tap_packet_status1087tcpip_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *vip, tap_flags_t flags)1088{1089 conv_hash_t *hash = (conv_hash_t*) pit;1090 hash->flags = flags;1091 1092 const struct tcpheader *tcphdr=(const struct tcpheader *)vip;1093 1094 /* Take two "add" passes per packet, adding for each direction, ensures that all1095 packets are counted properly (even if address is sending to itself)1096 XXX - this could probably be done more efficiently inside endpoint_table */1097 add_endpoint_table_data(hash, &tcphdr->ip_src, tcphdr->th_sport, TRUE(!(0)), 1, pinfo->fd->pkt_len, &tcp_endpoint_dissector_info, ENDPOINT_TCPCONVERSATION_TCP);1098 add_endpoint_table_data(hash, &tcphdr->ip_dst, tcphdr->th_dport, FALSE(0), 1, pinfo->fd->pkt_len, &tcp_endpoint_dissector_info, ENDPOINT_TCPCONVERSATION_TCP);1099 1100 return TAP_PACKET_REDRAW;1101}1102 1103static gboolean1104tcp_filter_valid(packet_info *pinfo, void *user_data _U___attribute__((unused)))1105{1106 return proto_is_frame_protocol(pinfo->layers, "tcp");1107}1108 1109static gchar*1110tcp_build_filter_by_id(packet_info *pinfo, void *user_data _U___attribute__((unused)))1111{1112 return ws_strdup_printf("tcp.stream eq %d", pinfo->stream_id)wmem_strdup_printf(((void*)0), "tcp.stream eq %d", pinfo->
stream_id)
;1113}1114 1115 1116/****************************************************************************/1117/* whenever a TCP packet is seen by the tap listener */1118/* Add a new tcp frame into the graph */1119static tap_packet_status1120tcp_seq_analysis_packet( void *ptr, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *tcp_info, tap_flags_t tapflags _U___attribute__((unused)))1121{1122 seq_analysis_info_t *sainfo = (seq_analysis_info_t *) ptr;1123 const struct tcpheader *tcph = (const struct tcpheader *)tcp_info;1124 char* flags;1125 seq_analysis_item_t *sai = sequence_analysis_create_sai_with_addresses(pinfo, sainfo);1126 1127 if (!sai)1128 return TAP_PACKET_DONT_REDRAW;1129 1130 sai->frame_number = pinfo->num;1131 1132 sai->port_src=pinfo->srcport;1133 sai->port_dst=pinfo->destport;1134 1135 flags = tcp_flags_to_str(NULL((void*)0), tcph);1136 1137 if ((tcph->th_have_seglen)&&(tcph->th_seglen!=0)){1138 sai->frame_label = ws_strdup_printf("%s - Len: %u",flags, tcph->th_seglen)wmem_strdup_printf(((void*)0), "%s - Len: %u",flags, tcph->
th_seglen)
;1139 }1140 else{1141 sai->frame_label = g_strdup(flags);1142 }1143 1144 wmem_free(NULL((void*)0), flags);1145 1146 if (tcph->th_flags & TH_ACK0x0010)1147 sai->comment = ws_strdup_printf("Seq = %u Ack = %u",tcph->th_seq, tcph->th_ack)wmem_strdup_printf(((void*)0), "Seq = %u Ack = %u",tcph->th_seq
, tcph->th_ack)
;1148 else1149 sai->comment = ws_strdup_printf("Seq = %u",tcph->th_seq)wmem_strdup_printf(((void*)0), "Seq = %u",tcph->th_seq);1150 1151 sai->line_style = 1;1152 sai->conv_num = (guint16) tcph->th_stream;1153 sai->display = TRUE(!(0));1154 1155 g_queue_push_tail(sainfo->items, sai);1156 1157 return TAP_PACKET_REDRAW;1158}1159 1160 1161gchar *tcp_follow_conv_filter(epan_dissect_t *edt _U___attribute__((unused)), packet_info *pinfo, guint *stream, guint *sub_stream _U___attribute__((unused)))1162{1163 conversation_t *conv;1164 struct tcp_analysis *tcpd;1165 1166 /* XXX: Since TCP doesn't use the endpoint API, we can only look1167 * up using the current pinfo addresses and ports. We don't want1168 * to create a new conversation or new TCP stream.1169 * Eventually the endpoint API should support storing multiple1170 * endpoints and TCP should be changed to use the endpoint API.1171 */1172 conv = find_conversation_strat(pinfo);1173 if (((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) ||1174 (pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6))1175 && (pinfo->ptype == PT_TCP) &&1176 conv != NULL((void*)0))1177 {1178 /* TCP over IPv4/6 */1179 tcpd=get_tcp_conversation_data(conv, pinfo);1180 if (tcpd == NULL((void*)0))1181 return NULL((void*)0);1182 1183 *stream = tcpd->stream;1184 return ws_strdup_printf("tcp.stream eq %u", tcpd->stream)wmem_strdup_printf(((void*)0), "tcp.stream eq %u", tcpd->stream
)
;1185 }1186 1187 return NULL((void*)0);1188}1189 1190gchar *tcp_follow_index_filter(guint stream, guint sub_stream _U___attribute__((unused)))1191{1192 return ws_strdup_printf("tcp.stream eq %u", stream)wmem_strdup_printf(((void*)0), "tcp.stream eq %u", stream);1193}1194 1195gchar *tcp_follow_address_filter(address *src_addr, address *dst_addr, int src_port, int dst_port)1196{1197 const gchar *ip_version = src_addr->type == AT_IPv6 ? "v6" : "";1198 gchar src_addr_str[WS_INET6_ADDRSTRLEN46];1199 gchar dst_addr_str[WS_INET6_ADDRSTRLEN46];1200 1201 address_to_str_buf(src_addr, src_addr_str, sizeof(src_addr_str));1202 address_to_str_buf(dst_addr, dst_addr_str, sizeof(dst_addr_str));1203 1204 return ws_strdup_printf("((ip%s.src eq %s and tcp.srcport eq %d) and "wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
1205 "(ip%s.dst eq %s and tcp.dstport eq %d))"wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
1206 " or "wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
1207 "((ip%s.src eq %s and tcp.srcport eq %d) and "wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
1208 "(ip%s.dst eq %s and tcp.dstport eq %d))",wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
1209 ip_version, src_addr_str, src_port,wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
1210 ip_version, dst_addr_str, dst_port,wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
1211 ip_version, dst_addr_str, dst_port,wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
1212 ip_version, src_addr_str, src_port)wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and "
"(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str
, src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str
, dst_port, ip_version, src_addr_str, src_port)
;1213 1214}1215 1216typedef struct tcp_follow_tap_data1217{1218 tvbuff_t *tvb;1219 struct tcpheader* tcph;1220 struct tcp_analysis *tcpd;1221 1222} tcp_follow_tap_data_t;1223 1224/*1225 * Tries to apply segments from fragments list to the reconstructed payload.1226 * Fragments that can be appended to the end of the payload will be applied (and1227 * removed from the list). Fragments that should have been received (according1228 * to the ack number) will also be appended to the payload (preceded by some1229 * dummy data to mark packet loss if any).1230 *1231 * Returns TRUE if one fragment has been applied or FALSE if no more fragments1232 * can be added to the payload (there might still be unacked fragments with1233 * missing segments before them).1234 */1235static gboolean1236check_follow_fragments(follow_info_t *follow_info, gboolean is_server, guint32 acknowledged, guint32 packet_num, gboolean use_ack)1237{1238 GList *fragment_entry;1239 follow_record_t *fragment, *follow_record;1240 guint32 lowest_seq = 0;1241 gchar *dummy_str;1242 1243 fragment_entry = g_list_first(follow_info->fragments[is_server]);1244 if (fragment_entry == NULL((void*)0))1245 return FALSE(0);1246 1247 fragment = (follow_record_t*)fragment_entry->data;1248 lowest_seq = fragment->seq;1249 1250 for (; fragment_entry != NULL((void*)0); fragment_entry = g_list_next(fragment_entry)((fragment_entry) ? (((GList *)(fragment_entry))->next) : (
(void*)0))
)1251 {1252 fragment = (follow_record_t*)fragment_entry->data;1253 1254 if( GT_SEQ(lowest_seq, fragment->seq)((gint32)((fragment->seq) - (lowest_seq)) < 0) ) {1255 lowest_seq = fragment->seq;1256 }1257 1258 if( LT_SEQ(fragment->seq, follow_info->seq[is_server])((gint32)((fragment->seq) - (follow_info->seq[is_server
])) < 0)
) {1259 guint32 newseq;1260 /* this sequence number seems dated, but1261 check the end to make sure it has no more1262 info than we have already seen */1263 newseq = fragment->seq + fragment->data->len;1264 if( GT_SEQ(newseq, follow_info->seq[is_server])((gint32)((follow_info->seq[is_server]) - (newseq)) < 0
)
) {1265 guint32 new_pos;1266 1267 /* this one has more than we have seen. let's get the1268 payload that we have not seen. This happens when1269 part of this frame has been retransmitted */1270 1271 new_pos = follow_info->seq[is_server] - fragment->seq;1272 1273 if ( fragment->data->len > new_pos ) {1274 guint32 new_frag_size = fragment->data->len - new_pos;1275 1276 follow_record = g_new0(follow_record_t,1)((follow_record_t *) g_malloc0_n ((1), sizeof (follow_record_t
)))
;1277 1278 follow_record->is_server = is_server;1279 follow_record->packet_num = fragment->packet_num;1280 follow_record->abs_ts = fragment->abs_ts;1281 follow_record->seq = follow_info->seq[is_server] + new_frag_size;1282 1283 follow_record->data = g_byte_array_append(g_byte_array_new(),1284 fragment->data->data + new_pos,1285 new_frag_size);1286 1287 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);1288 }1289 1290 follow_info->seq[is_server] += (fragment->data->len - new_pos);1291 }1292 1293 /* Remove the fragment from the list as the "new" part of it1294 * has been processed or its data has been seen already in1295 * another packet. */1296 g_byte_array_free(fragment->data, TRUE(!(0)));1297 g_free(fragment);1298 follow_info->fragments[is_server] = g_list_delete_link(follow_info->fragments[is_server], fragment_entry);1299 return TRUE(!(0));1300 }1301 1302 if( EQ_SEQ(fragment->seq, follow_info->seq[is_server])(fragment->seq) == (follow_info->seq[is_server]) ) {1303 /* this fragment fits the stream */1304 if( fragment->data->len > 0 ) {1305 follow_info->payload = g_list_prepend(follow_info->payload, fragment);1306 }1307 1308 follow_info->seq[is_server] += fragment->data->len;1309 follow_info->fragments[is_server] = g_list_delete_link(follow_info->fragments[is_server], fragment_entry);1310 return TRUE(!(0));1311 }1312 }1313 1314 if( use_ack && GT_SEQ(acknowledged, lowest_seq)((gint32)((lowest_seq) - (acknowledged)) < 0) ) {1315 /* There are frames missing in the capture file that were seen1316 * by the receiving host. Add dummy stream chunk with the data1317 * "[xxx bytes missing in capture file]".1318 */1319 dummy_str = ws_strdup_printf("[%d bytes missing in capture file]",wmem_strdup_printf(((void*)0), "[%d bytes missing in capture file]"
, (int)(lowest_seq - follow_info->seq[is_server]))
1320 (int)(lowest_seq - follow_info->seq[is_server]) )wmem_strdup_printf(((void*)0), "[%d bytes missing in capture file]"
, (int)(lowest_seq - follow_info->seq[is_server]))
;1321 // XXX the dummy replacement could be larger than the actual missing bytes.1322 1323 follow_record = g_new0(follow_record_t,1)((follow_record_t *) g_malloc0_n ((1), sizeof (follow_record_t
)))
;1324 1325 follow_record->data = g_byte_array_append(g_byte_array_new(),1326 (guchar*)dummy_str,1327 (guint)strlen(dummy_str)+1);1328 g_free(dummy_str);1329 follow_record->is_server = is_server;1330 follow_record->packet_num = packet_num;1331 follow_record->seq = lowest_seq;1332 1333 follow_info->seq[is_server] = lowest_seq;1334 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);1335 return TRUE(!(0));1336 }1337 1338 return FALSE(0);1339}1340 1341static tap_packet_status1342follow_tcp_tap_listener(void *tapdata, packet_info *pinfo,1343 epan_dissect_t *edt _U___attribute__((unused)), const void *data, tap_flags_t flags _U___attribute__((unused)))1344{1345 follow_record_t *follow_record;1346 follow_info_t *follow_info = (follow_info_t *)tapdata;1347 const tcp_follow_tap_data_t *follow_data = (const tcp_follow_tap_data_t *)data;1348 gboolean is_server;1349 guint32 sequence = follow_data->tcph->th_seq;1350 guint32 length = follow_data->tcph->th_have_seglen1351 ? follow_data->tcph->th_seglen1352 : 0;1353 guint32 data_offset = 0;1354 guint32 data_length = tvb_captured_length(follow_data->tvb);1355 1356 if (follow_data->tcph->th_flags & TH_SYN0x0002) {1357 sequence++;1358 }1359 1360 if (follow_info->client_port == 0) {1361 follow_info->client_port = pinfo->srcport;1362 copy_address(&follow_info->client_ip, &pinfo->src);1363 follow_info->server_port = pinfo->destport;1364 copy_address(&follow_info->server_ip, &pinfo->dst);1365 }1366 1367 is_server = !(addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport);1368 1369 /* Check whether this frame ACKs fragments in flow from the other direction.1370 * This happens when frames are not in the capture file, but were actually1371 * seen by the receiving host (Fixes bug 592).1372 */1373 if (follow_info->fragments[!is_server] != NULL((void*)0)) {1374 while (check_follow_fragments(follow_info, !is_server, follow_data->tcph->th_ack, pinfo->fd->num, TRUE(!(0))));1375 }1376 1377 /*1378 * If this is the first segment of this stream, initialize the next expected1379 * sequence number. If there is any data, it will be added below.1380 */1381 if (follow_info->bytes_written[is_server] == 0 && follow_info->seq[is_server] == 0) {1382 follow_info->seq[is_server] = sequence;1383 }1384 1385 /* We have already seen this src (and received some segments), let's figure1386 * out whether this segment extends the stream or overlaps a previous gap. */1387 if (LT_SEQ(sequence, follow_info->seq[is_server])((gint32)((sequence) - (follow_info->seq[is_server])) <
0)
) {1388 /* This sequence number seems dated, but check the end in case it was a1389 * retransmission with more data. */1390 guint32 nextseq = sequence + length;1391 if (GT_SEQ(nextseq, follow_info->seq[is_server])((gint32)((follow_info->seq[is_server]) - (nextseq)) < 0
)
) {1392 /* The begin of the segment was already seen, try to add the1393 * remaining data that we have not seen to the payload. */1394 data_offset = follow_info->seq[is_server] - sequence;1395 if (data_length <= data_offset) {1396 data_length = 0;1397 } else {1398 data_length -= data_offset;1399 }1400 1401 sequence = follow_info->seq[is_server];1402 length = nextseq - follow_info->seq[is_server];1403 }1404 }1405 /*1406 * Ignore segments that have no new data (either because it was empty, or1407 * because it was fully overlapping with previously received data).1408 */1409 if (data_length == 0 || LT_SEQ(sequence, follow_info->seq[is_server])((gint32)((sequence) - (follow_info->seq[is_server])) <
0)
) {1410 return TAP_PACKET_DONT_REDRAW;1411 }1412 1413 follow_record = g_new0(follow_record_t, 1)((follow_record_t *) g_malloc0_n ((1), sizeof (follow_record_t
)))
;1414 follow_record->is_server = is_server;1415 follow_record->packet_num = pinfo->fd->num;1416 follow_record->abs_ts = pinfo->fd->abs_ts;1417 follow_record->seq = sequence; /* start of fragment, used by check_follow_fragments. */1418 follow_record->data = g_byte_array_append(g_byte_array_new(),1419 tvb_get_ptr(follow_data->tvb, data_offset, data_length),1420 data_length);1421 1422 if (EQ_SEQ(sequence, follow_info->seq[is_server])(sequence) == (follow_info->seq[is_server])) {1423 /* The segment overlaps or extends the previous end of stream. */1424 follow_info->seq[is_server] += length;1425 follow_info->bytes_written[is_server] += follow_record->data->len;1426 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);1427 1428 /* done with the packet, see if it caused a fragment to fit */1429 while(check_follow_fragments(follow_info, is_server, 0, pinfo->fd->num, FALSE(0)));1430 } else {1431 /* Out of order packet (more preceding segments are expected). */1432 follow_info->fragments[is_server] = g_list_append(follow_info->fragments[is_server], follow_record);1433 }1434 return TAP_PACKET_DONT_REDRAW;1435}1436 1437#define EXP_PDU_TCP_INFO_DATA_LEN19 191438#define EXP_PDU_TCP_INFO_VERSION1 11439 1440static int exp_pdu_tcp_dissector_data_size(packet_info *pinfo _U___attribute__((unused)), void* data _U___attribute__((unused)))1441{1442 return EXP_PDU_TCP_INFO_DATA_LEN19+4;1443}1444 1445static int exp_pdu_tcp_dissector_data_populate_data(packet_info *pinfo _U___attribute__((unused)), void* data, guint8 *tlv_buffer, guint32 buffer_size _U___attribute__((unused)))1446{1447 struct tcpinfo* dissector_data = (struct tcpinfo*)data;1448 1449 phton16(&tlv_buffer[0], EXP_PDU_TAG_TCP_INFO_DATA34);1450 phton16(&tlv_buffer[2], EXP_PDU_TCP_INFO_DATA_LEN19); /* tag length */1451 phton16(&tlv_buffer[4], EXP_PDU_TCP_INFO_VERSION1);1452 phton32(&tlv_buffer[6], dissector_data->seq);1453 phton32(&tlv_buffer[10], dissector_data->nxtseq);1454 phton32(&tlv_buffer[14], dissector_data->lastackseq);1455 tlv_buffer[18] = dissector_data->is_reassembled;1456 phton16(&tlv_buffer[19], dissector_data->flags);1457 phton16(&tlv_buffer[21], dissector_data->urgent_pointer);1458 1459 return exp_pdu_tcp_dissector_data_size(pinfo, data);1460}1461 1462static tvbuff_t*1463handle_export_pdu_check_desegmentation(packet_info *pinfo, tvbuff_t *tvb)1464{1465 /* Check to see if the tvb we're planning on exporting PDUs from was1466 * dissected fully, or whether it requested further desegmentation.1467 * This should only matter on the first pass (so in one-pass tshark.)1468 */1469 if (pinfo->can_desegment > 0 && pinfo->desegment_len != 0) {1470 /* Desegmentation was requested. How much did we desegment here?1471 * The rest, presumably, will be handled in another frame.1472 */1473 if (pinfo->desegment_offset == 0) {1474 /* We couldn't, in fact, dissect any of it. */1475 return NULL((void*)0);1476 }1477 tvb = tvb_new_subset_length(tvb, 0, pinfo->desegment_offset);1478 }1479 return tvb;1480}1481 1482static void1483handle_export_pdu_dissection_table(packet_info *pinfo, tvbuff_t *tvb, guint32 port, struct tcpinfo *tcpinfo)1484{1485 if (have_tap_listener(exported_pdu_tap)) {1486 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);1487 if (tvb == NULL((void*)0)) {1488 return;1489 }1490 exp_pdu_data_item_t exp_pdu_data_table_value = {exp_pdu_data_dissector_table_num_value_size, exp_pdu_data_dissector_table_num_value_populate_data, NULL((void*)0)};1491 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL((void*)0)};1492 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {1493 &exp_pdu_data_src_ip,1494 &exp_pdu_data_dst_ip,1495 &exp_pdu_data_port_type,1496 &exp_pdu_data_src_port,1497 &exp_pdu_data_dst_port,1498 &exp_pdu_data_orig_frame_num,1499 &exp_pdu_data_table_value,1500 &exp_pdu_data_dissector_data,1501 NULL((void*)0)1502 };1503 1504 exp_pdu_data_t *exp_pdu_data;1505 1506 exp_pdu_data_table_value.data = GUINT_TO_POINTER(port)((gpointer) (gulong) (port));1507 exp_pdu_data_dissector_data.data = tcpinfo;1508 1509 exp_pdu_data = export_pdu_create_tags(pinfo, "tcp.port", EXP_PDU_TAG_DISSECTOR_TABLE_NAME14, tcp_exp_pdu_items);1510 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);1511 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);1512 exp_pdu_data->pdu_tvb = tvb;1513 1514 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);1515 }1516}1517 1518static void1519handle_export_pdu_heuristic(packet_info *pinfo, tvbuff_t *tvb, heur_dtbl_entry_t *hdtbl_entry, struct tcpinfo *tcpinfo)1520{1521 exp_pdu_data_t *exp_pdu_data = NULL((void*)0);1522 1523 if (have_tap_listener(exported_pdu_tap)) {1524 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);1525 if (tvb == NULL((void*)0)) {1526 return;1527 }1528 if ((!hdtbl_entry->enabled) ||1529 (hdtbl_entry->protocol != NULL((void*)0) && !proto_is_protocol_enabled(hdtbl_entry->protocol))) {1530 exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME12);1531 } else if (hdtbl_entry->protocol != NULL((void*)0)) {1532 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL((void*)0)};1533 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {1534 &exp_pdu_data_src_ip,1535 &exp_pdu_data_dst_ip,1536 &exp_pdu_data_port_type,1537 &exp_pdu_data_src_port,1538 &exp_pdu_data_dst_port,1539 &exp_pdu_data_orig_frame_num,1540 &exp_pdu_data_dissector_data,1541 NULL((void*)0)1542 };1543 1544 exp_pdu_data_dissector_data.data = tcpinfo;1545 1546 exp_pdu_data = export_pdu_create_tags(pinfo, hdtbl_entry->short_name, EXP_PDU_TAG_HEUR_DISSECTOR_NAME13, tcp_exp_pdu_items);1547 }1548 1549 if (exp_pdu_data != NULL((void*)0)) {1550 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);1551 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);1552 exp_pdu_data->pdu_tvb = tvb;1553 1554 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);1555 }1556 }1557}1558 1559static void1560handle_export_pdu_conversation(packet_info *pinfo, tvbuff_t *tvb, int src_port, int dst_port, struct tcpinfo *tcpinfo)1561{1562 if (have_tap_listener(exported_pdu_tap)) {1563 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);1564 if (tvb == NULL((void*)0)) {1565 return;1566 }1567 conversation_t *conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, src_port, dst_port, 0);1568 if (conversation != NULL((void*)0))1569 {1570 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num);1571 if (handle != NULL((void*)0))1572 {1573 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL((void*)0)};1574 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {1575 &exp_pdu_data_src_ip,1576 &exp_pdu_data_dst_ip,1577 &exp_pdu_data_port_type,1578 &exp_pdu_data_src_port,1579 &exp_pdu_data_dst_port,1580 &exp_pdu_data_orig_frame_num,1581 &exp_pdu_data_dissector_data,1582 NULL((void*)0)1583 };1584 1585 exp_pdu_data_t *exp_pdu_data;1586 1587 exp_pdu_data_dissector_data.data = tcpinfo;1588 1589 exp_pdu_data = export_pdu_create_tags(pinfo, dissector_handle_get_dissector_name(handle), EXP_PDU_TAG_DISSECTOR_NAME12, tcp_exp_pdu_items);1590 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);1591 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);1592 exp_pdu_data->pdu_tvb = tvb;1593 1594 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);1595 }1596 }1597 }1598}1599 1600/*1601 * display the TCP Conversation Completeness1602 * we of course pay much attention on complete conversations but also incomplete ones which1603 * have a regular start, as in practice we are often looking for such thing1604 */1605static void conversation_completeness_fill(gchar *buf, guint32 value)1606{1607 switch(value) {1608 case TCP_COMPLETENESS_SYNSENT0x01:1609 snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete, SYN_SENT (%u)", value);1610 break;1611 case (TCP_COMPLETENESS_SYNSENT0x01|1612 TCP_COMPLETENESS_SYNACK0x02):1613 snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete, CLIENT_ESTABLISHED (%u)", value);1614 break;1615 case (TCP_COMPLETENESS_SYNSENT0x01|1616 TCP_COMPLETENESS_SYNACK0x02|1617 TCP_COMPLETENESS_ACK0x04):1618 snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete, ESTABLISHED (%u)", value);1619 break;1620 case (TCP_COMPLETENESS_SYNSENT0x01|1621 TCP_COMPLETENESS_SYNACK0x02|1622 TCP_COMPLETENESS_ACK0x04|1623 TCP_COMPLETENESS_DATA0x08):1624 snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete, DATA (%u)", value);1625 break;1626 case (TCP_COMPLETENESS_SYNSENT0x01|1627 TCP_COMPLETENESS_SYNACK0x02|1628 TCP_COMPLETENESS_ACK0x04|1629 TCP_COMPLETENESS_DATA0x08|1630 TCP_COMPLETENESS_FIN0x10):1631 case (TCP_COMPLETENESS_SYNSENT0x01|1632 TCP_COMPLETENESS_SYNACK0x02|1633 TCP_COMPLETENESS_ACK0x04|1634 TCP_COMPLETENESS_DATA0x08|1635 TCP_COMPLETENESS_RST0x20):1636 case (TCP_COMPLETENESS_SYNSENT0x01|1637 TCP_COMPLETENESS_SYNACK0x02|1638 TCP_COMPLETENESS_ACK0x04|1639 TCP_COMPLETENESS_DATA0x08|1640 TCP_COMPLETENESS_FIN0x10|1641 TCP_COMPLETENESS_RST0x20):1642 snprintf(buf, ITEM_LABEL_LENGTH240, "Complete, WITH_DATA (%u)", value);1643 break;1644 case (TCP_COMPLETENESS_SYNSENT0x01|1645 TCP_COMPLETENESS_SYNACK0x02|1646 TCP_COMPLETENESS_ACK0x04|1647 TCP_COMPLETENESS_FIN0x10):1648 case (TCP_COMPLETENESS_SYNSENT0x01|1649 TCP_COMPLETENESS_SYNACK0x02|1650 TCP_COMPLETENESS_ACK0x04|1651 TCP_COMPLETENESS_RST0x20):1652 case (TCP_COMPLETENESS_SYNSENT0x01|1653 TCP_COMPLETENESS_SYNACK0x02|1654 TCP_COMPLETENESS_ACK0x04|1655 TCP_COMPLETENESS_FIN0x10|1656 TCP_COMPLETENESS_RST0x20):1657 snprintf(buf, ITEM_LABEL_LENGTH240, "Complete, NO_DATA (%u)", value);1658 break;1659 default:1660 snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete (%u)", value);1661 break;1662 }1663}1664 1665/* TCP structs and definitions */1666 1667/* **************************************************************************1668 * RTT, relative sequence numbers, window scaling & etc.1669 * **************************************************************************/1670static bool_Bool tcp_analyze_seq = true1;1671static bool_Bool tcp_relative_seq = true1;1672static bool_Bool tcp_track_bytes_in_flight = true1;1673static bool_Bool tcp_bif_seq_based;1674static bool_Bool tcp_calculate_ts = true1;1675 1676static bool_Bool tcp_analyze_mptcp = true1;1677static bool_Bool mptcp_relative_seq = true1;1678static bool_Bool mptcp_analyze_mappings;1679static bool_Bool mptcp_intersubflows_retransmission;1680 1681 1682#define TCP_A_RETRANSMISSION0x0001 0x00011683#define TCP_A_LOST_PACKET0x0002 0x00021684#define TCP_A_ACK_LOST_PACKET0x0004 0x00041685#define TCP_A_KEEP_ALIVE0x0008 0x00081686#define TCP_A_DUPLICATE_ACK0x0010 0x00101687#define TCP_A_ZERO_WINDOW0x0020 0x00201688#define TCP_A_ZERO_WINDOW_PROBE0x0040 0x00401689#define TCP_A_ZERO_WINDOW_PROBE_ACK0x0080 0x00801690#define TCP_A_KEEP_ALIVE_ACK0x0100 0x01001691#define TCP_A_OUT_OF_ORDER0x0200 0x02001692#define TCP_A_FAST_RETRANSMISSION0x0400 0x04001693#define TCP_A_WINDOW_UPDATE0x0800 0x08001694#define TCP_A_WINDOW_FULL0x1000 0x10001695#define TCP_A_REUSED_PORTS0x2000 0x20001696#define TCP_A_SPURIOUS_RETRANSMISSION0x4000 0x40001697 1698/* This flag for desegment_tcp to exclude segments with previously1699 * seen sequence numbers.1700 * It is from the perspective of Wireshark's reassembler, whereas1701 * the other flags above are from the perspective of the sender.1702 * (E.g., TCP_A_RETRANSMISSION or TCP_A_SPURIOUS_RETRANSMISSION1703 * can be set even when first appearance in the capture file.)1704 */1705#define TCP_A_OLD_DATA0x8000 0x80001706 1707/* Static TCP flags. Set in tcp_flow_t:static_flags */1708#define TCP_S_BASE_SEQ_SET0x01 0x011709#define TCP_S_SAW_SYN0x03 0x031710#define TCP_S_SAW_SYNACK0x05 0x051711 1712 1713/* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */1714#define MPTCP_META_HAS_BASE_DSN_MSB0x01 0x011715#define MPTCP_META_HAS_KEY0x03 0x031716#define MPTCP_META_HAS_TOKEN0x04 0x041717#define MPTCP_META_HAS_ADDRESSES0x08 0x081718 1719/* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */1720#define MPTCP_SUBFLOW_HAS_NONCE0x01 0x011721#define MPTCP_SUBFLOW_HAS_ADDRESS_ID0x02 0x021722 1723/* MPTCP meta analysis related */1724#define MPTCP_META_CHECKSUM_REQUIRED0x0002 0x00021725 1726/* if we have no key for this connection, some conversion become impossible,1727 * thus return false1728 */1729static1730gboolean1731mptcp_convert_dsn(guint64 dsn, mptcp_meta_flow_t *meta, enum mptcp_dsn_conversion conv, gboolean relative, guint64 *result ) {1732 1733 *result = dsn;1734 1735 /* if relative is set then we need the 64 bits version anyway1736 * we assume no wrapping was done on the 32 lsb so this may be wrong for elephant flows1737 */1738 if(conv == DSN_CONV_32_TO_64 || relative) {1739 1740 if(!(meta->static_flags & MPTCP_META_HAS_BASE_DSN_MSB0x01)) {1741 /* can't do those without the expected_idsn based on the key */1742 return FALSE(0);1743 }1744 }1745 1746 if(conv == DSN_CONV_32_TO_64) {1747 *result = KEEP_32MSB_OF_GUINT64(meta->base_dsn) | dsn;1748 }1749 1750 if(relative) {1751 *result -= meta->base_dsn;1752 }1753 1754 if(conv == DSN_CONV_64_TO_32) {1755 *result = (guint32) *result;1756 }1757 1758 return TRUE(!(0));1759}1760 1761 1762static void1763process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,1764 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,1765 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,1766 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo);1767 1768 1769static struct tcp_analysis *1770init_tcp_conversation_data(packet_info *pinfo, int direction)1771{1772 struct tcp_analysis *tcpd;1773 1774 /* Initialize the tcp protocol data structure to add to the tcp conversation */1775 tcpd=wmem_new0(wmem_file_scope(), struct tcp_analysis)((struct tcp_analysis*)wmem_alloc0((wmem_file_scope()), sizeof
(struct tcp_analysis)))
;1776 tcpd->flow1.win_scale = (direction >= 0) ? pinfo->src_win_scale : pinfo->dst_win_scale;1777 tcpd->flow1.window = G_MAXUINT32((guint32) 0xffffffff);1778 tcpd->flow1.multisegment_pdus=wmem_tree_new(wmem_file_scope());1779 1780 tcpd->flow2.window = G_MAXUINT32((guint32) 0xffffffff);1781 tcpd->flow2.win_scale = (direction >= 0) ? pinfo->dst_win_scale : pinfo->src_win_scale;1782 tcpd->flow2.multisegment_pdus=wmem_tree_new(wmem_file_scope());1783 1784 if (tcp_reassemble_out_of_order) {1785 tcpd->flow1.ooo_segments=wmem_list_new(wmem_file_scope());1786 tcpd->flow2.ooo_segments=wmem_list_new(wmem_file_scope());1787 }1788 1789 /* Only allocate the data if its actually going to be analyzed */1790 if (tcp_analyze_seq)1791 {1792 tcpd->flow1.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t)((struct tcp_analyze_seq_flow_info_t*)wmem_alloc0((wmem_file_scope
()), sizeof(struct tcp_analyze_seq_flow_info_t)))
;1793 tcpd->flow2.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t)((struct tcp_analyze_seq_flow_info_t*)wmem_alloc0((wmem_file_scope
()), sizeof(struct tcp_analyze_seq_flow_info_t)))
;1794 }1795 /* Only allocate the data if its actually going to be displayed */1796 if (tcp_display_process_info)1797 {1798 tcpd->flow1.process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t)((struct tcp_process_info_t*)wmem_alloc0((wmem_file_scope()),
sizeof(struct tcp_process_info_t)))
;1799 tcpd->flow2.process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t)((struct tcp_process_info_t*)wmem_alloc0((wmem_file_scope()),
sizeof(struct tcp_process_info_t)))
;1800 }1801 1802 tcpd->acked_table=wmem_tree_new(wmem_file_scope());1803 tcpd->ts_first.secs=pinfo->abs_ts.secs;1804 tcpd->ts_first.nsecs=pinfo->abs_ts.nsecs;1805 nstime_set_zero(&tcpd->ts_mru_syn);1806 nstime_set_zero(&tcpd->ts_first_rtt);1807 tcpd->ts_prev.secs=pinfo->abs_ts.secs;1808 tcpd->ts_prev.nsecs=pinfo->abs_ts.nsecs;1809 tcpd->flow1.valid_bif = 1;1810 tcpd->flow2.valid_bif = 1;1811 tcpd->flow1.push_bytes_sent = 0;1812 tcpd->flow2.push_bytes_sent = 0;1813 tcpd->flow1.push_set_last = FALSE(0);1814 tcpd->flow2.push_set_last = FALSE(0);1815 tcpd->flow1.closing_initiator = FALSE(0);1816 tcpd->flow2.closing_initiator = FALSE(0);1817 tcpd->stream = tcp_stream_count++;1818 tcpd->server_port = 0;1819 tcpd->flow_direction = 0;1820 tcpd->flow1.flow_count = 0;1821 tcpd->flow2.flow_count = 0;1822 1823 return tcpd;1824}1825 1826/* setup meta as well */1827static void1828mptcp_init_subflow(tcp_flow_t *flow)1829{1830 struct mptcp_subflow *sf = wmem_new0(wmem_file_scope(), struct mptcp_subflow)((struct mptcp_subflow*)wmem_alloc0((wmem_file_scope()), sizeof
(struct mptcp_subflow)))
;1831 1832 DISSECTOR_ASSERT(flow->mptcp_subflow == 0)((void) ((flow->mptcp_subflow == 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c"
, 1832, "flow->mptcp_subflow == 0"))))
;1833 flow->mptcp_subflow = sf;1834 sf->ssn2dsn_mappings = wmem_itree_new(wmem_file_scope());1835 sf->dsn2packet_map = wmem_itree_new(wmem_file_scope());1836}1837 1838 1839/* add a new subflow to an mptcp connection */1840static void1841mptcp_attach_subflow(struct mptcp_analysis* mptcpd, struct tcp_analysis* tcpd) {1842 1843 if(!wmem_list_find(mptcpd->subflows, tcpd)) {1844 wmem_list_prepend(mptcpd->subflows, tcpd);1845 }1846 1847 /* in case we merge 2 mptcp connections */1848 tcpd->mptcp_analysis = mptcpd;1849}1850 1851struct tcp_analysis *1852get_tcp_conversation_data_idempotent(conversation_t *conv)1853{1854 struct tcp_analysis *tcpd;1855 1856 /* Get the data for this conversation */1857 tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);1858 1859 return tcpd;1860}1861 1862struct tcp_analysis *1863get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)1864{1865 int direction;1866 struct tcp_analysis *tcpd;1867 gboolean clear_ta = TRUE(!(0));1868 1869 /* Did the caller supply the conversation pointer? */1870 if( conv==NULL((void*)0) ) {1871 /* If the caller didn't supply a conversation, don't1872 * clear the analysis, it may be needed */1873 clear_ta = FALSE(0);1874 conv = find_or_create_conversation(pinfo);1875 }1876 1877 /* Get the data for this conversation */1878 tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);1879 1880 direction = cmp_address(&pinfo->src, &pinfo->dst);1881 /* if the addresses are equal, match the ports instead */1882 if (direction == 0) {1883 direction = (pinfo->srcport > pinfo->destport) ? 1 : -1;1884 }1885 /* If the conversation was just created or it matched a1886 * conversation with template options, tcpd will not1887 * have been initialized. So, initialize1888 * a new tcpd structure for the conversation.1889 */1890 if (!tcpd) {1891 tcpd = init_tcp_conversation_data(pinfo, direction);1892 conversation_add_proto_data(conv, proto_tcp, tcpd);1893 }1894 1895 if (!tcpd) {1896 return NULL((void*)0);1897 }1898 1899 /* check direction and get ua lists */1900 if(direction>=0) {1901 tcpd->fwd=&(tcpd->flow1);1902 tcpd->rev=&(tcpd->flow2);1903 } else {1904 tcpd->fwd=&(tcpd->flow2);1905 tcpd->rev=&(tcpd->flow1);1906 }1907 1908 if (clear_ta) {1909 tcpd->ta=NULL((void*)0);1910 }1911 return tcpd;1912}1913 1914/* Attach process info to a flow */1915/* XXX - We depend on the TCP dissector finding the conversation first */1916void1917add_tcp_process_info(guint32 frame_num, address *local_addr, address *remote_addr, guint16 local_port, guint16 remote_port, guint32 uid, guint32 pid, gchar *username, gchar *command) {1918 conversation_t *conv;1919 struct tcp_analysis *tcpd;1920 tcp_flow_t *flow = NULL((void*)0);1921 1922 if (!tcp_display_process_info)1923 return;1924 1925 conv = find_conversation(frame_num, local_addr, remote_addr, CONVERSATION_TCP, local_port, remote_port, 0);1926 if (!conv) {1927 return;1928 }1929 1930 tcpd = (struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);1931 if (!tcpd) {1932 return;1933 }1934 1935 if (cmp_address(local_addr, conversation_key_addr1(conv->key_ptr)) == 0 && local_port == conversation_key_port1(conv->key_ptr)) {1936 flow = &tcpd->flow1;1937 } else if (cmp_address(remote_addr, conversation_key_addr1(conv->key_ptr)) == 0 && remote_port == conversation_key_port1(conv->key_ptr)) {1938 flow = &tcpd->flow2;1939 }1940 if (!flow || (flow->process_info && flow->process_info->command)) {1941 return;1942 }1943 1944 if (flow->process_info == NULL((void*)0))1945 flow->process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t)((struct tcp_process_info_t*)wmem_alloc0((wmem_file_scope()),
sizeof(struct tcp_process_info_t)))
;1946 1947 flow->process_info->process_uid = uid;1948 flow->process_info->process_pid = pid;1949 flow->process_info->username = wmem_strdup(wmem_file_scope(), username);1950 flow->process_info->command = wmem_strdup(wmem_file_scope(), command);1951}1952 1953/* Return the current stream count */1954guint32 get_tcp_stream_count(void)1955{1956 return tcp_stream_count;1957}1958 1959/* Return the mptcp current stream count */1960guint32 get_mptcp_stream_count(void)1961{1962 return mptcp_stream_count;1963}1964 1965/* Calculate the timestamps relative to this conversation */1966static void1967tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,1968 struct tcp_per_packet_data_t *tcppd)1969{1970 if( !tcppd ) {1971 tcppd = wmem_new(wmem_file_scope(), struct tcp_per_packet_data_t)((struct tcp_per_packet_data_t*)wmem_alloc((wmem_file_scope()
), sizeof(struct tcp_per_packet_data_t)))
;1972 p_add_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num, tcppd);1973 }1974 1975 if (!tcpd)1976 return;1977 1978 /* pre-increment so packet numbers start at 1 */1979 tcppd->pnum = ++tcpd->pnum;1980 1981 nstime_delta(&tcppd->ts_del, &pinfo->abs_ts, &tcpd->ts_prev);1982 1983 tcpd->ts_prev.secs=pinfo->abs_ts.secs;1984 tcpd->ts_prev.nsecs=pinfo->abs_ts.nsecs;1985}1986 1987/* Add a subtree with the timestamps relative to this conversation */1988static void1989tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)1990{1991 proto_item *item;1992 proto_tree *tree;1993 nstime_t ts;1994 1995 if (!tcpd)1996 return;1997 1998 tree=proto_tree_add_subtree(parent_tree, tvb, 0, 0, ett_tcp_timestamps, &item, "Timestamps");1999 proto_item_set_generated(item);2000 2001 nstime_delta(&ts, &pinfo->abs_ts, &tcpd->ts_first);2002 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);2003 proto_item_set_generated(item);2004 2005 if( !tcppd )2006 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);2007 2008 if( tcppd ) {2009 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,2010 &tcppd->ts_del);2011 proto_item_set_generated(item);2012 }2013}2014 2015static void2016print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)2017{2018 proto_item *item;2019 2020 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);2021 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,2022 tvb, 0, 0, msp->first_frame);2023 proto_item_set_generated(item);2024}2025 2026/* if we know that a PDU starts inside this segment, return the adjusted2027 offset to where that PDU starts or just return offset back2028 and let TCP try to find out what it can about this segment2029*/2030static int2031scan_for_next_pdu(tvbuff_t *tvb, proto_tree *tcp_tree, packet_info *pinfo, int offset, guint32 seq, guint32 nxtseq, wmem_tree_t *multisegment_pdus)2032{2033 struct tcp_multisegment_pdu *msp=NULL((void*)0);2034 2035 if(!pinfo->fd->visited) {2036 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);2037 if(msp) {2038 /* If this is a continuation of a PDU started in a2039 * previous segment we need to update the last_frame2040 * variables.2041 */2042 if(seq>msp->seq && seq<msp->nxtpdu) {2043 msp->last_frame=pinfo->num;2044 msp->last_frame_time=pinfo->abs_ts;2045 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);2046 }2047 2048 /* If this segment is completely within a previous PDU2049 * then we just skip this packet2050 */2051 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {2052 return -1;2053 }2054 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {2055 offset+=msp->nxtpdu-seq;2056 return offset;2057 }2058 2059 }2060 } else {2061 /* First we try to find the start and transfer time for a PDU.2062 * We only print this for the very first segment of a PDU2063 * and only for PDUs spanning multiple segments.2064 * Se we look for if there was any multisegment PDU started2065 * just BEFORE the end of this segment. I.e. either inside this2066 * segment or in a previous segment.2067 * Since this might also match PDUs that are completely within2068 * this segment we also verify that the found PDU does span2069 * beyond the end of this segment.2070 */2071 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, nxtseq-1);2072 if(msp) {2073 if(pinfo->num==msp->first_frame) {2074 proto_item *item;2075 nstime_t ns;2076 2077 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);2078 proto_item_set_generated(item);2079 2080 nstime_delta(&ns, &msp->last_frame_time, &pinfo->abs_ts);2081 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,2082 tvb, 0, 0, &ns);2083 proto_item_set_generated(item);2084 }2085 }2086 2087 /* Second we check if this segment is part of a PDU started2088 * prior to the segment (seq-1)2089 */2090 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);2091 if(msp) {2092 /* If this segment is completely within a previous PDU2093 * then we just skip this packet2094 */2095 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {2096 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);2097 return -1;2098 }2099 2100 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {2101 offset+=msp->nxtpdu-seq;2102 return offset;2103 }2104 }2105 2106 }2107 return offset;2108}2109 2110/* if we saw a PDU that extended beyond the end of the segment,2111 use this function to remember where the next pdu starts2112*/2113struct tcp_multisegment_pdu *2114pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, wmem_tree_t *multisegment_pdus)2115{2116 struct tcp_multisegment_pdu *msp;2117 2118 msp=wmem_new(wmem_file_scope(), struct tcp_multisegment_pdu)((struct tcp_multisegment_pdu*)wmem_alloc((wmem_file_scope())
, sizeof(struct tcp_multisegment_pdu)))
;2119 msp->nxtpdu=nxtpdu;2120 msp->seq=seq;2121 msp->first_frame=pinfo->num;2122 msp->first_frame_with_seq=pinfo->num;2123 msp->last_frame=pinfo->num;2124 msp->last_frame_time=pinfo->abs_ts;2125 msp->flags=0;2126 wmem_tree_insert32(multisegment_pdus, seq, (void *)msp);2127 /*ws_warning("pdu_store_sequencenumber_of_next_pdu: seq %u", seq);*/2128 return msp;2129}2130 2131/* This is called for SYN and SYN+ACK packets and the purpose is to verify2132 * that we have seen window scaling in both directions.2133 * If we can't find window scaling being set in both directions2134 * that means it was present in the SYN but not in the SYN+ACK2135 * (or the SYN was missing) and then we disable the window scaling2136 * for this tcp session.2137 */2138static void2139verify_tcp_window_scaling(gboolean is_synack, struct tcp_analysis *tcpd)2140{2141 if( tcpd->fwd->win_scale==-1 ) {2142 /* We know window scaling will not be used as:2143 * a) this is the SYN and it does not have the WS option2144 * (we set the reverse win_scale also in case we miss2145 * the SYN/ACK)2146 * b) this is the SYN/ACK and either the SYN packet has not2147 * been seen or it did have the WS option. As the SYN/ACK2148 * does not have the WS option, window scaling will not be used.2149 *2150 * Setting win_scale to -2 to indicate that we can2151 * trust the window_size value in the TCP header.2152 */2153 tcpd->fwd->win_scale = -2;2154 tcpd->rev->win_scale = -2;2155 2156 } else if( is_synack && tcpd->rev->win_scale==-2 ) {2157 /* The SYN/ACK has the WS option, while the SYN did not,2158 * this should not happen, but the endpoints will not2159 * have used window scaling, so we will neither2160 */2161 tcpd->fwd->win_scale = -2;2162 }2163}2164 2165/* given a tcpd, returns the mptcp_subflow that sides with meta */2166static struct mptcp_subflow *2167mptcp_select_subflow_from_meta(const struct tcp_analysis *tcpd, const mptcp_meta_flow_t *meta)2168{2169 /* select the tcp_flow with appropriate direction */2170 if( tcpd->flow1.mptcp_subflow->meta == meta) {2171 return tcpd->flow1.mptcp_subflow;2172 }2173 else {2174 return tcpd->flow2.mptcp_subflow;2175 }2176}2177 2178/* if we saw a window scaling option, store it for future reference2179*/2180static void2181pdu_store_window_scale_option(guint8 ws, struct tcp_analysis *tcpd)2182{2183 if (tcpd)2184 tcpd->fwd->win_scale=ws;2185}2186 2187/* when this function returns, it will (if createflag) populate the ta pointer.2188 */2189static void2190tcp_analyze_get_acked_struct(guint32 frame, guint32 seq, guint32 ack, gboolean createflag, struct tcp_analysis *tcpd)2191{2192 2193 wmem_tree_key_t key[4];2194 2195 key[0].length = 1;2196 key[0].key = &frame;2197 2198 key[1].length = 1;2199 key[1].key = &seq;2200 2201 key[2].length = 1;2202 key[2].key = &ack;2203 2204 key[3].length = 0;2205 key[3].key = NULL((void*)0);2206 2207 if (!tcpd) {2208 return;2209 }2210 2211 tcpd->ta = (struct tcp_acked *)wmem_tree_lookup32_array(tcpd->acked_table, key);2212 if((!tcpd->ta) && createflag) {2213 tcpd->ta = wmem_new0(wmem_file_scope(), struct tcp_acked)((struct tcp_acked*)wmem_alloc0((wmem_file_scope()), sizeof(struct
tcp_acked)))
;2214 wmem_tree_insert32_array(tcpd->acked_table, key, (void *)tcpd->ta);2215 }2216}2217 2218 2219 2220/* fwd contains a list of all segments processed but not yet ACKed in the2221 * same direction as the current segment.2222 * rev contains a list of all segments received but not yet ACKed in the2223 * opposite direction to the current segment.2224 *2225 * New segments are always added to the head of the fwd/rev lists.2226 *2227 * Changes below should be synced with ChAdvTCPAnalysis in the User's2228 * Guide: docbook/wsug_src/WSUG_chapter_advanced.adoc2229 */2230static void2231tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint16 flags, guint32 window, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)2232{2233 tcp_unacked_t *ual=NULL((void*)0);2234 tcp_unacked_t *prevual=NULL((void*)0);2235 guint32 nextseq;2236 2237#if 02238 printf("\nanalyze_sequence numbers frame:%u\n",pinfo->num);2239 printf("FWD list lastflags:0x%04x base_seq:%u: nextseq:%u lastack:%u\n",tcpd->fwd->lastsegmentflags,tcpd->fwd->base_seq,tcpd->fwd->tcp_analyze_seq_info->nextseq,tcpd->rev->tcp_analyze_seq_info->lastack);2240 for(ual=tcpd->fwd->tcp_analyze_seq_info->segments; ual; ual=ual->next)2241 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);2242 printf("REV list lastflags:0x%04x base_seq:%u nextseq:%u lastack:%u\n",tcpd->rev->lastsegmentflags,tcpd->rev->base_seq,tcpd->rev->tcp_analyze_seq_info->nextseq,tcpd->fwd->tcp_analyze_seq_info->lastack);2243 for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next)2244 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);2245#endif2246 2247 if (!tcpd) {2248 return;2249 }2250 2251 if( flags & TH_ACK0x0010 ) {2252 tcpd->rev->valid_bif = 1;2253 }2254 2255 /* ZERO WINDOW PROBE2256 * it is a zero window probe if2257 * the sequence number is the next expected one2258 * the window in the other direction is 02259 * the segment is exactly 1 byte2260 */2261 if( seglen==12262 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq2263 && tcpd->rev->window==0 ) {2264 if(!tcpd->ta) {2265 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2266 }2267 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE0x0040;2268 goto finished_fwd;2269 }2270 2271 2272 /* ZERO WINDOW2273 * a zero window packet has window == 0 but none of the SYN/FIN/RST set2274 */2275 if( window==02276 && (flags&(TH_RST0x0004|TH_FIN0x0001|TH_SYN0x0002))==0 ) {2277 if(!tcpd->ta) {2278 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2279 }2280 tcpd->ta->flags|=TCP_A_ZERO_WINDOW0x0020;2281 }2282 2283 2284 /* LOST PACKET2285 * If this segment is beyond the last seen nextseq we must2286 * have missed some previous segment2287 *2288 * We only check for this if we have actually seen segments prior to this2289 * one.2290 * RST packets are not checked for this.2291 */2292 if( tcpd->fwd->tcp_analyze_seq_info->nextseq2293 && GT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq)((gint32)((tcpd->fwd->tcp_analyze_seq_info->nextseq)
- (seq)) < 0)
2294 && (flags&(TH_RST0x0004))==0 ) {2295 if(!tcpd->ta) {2296 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2297 }2298 tcpd->ta->flags|=TCP_A_LOST_PACKET0x0002;2299 2300 /* Disable BiF until an ACK is seen in the other direction */2301 tcpd->fwd->valid_bif = 0;2302 }2303 2304 2305 /* KEEP ALIVE2306 * a keepalive contains 0 or 1 bytes of data and starts one byte prior2307 * to what should be the next sequence number.2308 * SYN/FIN/RST segments are never keepalives2309 */2310 if( (seglen==0||seglen==1)2311 && seq==(tcpd->fwd->tcp_analyze_seq_info->nextseq-1)2312 && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) {2313 if(!tcpd->ta) {2314 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2315 }2316 tcpd->ta->flags|=TCP_A_KEEP_ALIVE0x0008;2317 }2318 2319 /* WINDOW UPDATE2320 * A window update is a 0 byte segment with the same SEQ/ACK numbers as2321 * the previous seen segment and with a new window value2322 */2323 if( seglen==02324 && window2325 && window!=tcpd->fwd->window2326 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq2327 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack2328 && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) {2329 if(!tcpd->ta) {2330 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2331 }2332 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE0x0800;2333 }2334 2335 2336 /* WINDOW FULL2337 * If we know the window scaling2338 * and if this segment contains data and goes all the way to the2339 * edge of the advertised window2340 * then we mark it as WINDOW FULL2341 * SYN/RST/FIN packets are never WINDOW FULL2342 */2343 if( seglen>02344 && tcpd->rev->win_scale!=-12345 && (seq+seglen)==(tcpd->rev->tcp_analyze_seq_info->lastack+(tcpd->rev->window<<(tcpd->rev->is_first_ack?0:(tcpd->rev->win_scale==-2?0:tcpd->rev->win_scale))))2346 && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) {2347 if(!tcpd->ta) {2348 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2349 }2350 tcpd->ta->flags|=TCP_A_WINDOW_FULL0x1000;2351 }2352 2353 2354 /* KEEP ALIVE ACK2355 * It is a keepalive ack if it repeats the previous ACK and if2356 * the last segment in the reverse direction was a keepalive2357 */2358 if( seglen==02359 && window2360 && window==tcpd->fwd->window2361 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq2362 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack2363 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE0x0008)2364 && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) {2365 if(!tcpd->ta) {2366 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2367 }2368 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK0x0100;2369 goto finished_fwd;2370 }2371 2372 2373 /* ZERO WINDOW PROBE ACK2374 * It is a zerowindowprobe ack if it repeats the previous ACK and if2375 * the last segment in the reverse direction was a zerowindowprobe2376 * It also repeats the previous zero window indication2377 */2378 if( seglen==02379 && window==02380 && window==tcpd->fwd->window2381 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq2382 && (ack==tcpd->fwd->tcp_analyze_seq_info->lastack || EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)(ack) == (tcpd->fwd->tcp_analyze_seq_info->lastack+1
)
)2383 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE0x0040)2384 && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) {2385 if(!tcpd->ta) {2386 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2387 }2388 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK0x0080;2389 2390 /* Some receivers consume that extra byte brought in the PROBE,2391 * but it was too early to know that during the WINDOW PROBE analysis.2392 * Do it now by moving the rev nextseq & maxseqtobeacked.2393 * See issue 10745.2394 */2395 if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)(ack) == (tcpd->fwd->tcp_analyze_seq_info->lastack+1
)
) {2396 tcpd->rev->tcp_analyze_seq_info->nextseq=ack;2397 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;2398 }2399 goto finished_fwd;2400 }2401 2402 2403 /* DUPLICATE ACK2404 * It is a duplicate ack if window/seq/ack is the same as the previous2405 * segment and if the segment length is 02406 */2407 if( seglen==02408 && window2409 && window==tcpd->fwd->window2410 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq2411 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack2412 && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) {2413 2414 /* MPTCP tolerates duplicate acks in some circ*mstances, see RFC 8684 4. */2415 if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) {2416 /* just ignore this DUPLICATE ACK */2417 } else {2418 tcpd->fwd->tcp_analyze_seq_info->dupacknum++;2419 2420 if(!tcpd->ta) {2421 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2422 }2423 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK0x0010;2424 tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum;2425 tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack;2426 }2427 }2428 2429 2430 2431finished_fwd:2432 /* If the ack number changed we must reset the dupack counters */2433 if( ack != tcpd->fwd->tcp_analyze_seq_info->lastack ) {2434 tcpd->fwd->tcp_analyze_seq_info->lastnondupack=pinfo->num;2435 tcpd->fwd->tcp_analyze_seq_info->dupacknum=0;2436 }2437 2438 2439 /* ACKED LOST PACKET2440 * If this segment acks beyond the 'max seq to be acked' in the other direction2441 * then that means we have missed packets going in the2442 * other direction.2443 * It might also indicate we are resuming from a Zero Window,2444 * where a Probe is just followed by an ACK opening again the window.2445 * See issue 8404.2446 *2447 * We only check this if we have actually seen some seq numbers2448 * in the other direction.2449 */2450 if( tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked2451 && GT_SEQ(ack, tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked )((gint32)((tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked
) - (ack)) < 0)
2452 && (flags&(TH_ACK0x0010))!=0 ) {2453 if(!tcpd->ta) {2454 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2455 }2456 2457 /* resuming from a Zero Window Probe which re-opens the window,2458 * mark it as a Window Update2459 */2460 if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)(ack) == (tcpd->fwd->tcp_analyze_seq_info->lastack+1
)
2461 && (seq==tcpd->fwd->tcp_analyze_seq_info->nextseq)2462 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE0x0040) ) {2463 tcpd->rev->tcp_analyze_seq_info->nextseq=ack;2464 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;2465 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE0x0800;2466 }2467 /* real ACKED LOST PACKET */2468 else {2469 /* We ensure there is no matching packet waiting in the unacked list,2470 * and take this opportunity to push the tail further than this single packet2471 */2472 2473 guint32 tail_le = 0, tail_re = 0;2474 for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next) {2475 2476 if(tail_le == tail_re) { /* init edge values */2477 tail_le = ual->seq;2478 tail_re = ual->nextseq;2479 }2480 2481 /* Only look at what happens above the current ACK value,2482 * as what happened before is definetely ACKed here and can be2483 * safely ignored. */2484 if(GE_SEQ(ual->seq,ack)((gint32)((ack) - (ual->seq)) <= 0)) {2485 2486 /* if the left edge is contiguous, move the tail leftward */2487 if(EQ_SEQ(ual->nextseq,tail_le)(ual->nextseq) == (tail_le)) {2488 tail_le = ual->seq;2489 }2490 2491 /* otherwise, we have isolated segments above what is being ACKed here,2492 * and we reinit the tails with the current values */2493 else {2494 tail_le = ual->seq;2495 tail_re = ual->nextseq; // move the end tail2496 }2497 }2498 }2499 2500 /* a tail was found and we can push the maxseqtobeacked further */2501 if(EQ_SEQ(ack,tail_le)(ack) == (tail_le) && GT_SEQ(tail_re, ack)((gint32)((ack) - (tail_re)) < 0)) {2502 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=tail_re;2503 }2504 2505 /* otherwise, just take into account the value being ACKed now */2506 else {2507 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;2508 }2509 2510 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET0x0004;2511 }2512 }2513 2514 2515 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER2516 * If the segment contains data (or is a SYN or a FIN) and2517 * if it does not advance the sequence number, it must be one2518 * of these three.2519 * Only test for this if we know what the seq number should be2520 * (tcpd->fwd->nextseq)2521 *2522 * Note that a simple KeepAlive is not a retransmission2523 */2524 if (seglen>0 || flags&(TH_SYN0x0002|TH_FIN0x0001)) {2525 gboolean seq_not_advanced = tcpd->fwd->tcp_analyze_seq_info->nextseq2526 && (LT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq)((gint32)((seq) - (tcpd->fwd->tcp_analyze_seq_info->
nextseq)) < 0)
);2527 2528 guint64 t;2529 guint64 ooo_thres;2530 2531 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE0x0008) ) {2532 goto finished_checking_retransmission_type;2533 }2534 2535 /* This segment is *not* considered a retransmission/out-of-order if2536 * the segment length is larger than one (it really adds new data)2537 * the sequence number is one less than the previous nextseq and2538 * (the previous segment is possibly a zero window probe)2539 *2540 * We should still try to flag Spurious Retransmissions though.2541 */2542 if (seglen > 1 && tcpd->fwd->tcp_analyze_seq_info->nextseq - 1 == seq) {2543 seq_not_advanced = FALSE(0);2544 }2545 2546 /* Check for spurious retransmission. If the current seq + segment length2547 * is less than or equal to the current lastack, the packet contains2548 * duplicate data and may be considered spurious.2549 */2550 if ( seglen > 02551 && tcpd->rev->tcp_analyze_seq_info->lastack2552 && LE_SEQ(seq + seglen, tcpd->rev->tcp_analyze_seq_info->lastack)((gint32)((seq + seglen) - (tcpd->rev->tcp_analyze_seq_info
->lastack)) <= 0)
) {2553 if(!tcpd->ta){2554 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2555 }2556 tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION0x4000;2557 goto finished_checking_retransmission_type;2558 }2559 2560 nextseq = seq+seglen;2561 2562 gboolean precedence_count = tcp_fastrt_precedence;2563 do {2564 switch(precedence_count) {2565 case TRUE(!(0)):2566 /* If there were >=2 duplicate ACKs in the reverse direction2567 * (there might be duplicate acks missing from the trace)2568 * and if this sequence number matches those ACKs2569 * and if the packet occurs within 20ms of the last2570 * duplicate ack2571 * then this is a fast retransmission2572 */2573 t=(pinfo->abs_ts.secs-tcpd->rev->tcp_analyze_seq_info->lastacktime.secs)*1000000000;2574 t=t+(pinfo->abs_ts.nsecs)-tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs;2575 if( seq_not_advanced2576 && tcpd->rev->tcp_analyze_seq_info->dupacknum>=22577 && tcpd->rev->tcp_analyze_seq_info->lastack==seq2578 && t<20000000 ) {2579 if(!tcpd->ta) {2580 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2581 }2582 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION0x0400;2583 goto finished_checking_retransmission_type;2584 }2585 2586 /* Look for this segment in reported SACK ranges,2587 * if not present this might very well be a FAST Retrans,2588 * when the conditions above (timing, number of retrans) are still true */2589 if( seq_not_advanced2590 && t<200000002591 && tcpd->rev->tcp_analyze_seq_info->dupacknum>=22592 && tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) {2593 2594 gboolean is_sacked = FALSE(0);2595 int i=0;2596 while( !is_sacked && i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges ) {2597 is_sacked = ((seq >= tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i++])2598 && (nextseq <= tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i]));2599 }2600 2601 /* fine, it's probably a Fast Retrans triggered by the SACK sender algo */2602 if(!is_sacked) {2603 if(!tcpd->ta)2604 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2605 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION0x0400;2606 goto finished_checking_retransmission_type;2607 }2608 }2609 2610 precedence_count=!precedence_count;2611 break;2612 2613 case FALSE(0):2614 /* If the segment came relatively close since the segment with the highest2615 * seen sequence number and it doesn't look like a retransmission2616 * then it is an OUT-OF-ORDER segment.2617 */2618 t=(pinfo->abs_ts.secs-tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs)*1000000000;2619 t=t+(pinfo->abs_ts.nsecs)-tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs;2620 if (tcpd->ts_first_rtt.nsecs == 0 && tcpd->ts_first_rtt.secs == 0) {2621 ooo_thres = 3000000;2622 } else {2623 ooo_thres = tcpd->ts_first_rtt.nsecs + tcpd->ts_first_rtt.secs*1000000000;2624 }2625 2626 /* If the segment is already seen and waiting to be acknowledged, ignore the2627 * Fast-Retrans/OOO debate and go ahead, as it only can be an ordinary Retrans.2628 * Fast-Retrans/Retrans are never ambiguous in the context of packets seen but2629 * this code could be moved above.2630 * See Issues 13284, 138432631 * XXX: if compared packets have different sizes, it's not handled yet2632 */2633 gboolean pk_already_seen = FALSE(0);2634 ual = tcpd->fwd->tcp_analyze_seq_info->segments;2635 while(ual) {2636 if(GE_SEQ(seq,ual->seq)((gint32)((ual->seq) - (seq)) <= 0) && LE_SEQ(seq+seglen,ual->nextseq)((gint32)((seq+seglen) - (ual->nextseq)) <= 0)) {2637 pk_already_seen = TRUE(!(0));2638 break;2639 }2640 ual=ual->next;2641 }2642 2643 if(seq_not_advanced && t < ooo_thres && !pk_already_seen) {2644 /* ordinary OOO with SEQ numbers and lengths clearly stating the situation */2645 if( tcpd->fwd->tcp_analyze_seq_info->nextseq != (seq + seglen + (flags&(TH_SYN0x0002|TH_FIN0x0001) ? 1 : 0))) {2646 if(!tcpd->ta) {2647 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2648 }2649 2650 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER0x0200;2651 goto finished_checking_retransmission_type;2652 }2653 else {2654 /* facing an OOO closing a series of disordered packets,2655 all preceded by a pure ACK. See issue 17214 */2656 if(tcpd->fwd->tcp_analyze_seq_info->lastacklen == 0) {2657 if(!tcpd->ta) {2658 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2659 }2660 2661 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER0x0200;2662 goto finished_checking_retransmission_type;2663 }2664 }2665 }2666 precedence_count=!precedence_count;2667 break;2668 }2669 } while (precedence_count!=tcp_fastrt_precedence) ;2670 2671 if (seq_not_advanced) {2672 /* Then it has to be a generic retransmission */2673 if(!tcpd->ta) {2674 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2675 }2676 tcpd->ta->flags|=TCP_A_RETRANSMISSION0x0001;2677 2678 /*2679 * worst case scenario: if we don't have better than a recent packet,2680 * use it as the reference for RTO2681 */2682 nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &tcpd->fwd->tcp_analyze_seq_info->nextseqtime);2683 tcpd->ta->rto_frame=tcpd->fwd->tcp_analyze_seq_info->nextseqframe;2684 2685 /*2686 * better case scenario: if we have a list of the previous unacked packets,2687 * go back to the eldest one, which in theory is likely to be the one retransmitted here.2688 * It's not always the perfect match, particularly when original captured packet used LSO2689 * We may parse this list and try to find an obvious matching packet present in the2690 * capture. If such packet is actually missing, we'll reach the list first entry.2691 * See : issue #122592692 * See : issue #177142693 */2694 ual = tcpd->fwd->tcp_analyze_seq_info->segments;2695 while(ual) {2696 if(GE_SEQ(ual->seq, seq)((gint32)((seq) - (ual->seq)) <= 0)) {2697 nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &ual->ts );2698 tcpd->ta->rto_frame=ual->frame;2699 }2700 ual=ual->next;2701 }2702 }2703 }2704 2705finished_checking_retransmission_type:2706 2707 /* Override the TCP sequence analysis with the value given2708 * manually by the user. This only applies to flagged packets.2709 */2710 if(tcppd && tcpd->ta &&2711 (tcppd->tcp_snd_manual_analysis>0) &&2712 (tcpd->ta->flags & TCP_A_RETRANSMISSION0x0001 ||2713 tcpd->ta->flags & TCP_A_OUT_OF_ORDER0x0200 ||2714 tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION0x0400 ||2715 tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION0x4000)) {2716 2717 /* clean flags set during the automatic analysis */2718 tcpd->ta->flags &= ~(TCP_A_RETRANSMISSION0x0001|2719 TCP_A_OUT_OF_ORDER0x0200|2720 TCP_A_FAST_RETRANSMISSION0x0400|2721 TCP_A_SPURIOUS_RETRANSMISSION0x4000);2722 2723 /* set the corresponding flag chosen by the user */2724 switch(tcppd->tcp_snd_manual_analysis) {2725 case 0:2726 /* the user asked for an empty overriding, which2727 * means removing any previous value, thus restoring2728 * the automatic analysis.2729 */2730 break;2731 2732 case 1:2733 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER0x0200;2734 break;2735 2736 case 2:2737 tcpd->ta->flags|=TCP_A_RETRANSMISSION0x0001;2738 break;2739 2740 case 3:2741 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION0x0400;2742 break;2743 2744 case 4:2745 tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION0x4000;2746 break;2747 2748 default:2749 /* there is no expected default case */2750 break;2751 }2752 }2753 2754 nextseq = seq+seglen;2755 if ((seglen || flags&(TH_SYN0x0002|TH_FIN0x0001)) && tcpd->fwd->tcp_analyze_seq_info->segment_count < TCP_MAX_UNACKED_SEGMENTS10000) {2756 /* Add this new sequence number to the fwd list. But only if there2757 * aren't "too many" unacked segments (e.g., we're not seeing the ACKs).2758 */2759 ual = wmem_new(wmem_file_scope(), tcp_unacked_t)((tcp_unacked_t*)wmem_alloc((wmem_file_scope()), sizeof(tcp_unacked_t
)))
;2760 ual->next=tcpd->fwd->tcp_analyze_seq_info->segments;2761 tcpd->fwd->tcp_analyze_seq_info->segments=ual;2762 tcpd->fwd->tcp_analyze_seq_info->segment_count++;2763 ual->frame=pinfo->num;2764 ual->seq=seq;2765 ual->ts=pinfo->abs_ts;2766 2767 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */2768 if( (flags&(TH_SYN0x0002|TH_FIN0x0001)) ) {2769 nextseq+=1;2770 }2771 ual->nextseq=nextseq;2772 }2773 2774 /* Every time we are moving the highest number seen,2775 * we are also tracking the segment length then we will know for sure,2776 * later, if this was a pure ACK or an ordinary data packet. */2777 if(!tcpd->fwd->tcp_analyze_seq_info->nextseq2778 || GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq + (flags&(TH_SYN|TH_FIN) ? 1 : 0))((gint32)((tcpd->fwd->tcp_analyze_seq_info->nextseq +
(flags&(0x0002|0x0001) ? 1 : 0)) - (nextseq)) < 0)
) {2779 tcpd->fwd->tcp_analyze_seq_info->lastacklen=seglen;2780 }2781 2782 /* Store the highest number seen so far for nextseq so we can detect2783 * when we receive segments that arrive with a "hole"2784 * If we don't have anything since before, just store what we got.2785 * ZeroWindowProbes are special and don't really advance the nextseq2786 */2787 if(GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq)((gint32)((tcpd->fwd->tcp_analyze_seq_info->nextseq)
- (nextseq)) < 0)
|| !tcpd->fwd->tcp_analyze_seq_info->nextseq) {2788 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE0x0040) ) {2789 tcpd->fwd->tcp_analyze_seq_info->nextseq=nextseq;2790 tcpd->fwd->tcp_analyze_seq_info->nextseqframe=pinfo->num;2791 tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs=pinfo->abs_ts.secs;2792 tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs=pinfo->abs_ts.nsecs;2793 2794 /* Count the flows turns by checking all packets carrying real data2795 * Packets not ordered are ignored.2796 */2797 if((!tcpd->ta ) ||2798 !(tcpd->ta->flags & TCP_A_RETRANSMISSION0x0001 ||2799 tcpd->ta->flags & TCP_A_OUT_OF_ORDER0x0200 ||2800 tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION0x0400 ||2801 tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION0x4000)) {2802 2803 if( seglen>0) {2804 /* check direction */2805 gint8 direction;2806 direction=cmp_address(&pinfo->src, &pinfo->dst);2807 2808 /* if the addresses are equal, match the ports instead */2809 if(direction==0) {2810 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;2811 }2812 2813 /* invert the direction and increment the counter */2814 if(direction != tcpd->flow_direction) {2815 tcpd->flow_direction = direction;2816 tcpd->fwd->flow_count++;2817 }2818 /* if the direction was not reversed, maybe are we2819 * facing the first flow ? Yes, if the counter still equals 0.2820 */2821 else {2822 if(tcpd->fwd->flow_count==0) {2823 tcpd->fwd->flow_count++;2824 }2825 }2826 }2827 }2828 }2829 }2830 2831 /* Store the highest continuous seq number seen so far for 'max seq to be acked',2832 * so we can detect TCP_A_ACK_LOST_PACKET condition.2833 * If this ever happens, this boundary value can "jump" further in order to2834 * avoid duplicating multiple messages for the very same lost packet. See later2835 * how ACKED LOST PACKET are handled.2836 * Zero Window Probes are logically left out at this moment, but if their data2837 * really were to be ack'ed, then it will be done later when analyzing their2838 * Probe ACK (be it a real Probe ACK, or an ordinary ACK moving the RCV Window).2839 */2840 if(EQ_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked)(seq) == (tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked
)
|| !tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) {2841 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE0x0040) ) {2842 tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked=tcpd->fwd->tcp_analyze_seq_info->nextseq;2843 }2844 }2845 2846 2847 /* remember what the ack/window is so we can track window updates and retransmissions */2848 tcpd->fwd->window=window;2849 tcpd->fwd->tcp_analyze_seq_info->lastack=ack;2850 tcpd->fwd->tcp_analyze_seq_info->lastacktime.secs=pinfo->abs_ts.secs;2851 tcpd->fwd->tcp_analyze_seq_info->lastacktime.nsecs=pinfo->abs_ts.nsecs;2852 2853 /* remember the MPTCP operations if any */2854 if( tcpd->mptcp_analysis ) {2855 tcpd->fwd->mp_operations=tcpd->mptcp_analysis->mp_operations;2856 }2857 2858 /* if there were any flags set for this segment we need to remember them2859 * we only remember the flags for the very last segment though.2860 */2861 if(tcpd->ta) {2862 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;2863 } else {2864 tcpd->fwd->lastsegmentflags=0;2865 }2866 2867 2868 /* remove all segments this ACKs and we don't need to keep around any more2869 */2870 prevual = NULL((void*)0);2871 ual = tcpd->rev->tcp_analyze_seq_info->segments;2872 while(ual) {2873 tcp_unacked_t *tmpual;2874 2875 /* If this ack matches the segment, process accordingly */2876 if(ack==ual->nextseq) {2877 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2878 tcpd->ta->frame_acked=ual->frame;2879 nstime_delta(&tcpd->ta->ts, &pinfo->abs_ts, &ual->ts);2880 /* mark it as a full segment ACK */2881 tcpd->ta->partial_ack=0;2882 }2883 /* If this acknowledges part of the segment, adjust the segment info for the acked part.2884 * This typically happens in the context of GSO/GRO or Retransmissions with2885 * segment repackaging (elsewhere called repacketization). For the user, looking at the2886 * previous packets for any Retransmission or at the SYN MSS Option presence would2887 * answer what case is precisely encountered.2888 */2889 else if (GT_SEQ(ack, ual->seq)((gint32)((ual->seq) - (ack)) < 0) && LE_SEQ(ack, ual->nextseq)((gint32)((ack) - (ual->nextseq)) <= 0)) {2890 ual->seq = ack;2891 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2892 tcpd->ta->frame_acked=ual->frame;2893 nstime_delta(&tcpd->ta->ts, &pinfo->abs_ts, &ual->ts);2894 2895 /* mark it as a partial segment ACK2896 *2897 * XXX - This mark is used later to create an Expert Note,2898 * but other ways of tracking these packets are possible:2899 * for example a similar indication to ta->frame_acked2900 * would help differentiating the SEQ/ACK analysis messages.2901 * Also, a TCP Analysis Flag could be added, but doesn't seem2902 * essential yet, as matching packets can be selected with2903 * 'tcp.analysis.partial_ack'.2904 */2905 tcpd->ta->partial_ack=1;2906 continue;2907 }2908 /* If this acknowledges a segment prior to this one, leave this segment alone and move on */2909 else if (GT_SEQ(ual->nextseq,ack)((gint32)((ack) - (ual->nextseq)) < 0)) {2910 prevual = ual;2911 ual = ual->next;2912 continue;2913 }2914 2915 /* This segment is old, or an exact match. Delete the segment from the list */2916 tmpual=ual->next;2917 2918 if (tcpd->rev->scps_capable) {2919 /* Track largest segment successfully sent for SNACK analysis*/2920 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) {2921 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);2922 }2923 }2924 2925 if (!prevual) {2926 tcpd->rev->tcp_analyze_seq_info->segments = tmpual;2927 }2928 else{2929 prevual->next = tmpual;2930 }2931 wmem_free(wmem_file_scope(), ual);2932 ual = tmpual;2933 tcpd->rev->tcp_analyze_seq_info->segment_count--;2934 }2935 2936 /* how many bytes of data are there in flight after this frame2937 * was sent2938 * The historical evaluation is done from the payload seen in the2939 * segments captured. Another method deduced from the SEQ numbers2940 * is introduced with issue 7703, but not used by default now. The2941 * method is chosen by the user preference tcp_bif_seq_based.2942 */2943 if(tcp_track_bytes_in_flight) {2944 guint32 in_flight, delivered = 0;2945 /*2946 * "don't repeat yourself" boolean, for the shared part2947 * between both methods2948 */2949 gboolean dry_bif_handling = FALSE(0);2950 2951 /*2952 * historical calculation method based on payloads, which is2953 * by now still the default.2954 */2955 if(!tcp_bif_seq_based) {2956 ual=tcpd->fwd->tcp_analyze_seq_info->segments;2957 2958 if (seglen!=0 && ual && tcpd->fwd->valid_bif) {2959 guint32 first_seq, last_seq;2960 2961 dry_bif_handling = TRUE(!(0));2962 2963 first_seq = ual->seq - tcpd->fwd->base_seq;2964 last_seq = ual->nextseq - tcpd->fwd->base_seq;2965 while (ual) {2966 if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) {2967 last_seq = ual->nextseq-tcpd->fwd->base_seq;2968 }2969 if ((ual->seq-tcpd->fwd->base_seq)<first_seq) {2970 first_seq = ual->seq-tcpd->fwd->base_seq;2971 }2972 ual = ual->next;2973 }2974 in_flight = last_seq-first_seq;2975 }2976 } else { /* calculation based on SEQ numbers (see issue 7703) */2977 if (seglen!=0 && tcpd->fwd->tcp_analyze_seq_info && tcpd->fwd->valid_bif) {2978 2979 dry_bif_handling = TRUE(!(0));2980 2981 in_flight = tcpd->fwd->tcp_analyze_seq_info->nextseq2982 - tcpd->rev->tcp_analyze_seq_info->lastack;2983 }2984 }2985 if(dry_bif_handling) {2986 /* subtract any SACK block */2987 if(tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) {2988 int i;2989 for(i = 0; i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges; i++) {2990 delivered += (tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i+1] -2991 tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i+1]);2992 }2993 in_flight -= delivered;2994 }2995 2996 if (in_flight>0 && in_flight<2000000000) {2997 if(!tcpd->ta) {2998 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd);2999 }3000 tcpd->ta->bytes_in_flight = in_flight;3001 /* Decrement in_flight bytes by one when we have a SYN or FIN bit3002 * flag set as it is only virtual.3003 */3004 if (flags&(TH_SYN0x0002|TH_FIN0x0001)) {3005 tcpd->ta->bytes_in_flight -= 1;3006 }3007 }3008 3009 if((flags & TH_PUSH0x0008) && !tcpd->fwd->push_set_last) {3010 tcpd->fwd->push_bytes_sent += seglen;3011 tcpd->fwd->push_set_last = TRUE(!(0));3012 } else if ((flags & TH_PUSH0x0008) && tcpd->fwd->push_set_last) {3013 tcpd->fwd->push_bytes_sent = seglen;3014 tcpd->fwd->push_set_last = TRUE(!(0));3015 } else if (tcpd->fwd->push_set_last) {3016 tcpd->fwd->push_bytes_sent = seglen;3017 tcpd->fwd->push_set_last = FALSE(0);3018 } else {3019 tcpd->fwd->push_bytes_sent += seglen;3020 }3021 if(!tcpd->ta) {3022 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE(!(0)), tcpd);3023 }3024 tcpd->ta->push_bytes_sent = tcpd->fwd->push_bytes_sent;3025 }3026 }3027 3028}3029 3030/*3031 * Prints results of the sequence number analysis concerning tcp segments3032 * retransmitted or out-of-order3033 */3034static void3035tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,3036 tvbuff_t * tvb,3037 proto_tree * flags_tree, proto_item * flags_item,3038 struct tcp_acked *ta3039 )3040{3041 /* TCP Retransmission */3042 if (ta->flags & TCP_A_RETRANSMISSION0x0001) {3043 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);3044 3045 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");3046 3047 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {3048 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,3049 tvb, 0, 0, &ta->rto_ts);3050 proto_item_set_generated(flags_item);3051 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,3052 tvb, 0, 0, ta->rto_frame);3053 proto_item_set_generated(flags_item);3054 }3055 }3056 /* TCP Fast Retransmission */3057 if (ta->flags & TCP_A_FAST_RETRANSMISSION0x0400) {3058 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_fast_retransmission);3059 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);3060 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,3061 "[TCP Fast Retransmission] ");3062 }3063 /* TCP Spurious Retransmission */3064 if (ta->flags & TCP_A_SPURIOUS_RETRANSMISSION0x4000) {3065 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_spurious_retransmission);3066 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);3067 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,3068 "[TCP Spurious Retransmission] ");3069 }3070 3071 /* TCP Out-Of-Order */3072 if (ta->flags & TCP_A_OUT_OF_ORDER0x0200) {3073 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_out_of_order);3074 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");3075 }3076}3077 3078/* Prints results of the sequence number analysis concerning reused ports */3079static void3080tcp_sequence_number_analysis_print_reused(packet_info * pinfo,3081 proto_item * flags_item,3082 struct tcp_acked *ta3083 )3084{3085 /* TCP Ports Reused */3086 if (ta->flags & TCP_A_REUSED_PORTS0x2000) {3087 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_reused_ports);3088 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,3089 "[TCP Port numbers reused] ");3090 }3091}3092 3093/* Prints results of the sequence number analysis concerning lost tcp segments */3094static void3095tcp_sequence_number_analysis_print_lost(packet_info * pinfo,3096 proto_item * flags_item,3097 struct tcp_acked *ta3098 )3099{3100 /* TCP Lost Segment */3101 if (ta->flags & TCP_A_LOST_PACKET0x0002) {3102 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_lost_packet);3103 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,3104 "[TCP Previous segment not captured] ");3105 }3106 /* TCP Ack lost segment */3107 if (ta->flags & TCP_A_ACK_LOST_PACKET0x0004) {3108 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_ack_lost_packet);3109 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,3110 "[TCP ACKed unseen segment] ");3111 }3112}3113 3114/* Prints results of the sequence number analysis concerning tcp window */3115static void3116tcp_sequence_number_analysis_print_window(packet_info * pinfo,3117 proto_item * flags_item,3118 struct tcp_acked *ta3119 )3120{3121 /* TCP Window Update */3122 if (ta->flags & TCP_A_WINDOW_UPDATE0x0800) {3123 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_update);3124 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");3125 }3126 /* TCP Full Window */3127 if (ta->flags & TCP_A_WINDOW_FULL0x1000) {3128 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_full);3129 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");3130 }3131}3132 3133/* Prints results of the sequence number analysis concerning tcp keepalive */3134static void3135tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,3136 proto_item * flags_item,3137 struct tcp_acked *ta3138 )3139{3140 /*TCP Keep Alive */3141 if (ta->flags & TCP_A_KEEP_ALIVE0x0008) {3142 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive);3143 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");3144 }3145 /* TCP Ack Keep Alive */3146 if (ta->flags & TCP_A_KEEP_ALIVE_ACK0x0100) {3147 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive_ack);3148 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");3149 }3150}3151 3152/* Prints results of the sequence number analysis concerning tcp duplicate ack */3153static void3154tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,3155 tvbuff_t * tvb,3156 proto_tree * flags_tree,3157 struct tcp_acked *ta,3158 proto_tree * tree3159 )3160{3161 proto_item * flags_item;3162 3163 /* TCP Duplicate ACK */3164 if (ta->dupack_num) {3165 if (ta->flags & TCP_A_DUPLICATE_ACK0x0010 ) {3166 flags_item=proto_tree_add_none_format(flags_tree,3167 hf_tcp_analysis_duplicate_ack,3168 tvb, 0, 0,3169 "This is a TCP duplicate ack"3170 );3171 proto_item_set_generated(flags_item);3172 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,3173 "[TCP Dup ACK %u#%u] ",3174 ta->dupack_frame,3175 ta->dupack_num3176 );3177 3178 }3179 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,3180 tvb, 0, 0, ta->dupack_num);3181 proto_item_set_generated(flags_item);3182 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,3183 tvb, 0, 0, ta->dupack_frame);3184 proto_item_set_generated(flags_item);3185 expert_add_info_format(pinfo, flags_item, &ei_tcp_analysis_duplicate_ack, "Duplicate ACK (#%u)", ta->dupack_num);3186 }3187}3188 3189/* Prints results of the sequence number analysis concerning tcp zero window */3190static void3191tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,3192 proto_item * flags_item,3193 struct tcp_acked *ta3194 )3195{3196 /* TCP Zero Window Probe */3197 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE0x0040) {3198 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe);3199 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");3200 }3201 /* TCP Zero Window */3202 if (ta->flags&TCP_A_ZERO_WINDOW0x0020) {3203 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window);3204 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");3205 }3206 /* TCP Zero Window Probe Ack */3207 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK0x0080) {3208 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe_ack);3209 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,3210 "[TCP ZeroWindowProbeAck] ");3211 }3212}3213 3214 3215/* Prints results of the sequence number analysis concerning how many bytes of data are in flight */3216static void3217tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U___attribute__((unused)),3218 tvbuff_t * tvb,3219 proto_tree * flags_tree,3220 struct tcp_acked *ta3221 )3222{3223 proto_item * flags_item;3224 3225 if (tcp_track_bytes_in_flight) {3226 flags_item=proto_tree_add_uint(flags_tree,3227 hf_tcp_analysis_bytes_in_flight,3228 tvb, 0, 0, ta->bytes_in_flight);3229 3230 proto_item_set_generated(flags_item);3231 }3232}3233 3234/* Generate the initial data sequence number and MPTCP connection token from the key. */3235static void3236mptcp_cryptodata_sha1(const guint64 key, guint32 *token, guint64 *idsn)3237{3238 guint8 digest_buf[HASH_SHA1_LENGTH20];3239 guint64 pseudokey = GUINT64_TO_BE(key)((((guint64) ( (((guint64) (key) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (key) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (key) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (key) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (key) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (key) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (key) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (key) & (guint64) (0xff00000000000000UL
)) >> 56)))))
;3240 guint32 _token;3241 guint64 _isdn;3242 3243 gcry_md_hash_buffer(GCRY_MD_SHA1, digest_buf, (const guint8 *)&pseudokey, 8);3244 3245 /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */3246 memcpy(&_token, digest_buf, sizeof(_token));3247 *token = GUINT32_FROM_BE(_token)(((((guint32) ( (((guint32) (_token) & (guint32) 0x000000ffU
) << 24) | (((guint32) (_token) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (_token) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (_token) & (guint32) 0xff000000U
) >> 24))))))
;3248 memcpy(&_isdn, digest_buf + HASH_SHA1_LENGTH20 - sizeof(_isdn), sizeof(_isdn));3249 *idsn = GUINT64_FROM_BE(_isdn)(((((guint64) ( (((guint64) (_isdn) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (_isdn) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (_isdn) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (_isdn) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (_isdn) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (_isdn) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (_isdn) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (_isdn) & (guint64) (0xff00000000000000UL
)) >> 56))))))
;3250}3251 3252/* Generate the initial data sequence number and MPTCP connection token from the key. */3253static void3254mptcp_cryptodata_sha256(const guint64 key, guint32 *token, guint64 *idsn)3255{3256 guint8 digest_buf[HASH_SHA2_256_LENGTH32];3257 guint64 pseudokey = GUINT64_TO_BE(key)((((guint64) ( (((guint64) (key) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (key) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (key) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (key) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (key) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (key) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (key) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (key) & (guint64) (0xff00000000000000UL
)) >> 56)))))
;3258 guint32 _token;3259 guint64 _isdn;3260 3261 gcry_md_hash_buffer(GCRY_MD_SHA256, digest_buf, (const guint8 *)&pseudokey, 8);3262 3263 /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */3264 memcpy(&_token, digest_buf, sizeof(_token));3265 *token = GUINT32_FROM_BE(_token)(((((guint32) ( (((guint32) (_token) & (guint32) 0x000000ffU
) << 24) | (((guint32) (_token) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (_token) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (_token) & (guint32) 0xff000000U
) >> 24))))))
;3266 memcpy(&_isdn, digest_buf + HASH_SHA2_256_LENGTH32 - sizeof(_isdn), sizeof(_isdn));3267 *idsn = GUINT64_FROM_BE(_isdn)(((((guint64) ( (((guint64) (_isdn) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (_isdn) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (_isdn) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (_isdn) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (_isdn) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (_isdn) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (_isdn) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (_isdn) & (guint64) (0xff00000000000000UL
)) >> 56))))))
;3268}3269 3270 3271/* Print formatted list of tcp stream ids that are part of the connection */3272static void3273mptcp_analysis_add_subflows(packet_info *pinfo, tvbuff_t *tvb,3274 proto_tree *parent_tree, struct mptcp_analysis* mptcpd)3275{3276 wmem_list_frame_t *it;3277 proto_item *item;3278 3279 wmem_strbuf_t *val = wmem_strbuf_new(pinfo->pool, "");3280 3281 /* for the analysis, we set each subflow tcp stream id */3282 for(it = wmem_list_head(mptcpd->subflows); it != NULL((void*)0); it = wmem_list_frame_next(it)) {3283 struct tcp_analysis *sf = (struct tcp_analysis *)wmem_list_frame_data(it);3284 wmem_strbuf_append_printf(val, "%u ", sf->stream);3285 }3286 3287 item = proto_tree_add_string(parent_tree, hf_mptcp_analysis_subflows, tvb, 0, 0, wmem_strbuf_get_str(val));3288 proto_item_set_generated(item);3289}3290 3291/* Compute raw dsn if relative tcp seq covered by DSS mapping */3292static gboolean3293mptcp_map_relssn_to_rawdsn(mptcp_dss_mapping_t *mapping, guint32 relssn, guint64 *dsn)3294{3295 if( (relssn < mapping->ssn_low) || (relssn > mapping->ssn_high)) {3296 return FALSE(0);3297 }3298 3299 *dsn = mapping->rawdsn + (relssn - mapping->ssn_low);3300 return TRUE(!(0));3301}3302 3303 3304/* Add duplicated data */3305static mptcp_dsn2packet_mapping_t *3306mptcp_add_duplicated_dsn(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, struct mptcp_subflow *subflow,3307guint64 rawdsn64low, guint64 rawdsn64high3308)3309{3310 wmem_list_t *results = NULL((void*)0);3311 wmem_list_frame_t *packet_it = NULL((void*)0);3312 mptcp_dsn2packet_mapping_t *packet = NULL((void*)0);3313 proto_item *item = NULL((void*)0);3314 3315 results = wmem_itree_find_intervals(subflow->dsn2packet_map,3316 pinfo->pool,3317 rawdsn64low,3318 rawdsn64high3319 );3320 3321 for(packet_it = wmem_list_head(results);3322 packet_it != NULL((void*)0);3323 packet_it = wmem_list_frame_next(packet_it))3324 {3325 3326 packet = (mptcp_dsn2packet_mapping_t *) wmem_list_frame_data(packet_it);3327 DISSECTOR_ASSERT(packet)((void) ((packet) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3327, "packet"))))
;3328 3329 if(pinfo->num > packet->frame) {3330 item = proto_tree_add_uint(tree, hf_mptcp_reinjection_of, tvb, 0, 0, packet->frame);3331 }3332 else {3333 item = proto_tree_add_uint(tree, hf_mptcp_reinjected_in, tvb, 0, 0, packet->frame);3334 }3335 proto_item_set_generated(item);3336 }3337 3338 return packet;3339}3340 3341 3342/* Lookup mappings that describe the packet and then converts the tcp seq number3343 * into the MPTCP Data Sequence Number (DSN)3344 */3345static void3346mptcp_analysis_dsn_lookup(packet_info *pinfo , tvbuff_t *tvb,3347 proto_tree *parent_tree, struct tcp_analysis* tcpd, struct tcpheader * tcph, mptcp_per_packet_data_t *mptcppd)3348{3349 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;3350 proto_item *item = NULL((void*)0);3351 mptcp_dss_mapping_t *mapping = NULL((void*)0);3352 guint32 relseq;3353 guint64 rawdsn = 0;3354 enum mptcp_dsn_conversion convert;3355 3356 if(!mptcp_analyze_mappings)3357 {3358 /* abort analysis */3359 return;3360 }3361 3362 /* for this to work, we need to know the original seq number from the SYN, not from a subsequent packet3363 * hence, we abort if we didn't capture the SYN3364 */3365 if(!(tcpd->fwd->static_flags & ~TCP_S_BASE_SEQ_SET0x01 & (TCP_S_SAW_SYN0x03 | TCP_S_SAW_SYNACK0x05))) {3366 return;3367 }3368 3369 /* if seq not relative yet, we compute it */3370 relseq = (tcp_relative_seq) ? tcph->th_seq : tcph->th_seq - tcpd->fwd->base_seq;3371 3372 DISSECTOR_ASSERT(mptcpd)((void) ((mptcpd) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3372, "mptcpd"))))
;3373 DISSECTOR_ASSERT(mptcppd)((void) ((mptcppd) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3373, "mptcppd"))))
;3374 3375 /* in case of a SYN, there is no mapping covering the DSN */3376 if(tcph->th_flags & TH_SYN0x0002) {3377 3378 rawdsn = tcpd->fwd->mptcp_subflow->meta->base_dsn;3379 convert = DSN_CONV_NONE;3380 }3381 /* if it's a non-syn packet without data (just used to convey TCP options)3382 * then there would be no mappings */3383 else if(relseq == 1 && tcph->th_seglen == 0) {3384 rawdsn = tcpd->fwd->mptcp_subflow->meta->base_dsn + 1;3385 convert = DSN_CONV_NONE;3386 }3387 else {3388 3389 wmem_list_frame_t *dss_it = NULL((void*)0);3390 wmem_list_t *results = NULL((void*)0);3391 guint32 ssn_low = relseq;3392 guint32 seglen = tcph->th_seglen;3393 3394 results = wmem_itree_find_intervals(tcpd->fwd->mptcp_subflow->ssn2dsn_mappings,3395 pinfo->pool,3396 ssn_low,3397 (seglen) ? ssn_low + seglen - 1 : ssn_low3398 );3399 dss_it = wmem_list_head(results); /* assume it's always ok */3400 if(dss_it) {3401 mapping = (mptcp_dss_mapping_t *) wmem_list_frame_data(dss_it);3402 }3403 if(dss_it == NULL((void*)0) || mapping == NULL((void*)0)) {3404 expert_add_info(pinfo, parent_tree, &ei_mptcp_mapping_missing);3405 return;3406 }3407 else {3408 mptcppd->mapping = mapping;3409 }3410 3411 DISSECTOR_ASSERT(mapping)((void) ((mapping) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3411, "mapping"))))
;3412 if(seglen) {3413 /* Finds mappings that cover the sent data and adds them to the dissection tree */3414 for(dss_it = wmem_list_head(results);3415 dss_it != NULL((void*)0);3416 dss_it = wmem_list_frame_next(dss_it))3417 {3418 mapping = (mptcp_dss_mapping_t *) wmem_list_frame_data(dss_it);3419 DISSECTOR_ASSERT(mapping)((void) ((mapping) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3419, "mapping"))))
;3420 3421 item = proto_tree_add_uint(parent_tree, hf_mptcp_related_mapping, tvb, 0, 0, mapping->frame);3422 proto_item_set_generated(item);3423 }3424 }3425 3426 convert = (mapping->extended_dsn) ? DSN_CONV_NONE : DSN_CONV_32_TO_64;3427 DISSECTOR_ASSERT(mptcp_map_relssn_to_rawdsn(mapping, relseq, &rawdsn))((void) ((mptcp_map_relssn_to_rawdsn(mapping, relseq, &rawdsn
)) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3427, "mptcp_map_relssn_to_rawdsn(mapping, relseq, &rawdsn)"
))))
;3428 }3429 3430 /* Make sure we have the 64bit raw DSN */3431 if(mptcp_convert_dsn(rawdsn, tcpd->fwd->mptcp_subflow->meta,3432 convert, FALSE(0), &tcph->th_mptcp->mh_rawdsn64)) {3433 3434 /* always display the rawdsn64 (helpful for debug) */3435 item = proto_tree_add_uint64(parent_tree, hf_mptcp_rawdsn64, tvb, 0, 0, tcph->th_mptcp->mh_rawdsn64);3436 3437 /* converts to relative if required */3438 if (mptcp_relative_seq3439 && mptcp_convert_dsn(tcph->th_mptcp->mh_rawdsn64, tcpd->fwd->mptcp_subflow->meta, DSN_CONV_NONE, TRUE(!(0)), &tcph->th_mptcp->mh_dsn)) {3440 item = proto_tree_add_uint64(parent_tree, hf_mptcp_dsn, tvb, 0, 0, tcph->th_mptcp->mh_dsn);3441 proto_item_append_text(item, " (Relative)");3442 }3443 3444 /* register dsn->packet mapping */3445 if(mptcp_intersubflows_retransmission3446 && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)3447 && tcph->th_seglen > 03448 ) {3449 mptcp_dsn2packet_mapping_t *packet = 0;3450 packet = wmem_new0(wmem_file_scope(), mptcp_dsn2packet_mapping_t)((mptcp_dsn2packet_mapping_t*)wmem_alloc0((wmem_file_scope())
, sizeof(mptcp_dsn2packet_mapping_t)))
;3451 packet->frame = pinfo->fd->num;3452 packet->subflow = tcpd;3453 3454 wmem_itree_insert(tcpd->fwd->mptcp_subflow->dsn2packet_map,3455 tcph->th_mptcp->mh_rawdsn64,3456 tcph->th_mptcp->mh_rawdsn64 + (tcph->th_seglen - 1 ),3457 packet3458 );3459 }3460 proto_item_set_generated(item);3461 3462 /* We can do this only if rawdsn64 is valid !3463 if enabled, look for overlapping mappings on other subflows */3464 if(mptcp_intersubflows_retransmission3465 && tcph->th_have_seglen3466 && tcph->th_seglen) {3467 3468 wmem_list_frame_t *subflow_it = NULL((void*)0);3469 3470 /* results should be some kind of list in case 2 DSS are needed to cover this packet */3471 for(subflow_it = wmem_list_head(mptcpd->subflows); subflow_it != NULL((void*)0); subflow_it = wmem_list_frame_next(subflow_it)) {3472 struct tcp_analysis *sf_tcpd = (struct tcp_analysis *)wmem_list_frame_data(subflow_it);3473 struct mptcp_subflow *sf = mptcp_select_subflow_from_meta(sf_tcpd, tcpd->fwd->mptcp_subflow->meta);3474 3475 /* for current subflow */3476 if (sf == tcpd->fwd->mptcp_subflow) {3477 /* skip, this is the current subflow */3478 }3479 /* in case there were retransmissions on other subflows */3480 else {3481 mptcp_add_duplicated_dsn(pinfo, parent_tree, tvb, sf,3482 tcph->th_mptcp->mh_rawdsn64,3483 tcph->th_mptcp->mh_rawdsn64 + tcph->th_seglen-1);3484 }3485 }3486 }3487 }3488 else {3489 /* could not get the rawdsn64, ignore and continue */3490 }3491 3492}3493 3494 3495/* Print subflow list */3496static void3497mptcp_add_analysis_subtree(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree,3498 struct tcp_analysis *tcpd, struct mptcp_analysis *mptcpd, struct tcpheader * tcph)3499{3500 3501 proto_item *item = NULL((void*)0);3502 proto_tree *tree = NULL((void*)0);3503 mptcp_per_packet_data_t *mptcppd = NULL((void*)0);3504 3505 if(mptcpd == NULL((void*)0)) {3506 return;3507 }3508 3509 item=proto_tree_add_item(parent_tree, hf_mptcp_analysis, tvb, 0, 0, ENC_NA0x00000000);3510 proto_item_set_generated(item);3511 tree=proto_item_add_subtree(item, ett_mptcp_analysis);3512 proto_item_set_generated(tree);3513 3514 /* set field with mptcp stream */3515 if(mptcpd->master) {3516 3517 item = proto_tree_add_boolean_format_value(tree, hf_mptcp_analysis_master, tvb, 0,3518 0, (mptcpd->master->stream == tcpd->stream) ? TRUE(!(0)) : FALSE(0)3519 , "Master is tcp stream %u", mptcpd->master->stream3520 );3521 3522 }3523 else {3524 item = proto_tree_add_boolean(tree, hf_mptcp_analysis_master, tvb, 0,3525 0, FALSE(0));3526 }3527 3528 proto_item_set_generated(item);3529 3530#if 0 // nbOptionsChanged is currently unused.3531 /* store the TCP Options related to MPTCP then we will avoid false DUP ACKs later */3532 guint8 nbOptionsChanged = 0;3533 if((tcpd->mptcp_analysis->mp_operations&(0x01))!=tcph->th_mptcp->mh_mpc) {3534 tcpd->mptcp_analysis->mp_operations |= 0x01;3535 nbOptionsChanged++;3536 }3537 if((tcpd->mptcp_analysis->mp_operations&(0x02))!=tcph->th_mptcp->mh_join) {3538 tcpd->mptcp_analysis->mp_operations |= 0x02;3539 nbOptionsChanged++;3540 }3541 if((tcpd->mptcp_analysis->mp_operations&(0x04))!=tcph->th_mptcp->mh_dss) {3542 tcpd->mptcp_analysis->mp_operations |= 0x04;3543 nbOptionsChanged++;3544 }3545 if((tcpd->mptcp_analysis->mp_operations&(0x08))!=tcph->th_mptcp->mh_add) {3546 tcpd->mptcp_analysis->mp_operations |= 0x08;3547 nbOptionsChanged++;3548 }3549 if((tcpd->mptcp_analysis->mp_operations&(0x10))!=tcph->th_mptcp->mh_remove) {3550 tcpd->mptcp_analysis->mp_operations |= 0x10;3551 nbOptionsChanged++;3552 }3553 if((tcpd->mptcp_analysis->mp_operations&(0x20))!=tcph->th_mptcp->mh_prio) {3554 tcpd->mptcp_analysis->mp_operations |= 0x20;3555 nbOptionsChanged++;3556 }3557 if((tcpd->mptcp_analysis->mp_operations&(0x40))!=tcph->th_mptcp->mh_fail) {3558 tcpd->mptcp_analysis->mp_operations |= 0x40;3559 nbOptionsChanged++;3560 }3561 if((tcpd->mptcp_analysis->mp_operations&(0x80))!=tcph->th_mptcp->mh_fastclose) {3562 tcpd->mptcp_analysis->mp_operations |= 0x80;3563 nbOptionsChanged++;3564 }3565 /* we could track MPTCP option changes here, with nbOptionsChanged */3566#endif3567 3568 item = proto_tree_add_uint(tree, hf_mptcp_stream, tvb, 0, 0, mptcpd->stream);3569 proto_item_set_generated(item);3570 3571 /* retrieve saved analysis of packets, else create it */3572 mptcppd = (mptcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mptcp, pinfo->curr_layer_num);3573 if(!mptcppd) {3574 mptcppd = (mptcp_per_packet_data_t *)wmem_new0(wmem_file_scope(), mptcp_per_packet_data_t)((mptcp_per_packet_data_t*)wmem_alloc0((wmem_file_scope()), sizeof
(mptcp_per_packet_data_t)))
;3575 p_add_proto_data(wmem_file_scope(), pinfo, proto_mptcp, pinfo->curr_layer_num, mptcppd);3576 }3577 3578 /* Print formatted list of tcp stream ids that are part of the connection */3579 mptcp_analysis_add_subflows(pinfo, tvb, tree, mptcpd);3580 3581 /* Converts TCP seq number into its MPTCP DSN */3582 mptcp_analysis_dsn_lookup(pinfo, tvb, tree, tcpd, tcph, mptcppd);3583 3584}3585 3586 3587static void3588tcp_sequence_number_analysis_print_push_bytes_sent(packet_info * pinfo _U___attribute__((unused)),3589 tvbuff_t * tvb,3590 proto_tree * flags_tree,3591 struct tcp_acked *ta3592 )3593{3594 proto_item * flags_item;3595 3596 if (tcp_track_bytes_in_flight) {3597 flags_item=proto_tree_add_uint(flags_tree,3598 hf_tcp_analysis_push_bytes_sent,3599 tvb, 0, 0, ta->push_bytes_sent);3600 3601 proto_item_set_generated(flags_item);3602 }3603}3604 3605static void3606tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree,3607 struct tcp_analysis *tcpd, guint32 seq, guint32 ack)3608{3609 struct tcp_acked *ta = NULL((void*)0);3610 proto_item *item;3611 proto_tree *tree;3612 proto_tree *flags_tree=NULL((void*)0);3613 3614 if (!tcpd) {3615 return;3616 }3617 if(!tcpd->ta) {3618 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, FALSE(0), tcpd);3619 }3620 ta=tcpd->ta;3621 if(!ta) {3622 return;3623 }3624 3625 item=proto_tree_add_item(parent_tree, hf_tcp_analysis, tvb, 0, 0, ENC_NA0x00000000);3626 proto_item_set_generated(item);3627 tree=proto_item_add_subtree(item, ett_tcp_analysis);3628 3629 /* encapsulate all proto_tree_add_xxx in ifs so we only print what3630 data we actually have */3631 if(ta->frame_acked) {3632 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,3633 tvb, 0, 0, ta->frame_acked);3634 proto_item_set_generated(item);3635 3636 if(ta->partial_ack) {3637 expert_add_info(pinfo, item, &ei_tcp_analysis_partial_ack);3638 }3639 3640 /* only display RTT if we actually have something we are acking */3641 if( ta->ts.secs || ta->ts.nsecs ) {3642 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,3643 tvb, 0, 0, &ta->ts);3644 proto_item_set_generated(item);3645 }3646 }3647 if (!nstime_is_zero(&tcpd->ts_first_rtt)) {3648 item = proto_tree_add_time(tree, hf_tcp_analysis_first_rtt,3649 tvb, 0, 0, &(tcpd->ts_first_rtt));3650 proto_item_set_generated(item);3651 }3652 3653 if(ta->bytes_in_flight) {3654 /* print results for amount of data in flight */3655 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta);3656 tcp_sequence_number_analysis_print_push_bytes_sent(pinfo, tvb, tree, ta);3657 }3658 3659 if(ta->flags) {3660 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, 0, ENC_NA0x00000000);3661 proto_item_set_generated(item);3662 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);3663 3664 /* print results for reused tcp ports */3665 tcp_sequence_number_analysis_print_reused(pinfo, item, ta);3666 3667 /* print results for retransmission and out-of-order segments */3668 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, item, ta);3669 3670 /* print results for lost tcp segments */3671 tcp_sequence_number_analysis_print_lost(pinfo, item, ta);3672 3673 /* print results for tcp window information */3674 tcp_sequence_number_analysis_print_window(pinfo, item, ta);3675 3676 /* print results for tcp keep alive information */3677 tcp_sequence_number_analysis_print_keepalive(pinfo, item, ta);3678 3679 /* print results for tcp duplicate acks */3680 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);3681 3682 /* print results for tcp zero window */3683 tcp_sequence_number_analysis_print_zero_window(pinfo, item, ta);3684 3685 }3686 3687}3688 3689static void3690print_tcp_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *tcp_tree, packet_info *pinfo, tvbuff_t *next_tvb)3691{3692 proto_item *tcp_tree_item, *frag_tree_item;3693 3694 /*3695 * The subdissector thought it was completely3696 * desegmented (although the stuff at the3697 * end may, in turn, require desegmentation),3698 * so we show a tree with all segments.3699 */3700 show_fragment_tree(ipfd_head, &tcp_segment_items,3701 tree, pinfo, next_tvb, &frag_tree_item);3702 /*3703 * The toplevel fragment subtree is now3704 * behind all desegmented data; move it3705 * right behind the TCP tree.3706 */3707 tcp_tree_item = proto_tree_get_parent(tcp_tree);3708 if(frag_tree_item && tcp_tree_item) {3709 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);3710 }3711}3712 3713/* **************************************************************************3714 * End of tcp sequence number analysis3715 * **************************************************************************/3716 3717 3718/* Minimum TCP header length. */3719#define TCPH_MIN_LEN20 203720 3721/* Desegmentation of TCP streams */3722 3723/* The primary ID is the first frame of a multisegment PDU, which is3724 * most likely unique in the capture (unlike sequence numbers which3725 * can be re-used, especially when relative sequence numbers are enabled).3726 * However, frames can have multiple PDUs with certain encapsulations like3727 * GSE or MPE over DVB BaseBand Frames.3728 */3729 3730typedef struct _tcp_endpoint {3731 3732 address src_addr;3733 address dst_addr;3734 port_type ptype;3735 guint32 src_port;3736 guint32 dst_port;3737} tcp_endpoint_t;3738 3739static void3740save_endpoint(packet_info *pinfo, tcp_endpoint_t *a)3741{3742 copy_address_shallow(&a->src_addr, &pinfo->src);3743 copy_address_shallow(&a->dst_addr, &pinfo->dst);3744 a->ptype = pinfo->ptype;3745 a->src_port = pinfo->srcport;3746 a->dst_port = pinfo->destport;3747}3748 3749static void3750restore_endpoint(packet_info *pinfo, tcp_endpoint_t *a)3751{3752 copy_address_shallow(&pinfo->src, &a->src_addr);3753 copy_address_shallow(&pinfo->dst, &a->dst_addr);3754 pinfo->ptype = a->ptype;3755 pinfo->srcport = a->src_port;3756 pinfo->destport = a->dst_port;3757}3758 3759typedef struct _tcp_segment_key {3760 address src_addr;3761 address dst_addr;3762 guint32 src_port;3763 guint32 dst_port;3764 guint32 id; /* msp->first_frame */3765 guint32 seq; /* msp->seq */3766} tcp_segment_key;3767 3768static guint3769tcp_segment_hash(gconstpointer k)3770{3771 const tcp_segment_key* key = (const tcp_segment_key*) k;3772 guint hash_val;3773 3774 hash_val = key->id;3775 3776/* In most captures there is only one fragment per id / first_frame,3777 so we only use it in the hash as an optimization.3778 3779 int i;3780 for (i = 0; i < key->src.len; i++)3781 hash_val += key->src_addr.data[i];3782 for (i = 0; i < key->dst.len; i++)3783 hash_val += key->dst_addr.data[i];3784 hash_val += key->src_port;3785 hash_val += key->dst_port;3786 hash_val += key->seq;3787*/3788 3789 return hash_val;3790}3791 3792static gint3793tcp_segment_equal(gconstpointer k1, gconstpointer k2)3794{3795 const tcp_segment_key* key1 = (const tcp_segment_key*) k1;3796 const tcp_segment_key* key2 = (const tcp_segment_key*) k2;3797 3798 /*3799 * key.id is the first item to compare since it's the item most3800 * likely to differ between sessions, thus short-circuiting3801 * the comparison of addresses and ports.3802 */3803 return (key1->id == key2->id) &&3804 (addresses_equal(&key1->src_addr, &key2->src_addr)) &&3805 (addresses_equal(&key1->dst_addr, &key2->dst_addr)) &&3806 (key1->src_port == key2->src_port) &&3807 (key1->dst_port == key2->dst_port) &&3808 (key1->seq == key2->seq);3809}3810 3811/*3812 * Create a fragment key for temporary use; it can point to non-3813 * persistent data, and so must only be used to look up and3814 * delete entries, not to add them.3815 */3816static gpointer3817tcp_segment_temporary_key(const packet_info *pinfo, const guint32 id,3818 const void *data)3819{3820 struct tcp_multisegment_pdu *msp = (struct tcp_multisegment_pdu*)data;3821 DISSECTOR_ASSERT(msp)((void) ((msp) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3821, "msp"))))
;3822 tcp_segment_key *key = g_slice_new(tcp_segment_key)((tcp_segment_key*) g_slice_alloc (sizeof (tcp_segment_key)));3823 3824 /*3825 * Do a shallow copy of the addresses.3826 */3827 copy_address_shallow(&key->src_addr, &pinfo->src);3828 copy_address_shallow(&key->dst_addr, &pinfo->dst);3829 key->src_port = pinfo->srcport;3830 key->dst_port = pinfo->destport;3831 key->id = id;3832 key->seq = msp->seq;3833 3834 return (gpointer)key;3835}3836 3837/*3838 * Create a fragment key for permanent use; it must point to persistent3839 * data, so that it can be used to add entries.3840 */3841static gpointer3842tcp_segment_persistent_key(const packet_info *pinfo,3843 const guint32 id, const void *data)3844{3845 struct tcp_multisegment_pdu *msp = (struct tcp_multisegment_pdu*)data;3846 DISSECTOR_ASSERT(msp)((void) ((msp) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3846, "msp"))))
;3847 tcp_segment_key *key = g_slice_new(tcp_segment_key)((tcp_segment_key*) g_slice_alloc (sizeof (tcp_segment_key)));3848 3849 /*3850 * Do a deep copy of the addresses.3851 */3852 copy_address(&key->src_addr, &pinfo->src);3853 copy_address(&key->dst_addr, &pinfo->dst);3854 key->src_port = pinfo->srcport;3855 key->dst_port = pinfo->destport;3856 key->id = id;3857 key->seq = msp->seq;3858 3859 return (gpointer)key;3860}3861 3862static void3863tcp_segment_free_temporary_key(gpointer ptr)3864{3865 tcp_segment_key *key = (tcp_segment_key *)ptr;3866 g_slice_free(tcp_segment_key, key)do { if (1) g_slice_free1 (sizeof (tcp_segment_key), (key)); else
(void) ((tcp_segment_key*) 0 == (key)); } while (0)
;3867}3868 3869static void3870tcp_segment_free_persistent_key(gpointer ptr)3871{3872 tcp_segment_key *key = (tcp_segment_key *)ptr;3873 3874 if(key){3875 /*3876 * Free up the copies of the addresses from the old key.3877 */3878 free_address(&key->src_addr);3879 free_address(&key->dst_addr);3880 3881 g_slice_free(tcp_segment_key, key)do { if (1) g_slice_free1 (sizeof (tcp_segment_key), (key)); else
(void) ((tcp_segment_key*) 0 == (key)); } while (0)
;3882 }3883}3884 3885const reassembly_table_functions3886tcp_reassembly_table_functions = {3887 tcp_segment_hash,3888 tcp_segment_equal,3889 tcp_segment_temporary_key,3890 tcp_segment_persistent_key,3891 tcp_segment_free_temporary_key,3892 tcp_segment_free_persistent_key3893};3894 3895static reassembly_table tcp_reassembly_table;3896 3897/* functions to trace tcp segments */3898/* Enable desegmenting of TCP streams */3899static bool_Bool tcp_desegment = true1;3900 3901/* Returns the maximum contiguous sequence number of the reassembly associated3902 * with the msp *if* a new fragment were added ending in the given maxnextseq.3903 * The new fragment is from the current frame and may not have been added yet.3904 */3905static guint323906find_maxnextseq(packet_info *pinfo, struct tcp_multisegment_pdu *msp, guint32 maxnextseq)3907{3908 fragment_head *fd_head;3909 3910 DISSECTOR_ASSERT(msp)((void) ((msp) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3910, "msp"))))
;3911 3912 fd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);3913 /* msp implies existence of fragments, this should never be NULL. */3914 DISSECTOR_ASSERT(fd_head)((void) ((fd_head) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3914, "fd_head"))))
;3915 3916 /* Find length of contiguous fragments.3917 * Start with the first gap, but the new fragment is allowed to3918 * fill that gap. */3919 guint32 max_len = maxnextseq - msp->seq;3920 fragment_item* frag = (fd_head->first_gap) ? fd_head->first_gap : fd_head->next;3921 for (; frag && frag->offset <= max_len; frag = frag->next) {3922 max_len = MAX(max_len, frag->offset + frag->len)(((max_len) > (frag->offset + frag->len)) ? (max_len
) : (frag->offset + frag->len))
;3923 }3924 3925 return max_len + msp->seq;3926}3927 3928static struct tcp_multisegment_pdu*3929split_msp(packet_info *pinfo, struct tcp_multisegment_pdu *msp, struct tcp_analysis *tcpd)3930{3931 fragment_head *fd_head;3932 guint32 first_frame = 0;3933 guint32 last_frame = 0;3934 const guint32 split_offset = pinfo->desegment_offset;3935 3936 fd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);3937 /* This is for splitting defragmented MSPs, so fd_head should exist3938 * and be defragmented. This also ensures that fd_i->tvb_data exists.3939 */3940 DISSECTOR_ASSERT(fd_head && fd_head->flags & FD_DEFRAGMENTED)((void) ((fd_head && fd_head->flags & 0x0001) ?
(void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3940, "fd_head && fd_head->flags & 0x0001"
))))
;3941 3942 fragment_item *fd_i, *first_frag = NULL((void*)0);3943 3944 /* The fragment list is sorted in offset order, but not nec. frame order3945 * or end offset order due to out of order reassembly and possible overlap.3946 * fd_i->offset < split_offset - some bytes are before the split3947 * fd_i->offset + fd_i->len >= split_offset - some bytes are after split3948 * Look through all the fragments that have some data before the split point.3949 */3950 for (fd_i = fd_head->next; fd_i && (fd_i->offset < split_offset); fd_i = fd_i->next) {3951 if (last_frame < fd_i->frame) {3952 last_frame = fd_i->frame;3953 }3954 if (fd_i->offset + fd_i->len >= split_offset) {3955 if (first_frag == NULL((void*)0)) {3956 first_frag = fd_i;3957 first_frame = fd_i->frame;3958 } else if (fd_i->frame < first_frame) {3959 first_frame = fd_i->frame;3960 }3961 }3962 };3963 3964 /* Now look through all the remaining fragments that only have bytes after3965 * the split.3966 */3967 for (; fd_i; fd_i = fd_i->next) {3968 guint32 frag_end = fd_i->offset + fd_i->len;3969 if (split_offset <= frag_end && fd_i->frame < first_frame) {3970 first_frame = fd_i->frame;3971 }3972 }3973 3974 /* We only call this when the frame the fragments were reassembled in3975 * (which is the current frame) includes some data before the split3976 * point, so that it won't change and we can be consistent dissecting3977 * between passes. We also should have at least some data after the3978 * split point (because the subdissector claimed there was undissected3979 * data.)3980 */3981 DISSECTOR_ASSERT(fd_head->reassembled_in == last_frame)((void) ((fd_head->reassembled_in == last_frame) ? (void)0
: (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 3981, "fd_head->reassembled_in == last_frame"
))))
;3982 DISSECTOR_ASSERT(first_frag != NULL)((void) ((first_frag != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c"
, 3982, "first_frag != ((void*)0)"))))
;3983 3984 guint32 new_seq = msp->seq + pinfo->desegment_offset;3985 struct tcp_multisegment_pdu *newmsp;3986 newmsp = pdu_store_sequencenumber_of_next_pdu(pinfo, new_seq,3987 new_seq+1, tcpd->fwd->multisegment_pdus);3988 newmsp->first_frame = first_frame;3989 newmsp->nxtpdu = msp->nxtpdu;3990 3991 /* XXX: Could do the adding the new fragments in fragment_truncate */3992 for (fd_i = first_frag; fd_i; fd_i = fd_i->next) {3993 guint32 frag_offset = fd_i->offset;3994 guint32 frag_len = fd_i->len;3995 /* Check for some unusual out of order overlapping segment situations. */3996 if (split_offset < frag_offset + frag_len) {3997 if (fd_i->offset < split_offset) {3998 frag_offset = split_offset;3999 frag_len -= (split_offset - fd_i->offset);4000 }4001 fragment_add_out_of_order(&tcp_reassembly_table, fd_head->tvb_data,4002 frag_offset, pinfo, first_frame, newmsp,4003 frag_offset - split_offset, frag_len, TRUE(!(0)), fd_i->frame);4004 }4005 }4006 4007 fragment_truncate(&tcp_reassembly_table, pinfo, msp->first_frame, msp, split_offset);4008 msp->nxtpdu = msp->seq + split_offset;4009 4010 /* The newmsp nxtpdu will be adjusted after leaving this function. */4011 return newmsp;4012}4013 4014typedef struct _ooo_segment_item {4015 guint32 frame;4016 guint32 seq;4017 guint32 len;4018 guint8 *data;4019} ooo_segment_item;4020 4021static gint4022compare_ooo_segment_item(gconstpointer a, gconstpointer b)4023{4024 const ooo_segment_item *fd_a = a;4025 const ooo_segment_item *fd_b = b;4026 4027 /* We only insert segments into this list that satisfy4028 * LT_SEQ(tcpd->fwd->maxnextseq, seq), for the current value4029 * of maxnextseq (removing segments when maxnextseq is advanced)4030 * so these rollover-aware comparisons are transitive over the4031 * domain (never greater than 2^31).4032 */4033 if (LT_SEQ(fd_a->seq, fd_b->seq)((gint32)((fd_a->seq) - (fd_b->seq)) < 0))4034 return -1;4035 4036 if (GT_SEQ(fd_a->seq, fd_b->seq)((gint32)((fd_b->seq) - (fd_a->seq)) < 0))4037 return 1;4038 4039 if (fd_a->frame < fd_b->frame)4040 return -1;4041 4042 if (fd_a->frame > fd_b->frame)4043 return 1;4044 4045 return 0;4046}4047 4048/* Search through our list of out of order segments and add the ones that are4049 * now contiguous onto a MSP until we use them all or reach another gap.4050 *4051 * If the MSP parameter is a incomplete, returns it with any OOO segments added.4052 * If the MSP parameter is NULL or complete, returns a newly created MSP with4053 * OOO segments added, or NULL if there were no segments to add.4054 */4055static struct tcp_multisegment_pdu *4056msp_add_out_of_order(packet_info *pinfo, struct tcp_multisegment_pdu *msp, struct tcp_analysis *tcpd, guint32 seq)4057{4058 4059 /* Whether a previous MSP exists with missing segments. */4060 gboolean has_unfinished_msp = msp && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002);4061 bool_Bool updated_maxnextseq = FALSE(0);4062 4063 if (msp) {4064 guint32 maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);4065 if (LE_SEQ(tcpd->fwd->maxnextseq, maxnextseq)((gint32)((tcpd->fwd->maxnextseq) - (maxnextseq)) <=
0)
) {4066 tcpd->fwd->maxnextseq = maxnextseq;4067 }4068 updated_maxnextseq = TRUE(!(0));4069 }4070 wmem_list_frame_t *curr_entry;4071 curr_entry = wmem_list_head(tcpd->fwd->ooo_segments);4072 ooo_segment_item *fd;4073 tvbuff_t *tvb_data;4074 while (curr_entry) {4075 fd = (ooo_segment_item *)wmem_list_frame_data(curr_entry);4076 if (LT_SEQ(tcpd->fwd->maxnextseq, fd->seq)((gint32)((tcpd->fwd->maxnextseq) - (fd->seq)) < 0
)
) {4077 /* There might be segments already added to the msp that now extend4078 * the maximum contiguous sequence number. Check for them. */4079 if (msp && !updated_maxnextseq) {4080 tcpd->fwd->maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);4081 updated_maxnextseq = TRUE(!(0));4082 }4083 if (LT_SEQ(tcpd->fwd->maxnextseq, fd->seq)((gint32)((tcpd->fwd->maxnextseq) - (fd->seq)) < 0
)
) {4084 break;4085 }4086 }4087 /* We have filled in the gap, so this out of order4088 * segment is now contiguous and can be processed along4089 * with the segment we just received.4090 */4091 tcpd->fwd->maxnextseq = fd->seq + fd->len;4092 tvb_data = tvb_new_real_data(fd->data, fd->len, fd->len);4093 if (has_unfinished_msp) {4094 4095 /* Increase the expected MSP size if necessary. Yes, the4096 * subdissector may have told us that a PDU ended here, but we4097 * might have enough newly contiguous data to dissect another4098 * PDU past that, and we should send that to the subdissector4099 * too. */4100 if (LT_SEQ(msp->nxtpdu, fd->seq + fd->len)((gint32)((msp->nxtpdu) - (fd->seq + fd->len)) < 0
)
) {4101 msp->nxtpdu = fd->seq + fd->len;4102 }4103 /* Add this OOO segment to the unfinished MSP */4104 fragment_add_out_of_order(&tcp_reassembly_table,4105 tvb_data, 0,4106 pinfo, msp->first_frame, msp,4107 fd->seq - msp->seq, fd->len,4108 msp->nxtpdu, fd->frame);4109 } else {4110 /* No MSP in progress, so create one starting4111 * at the sequence number of segment received4112 * in this frame. Note that we will be adding4113 * the first segment below, and this is the frame4114 * of the first segment, so first_frame_with_seq4115 * is already correct (and unnecessary) and4116 * we don't need MSP_FLAGS_MISSING_FIRST_SEGMENT. */4117 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,4118 seq, fd->seq + fd->len,4119 tcpd->fwd->multisegment_pdus);4120 fragment_add_out_of_order(&tcp_reassembly_table,4121 tvb_data, 0, pinfo, msp->first_frame,4122 msp, fd->seq - msp->seq, fd->len,4123 msp->nxtpdu, fd->frame);4124 has_unfinished_msp = TRUE(!(0));4125 }4126 updated_maxnextseq = FALSE(0);4127 tvb_free(tvb_data);4128 wmem_list_remove_frame(tcpd->fwd->ooo_segments, curr_entry);4129 curr_entry = wmem_list_head(tcpd->fwd->ooo_segments);4130 4131 }4132 /* There might be segments already added to the msp that now extend4133 * the maximum contiguous sequence number. Check for them. */4134 if (msp && !updated_maxnextseq) {4135 tcpd->fwd->maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);4136 }4137 return msp;4138}4139 4140static void4141desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,4142 guint32 seq, guint32 nxtseq,4143 guint32 sport, guint32 dport,4144 proto_tree *tree, proto_tree *tcp_tree,4145 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)4146{4147 fragment_head *ipfd_head;4148 int last_fragment_len;4149 gboolean must_desegment;4150 gboolean called_dissector;4151 gboolean has_gap;4152 int another_pdu_follows;4153 int deseg_offset;4154 guint32 deseg_seq;4155 gint nbytes;4156 proto_item *item;4157 struct tcp_multisegment_pdu *msp;4158 gboolean cleared_writable = col_get_writable(pinfo->cinfo, COL_PROTOCOL);4159 gboolean first_pdu = TRUE(!(0));4160 const gboolean reassemble_ooo = tcp_analyze_seq && tcp_desegment && tcp_reassemble_out_of_order && tcpd && tcpd->fwd->ooo_segments;4161 4162 tcp_endpoint_t orig_endpoint, new_endpoint;4163 4164 save_endpoint(pinfo, &orig_endpoint);4165 save_endpoint(pinfo, &new_endpoint);4166 4167again:4168 ipfd_head = NULL((void*)0);4169 last_fragment_len = 0;4170 must_desegment = FALSE(0);4171 called_dissector = FALSE(0);4172 has_gap = FALSE(0);4173 another_pdu_follows = 0;4174 msp = NULL((void*)0);4175 4176 /*4177 * Initialize these to assume no desegmentation.4178 * If that's not the case, these will be set appropriately4179 * by the subdissector.4180 */4181 pinfo->desegment_offset = 0;4182 pinfo->desegment_len = 0;4183 4184 /*4185 * Initialize this to assume that this segment will just be4186 * added to the middle of a desegmented chunk of data, so4187 * that we should show it all as data.4188 * If that's not the case, it will be set appropriately.4189 */4190 deseg_offset = offset;4191 4192 /*4193 * TODO: Some notes on current limitations with TCP desegmentation:4194 *4195 * This function can be called with either relative or absolute sequence4196 * numbers; the ??_SEQ macros are called for comparisons to deal with4197 * with sequence number rollover. (With relative sequence numbers, if4198 * early TCP segments are received out of order before the SYN it can be4199 * possible for rollover to occur at the very beginning of a connection.)4200 *4201 * However, multi-segment PDU lookup does not work for MSPs that span4202 * TCP sequence number rollover, and desegmentation fails.4203 *4204 * When there is a single TCP connection that is longer than 4 GiB and4205 * thus sequence numbers are reused, multi-segment PDU lookup and4206 * retransmission identification does not work. (Bug 10503).4207 *4208 * Distinguishing between sequence number reuse on a very long connection4209 * and sequence number reuse due to retransmission is difficult. Right4210 * now very long connections are just not handled as the rarer case.4211 * Perhaps retransmission identification could be entirely left up to TCP4212 * analysis (if enabled, not done at all if disabled), instead of TCP4213 * analysis results only used to supplement work here?4214 *4215 * TCP sequence analysis can set TCP_A_RETRANSMISSION in cases where4216 * we still need to process the segment anyway because something other4217 * than the sequence number is different from the prior segment. That4218 * includes "retransmitted but with additional data" (Bug 13523) and4219 * "retransmitted due to bad checksum" (especially if checksum verification4220 * is enabled.)4221 *4222 * "Reassemble out-of-order segments" uses its own method of detecting4223 * retranmission, but uses more memory and CPU, and when used, a TCP stream4224 * that has missing segments that are never retransmitted stop processing4225 * after the missing segment.4226 *4227 * If multiple TCP/IP packets are encapsulated in the same frame (such4228 * as with GSE, which has very long Baseband Frames) this causes issues:4229 *4230 * If a subdissector reports that it can handle a payload, but needs4231 * more data (pinfo->desegment_len > 0) and did not actually dissect4232 * any of it (pinfo->desegment_offset == 0), on the first pass it4233 * still adds layers to the frame. On subsequent passes, the MSP created4234 * (or extended) in the first pass means that the subdissector won't be4235 * called at all. If there are other protocols contained in the frame4236 * that are dissected on the second pass they will have different4237 * layer numbers than in the first pass, which can disturb proto_data4238 * lookup, reassembly, etc. (Bug 16109 describes this for TLS.)4239 */4240 4241 if (tcpd) {4242 4243 if (reassemble_ooo) {4244 /* If we are reassembling out of order, we can do this retransmission4245 * check. Anything before the latest consecutive sequence number we've4246 * already processed is a retransmission (from the perspective of has4247 * been passed to subdissectors; the judgment of TCP Sequence Analysis4248 * may be different, because it considers RTO and ACKs and so forth).4249 *4250 * XXX: If these segments are part of incomplete MSPs, we pass them4251 * to the reassembly code which tests for overlap conflicts.4252 * For those which are part of completed reassemblies or not part4253 * of MSPs, we just don't process them. The former would throw a4254 * ReassemblyError, which is likely acceptable in the case of4255 * retransmission of the same segment but not if retransmitted with4256 * additional data, where we'd need to catch the exception to4257 * process the extra data. For ones that were not added to MSPs at4258 * all, we can't do much. (Bug #13061)4259 *4260 * Retransmissions of out of order segments after our latest4261 * consecutive sequence number will all be stored and then eventually4262 * put on multisegment PDUs and go to the reassembler, which should4263 * be able to handle retransmission, as those are still incomplete.4264 */4265 4266 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq);4267 4268 gboolean has_unfinished_msp = FALSE(0);4269 if (msp && LE_SEQ(msp->seq, seq)((gint32)((msp->seq) - (seq)) <= 0) && GT_SEQ(msp->nxtpdu, seq)((gint32)((seq) - (msp->nxtpdu)) < 0) && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002)) {4270 has_unfinished_msp = TRUE(!(0));4271 }4272 4273 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && first_pdu) {4274 if (tcpd->fwd->maxnextseq && LT_SEQ(seq, tcpd->fwd->maxnextseq)((gint32)((seq) - (tcpd->fwd->maxnextseq)) < 0) && !has_unfinished_msp) {4275 if(!tcpd->ta) {4276 tcp_analyze_get_acked_struct(pinfo->num, seq, tcpinfo->lastackseq, TRUE(!(0)), tcpd);4277 }4278 tcpd->ta->flags |= TCP_A_OLD_DATA0x8000;4279 if (GT_SEQ(nxtseq, tcpd->fwd->maxnextseq)((gint32)((tcpd->fwd->maxnextseq) - (nxtseq)) < 0)) {4280 tcpd->ta->new_data_seq = tcpd->fwd->maxnextseq;4281 } else {4282 tcpd->ta->new_data_seq = nxtseq;4283 }4284 }4285 }4286 4287 if(tcpd->ta && first_pdu) {4288 if((tcpd->ta->flags&TCP_A_OLD_DATA0x8000) == TCP_A_OLD_DATA0x8000) {4289 nbytes = tcpd->ta->new_data_seq - seq;4290 4291 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb,4292 offset, nbytes, NULL((void*)0),4293 "Retransmitted TCP segment data (%u byte%s)",4294 nbytes, plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s")));4295 4296 offset += nbytes;4297 seq = tcpd->ta->new_data_seq;4298 first_pdu = FALSE(0);4299 if (tvb_captured_length_remaining(tvb, offset) > 0)4300 goto again;4301 goto clean_exit;4302 }4303 }4304 } else {4305 4306 /* Have we seen this PDU before (and is it the start of a multi-4307 * segment PDU)?4308 *4309 * If the sequence number was seen before, it is part of a4310 * retransmission if the whole segment fits within the MSP.4311 * (But if this is this frame was already visited and the first frame of4312 * the MSP matches the current frame, then it is not a retransmission,4313 * but the start of a new MSP.)4314 *4315 * If only part of the segment fits in the MSP, then either:4316 * - The previous segment included with the MSP was a Zero Window Probe4317 * with one byte of data and the subdissector just asked for one more4318 * byte. Do not mark it as retransmission (Bug 15427).4319 * - Data was actually being retransmitted, but with additional data4320 * (Bug 13523). Do not mark it as retransmission to handle the extra4321 * bytes. (NOTE Due to the TCP_A_RETRANSMISSION check below, such4322 * extra data will still be ignored.)4323 * - The MSP contains multiple segments, but the subdissector finished4324 * reassembly using a subset of the final segment (thus "msp->nxtpdu"4325 * is smaller than the nxtseq of the previous segment). If that final4326 * segment was retransmitted, then "nxtseq > msp->nxtpdu".4327 * Unfortunately that will *not* be marked as retransmission here.4328 * The next TCP_A_RETRANSMISSION hopefully takes care of it though.4329 *4330 * Only shortcircuit here when the first segment of the MSP is known,4331 * and when this first segment is not one to complete the MSP.4332 */4333 if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, seq)) &&4334 nxtseq <= msp->nxtpdu &&4335 !(msp->flags & MSP_FLAGS_MISSING_FIRST_SEGMENT0x00000004) && msp->last_frame != pinfo->num) {4336 const char* str;4337 gboolean is_retransmission = FALSE(0);4338 4339 /* Yes. This could be because we've dissected this frame before4340 * or because this is a retransmission of a previously-seen4341 * segment. Either way, we don't need to hand it off to the4342 * subdissector and we certainly don't want to re-add it to the4343 * multisegment_pdus list: if we did, subsequent lookups would4344 * find this retransmission instead of the original transmission4345 * (breaking desegmentation if we'd already linked other segments4346 * to the original transmission's entry).4347 *4348 * Cases to handle here:4349 * - In-order stream, pinfo->num matches begin of MSP.4350 * - In-order stream, but pinfo->num does not match the begin of the4351 * MSP. Must be a retransmission.4352 * - OoO stream where this segment fills the gap in the begin of the4353 * MSP. msp->first_frame is the start where the gap was detected4354 * (and does NOT match pinfo->num).4355 */4356 4357 if (msp->first_frame == pinfo->num || msp->first_frame_with_seq == pinfo->num) {4358 str = "";4359 } else {4360 str = "Retransmitted ";4361 is_retransmission = TRUE(!(0));4362 /* TCP analysis already flags this (in COL_INFO) as a retransmission--if it's enabled */4363 }4364 4365 /* Fix for bug 3264: look up ipfd for this (first) segment,4366 so can add tcp.reassembled_in generated field on this code path. */4367 if (!is_retransmission) {4368 ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);4369 if (ipfd_head) {4370 if (ipfd_head->reassembled_in != 0) {4371 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,4372 0, ipfd_head->reassembled_in);4373 proto_item_set_generated(item);4374 4375 if (first_pdu) {4376 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[TCP PDU reassembled in %u]",4377 ipfd_head->reassembled_in);4378 }4379 }4380 }4381 }4382 4383 nbytes = tvb_reported_length_remaining(tvb, offset);4384 4385 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,4386 nbytes, NULL((void*)0), "%sTCP segment data (%u byte%s)", str, nbytes,4387 plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s")));4388 goto clean_exit;4389 }4390 4391 /* Else, find the most previous PDU starting before this sequence number */4392 if (!msp) {4393 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);4394 }4395 4396 gboolean has_unfinished_msp = FALSE(0);4397 if (msp && LE_SEQ(msp->seq, seq)((gint32)((msp->seq) - (seq)) <= 0) && GT_SEQ(msp->nxtpdu, seq)((gint32)((seq) - (msp->nxtpdu)) < 0) && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002)) {4398 has_unfinished_msp = TRUE(!(0));4399 }4400 4401 /* The above code only finds retransmission if the PDU boundaries and the seq coincide4402 * If we have sequence analysis active use the TCP_A_RETRANSMISSION flag.4403 * XXXX Could the above code be improved?4404 */4405 if(tcpd->ta) {4406 /* If we have an unfinished MSP that this segment belongs to4407 * or if the sequence number is newer than anything we've seen,4408 * then this is Out of Order from the reassembly perspective4409 * and we want to process it anyway.4410 */4411 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && tcpd->fwd->maxnextseq && LE_SEQ(seq, tcpd->fwd->maxnextseq)((gint32)((seq) - (tcpd->fwd->maxnextseq)) <= 0) && !has_unfinished_msp) {4412 /* Otherwise, if TCP Analysis calls the segment a4413 * Spurious Retransmission or Retransmission, ignore it4414 * here and on future passes.4415 * See issue 102894416 * XXX: There are still some cases where TCP Analysis4417 * marks segments as Retransmissions when they are4418 * Out of Order from this perspective (#10725, #13843)4419 */4420 if((tcpd->ta->flags&TCP_A_SPURIOUS_RETRANSMISSION0x4000) == TCP_A_SPURIOUS_RETRANSMISSION0x4000 ||4421 ((tcpd->ta->flags&TCP_A_RETRANSMISSION0x0001) == TCP_A_RETRANSMISSION0x0001)) {4422 tcpd->ta->flags |= TCP_A_OLD_DATA0x8000;4423 }4424 }4425 if((tcpd->ta->flags&TCP_A_OLD_DATA0x8000) == TCP_A_OLD_DATA0x8000) {4426 const char* str = "Retransmitted ";4427 nbytes = tvb_reported_length_remaining(tvb, offset);4428 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,4429 nbytes, NULL((void*)0), "%sTCP segment data (%u byte%s)", str, nbytes,4430 plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s")));4431 goto clean_exit;4432 }4433 }4434 }4435 }4436 4437 if (reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001)) {4438 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4439 /* If there is a gap between this segment and any previous ones4440 * (that is, seqno is larger than the maximum expected seqno), then4441 * it is possibly an out-of-order segment. The very first segment4442 * is expected to be in-order though (otherwise captures starting4443 * in midst of a connection would never be reassembled).4444 * (maxnextseq is 0 if we have not seen a SYN packet, even with4445 * absolute sequence numbers.)4446 *4447 * Do not bother checking for OoO segments for streams that are4448 * reassembled at FIN, the order of segments before FIN does not4449 * matter as reordering and reassembly occurs at FIN.4450 */4451 4452 if (tcpd->fwd->maxnextseq) {4453 /* Segments may be missing due to packet loss (assume later4454 * retransmission) or out-of-order (assume it appears later).4455 *4456 * XXX: It would be nice to handle captures that have both4457 * out-of-order packets and some lost packets that are4458 * never retransmitted. But using the reverse flow ACK4459 * (like follow_tcp_tap_listener) or using a known end of4460 * a MSP (that we haven't fully received yet) to process a4461 * segment that starts right afterwards would both break the4462 * promise of in-order delivery, if a missing packet did arrive4463 * later, which is a problem for any state-based dissector4464 * (including TLS.)4465 */4466 4467 /* Whether the new segment has a gap from our latest contiguous4468 * sequence number. */4469 has_gap = LT_SEQ(tcpd->fwd->maxnextseq, seq)((gint32)((tcpd->fwd->maxnextseq) - (seq)) < 0);4470 }4471 4472 if (!has_gap) {4473 /* Update the maximum expected seqno if no SYN packet was seen4474 * before, or if the new segment succeeds previous segments. */4475 tcpd->fwd->maxnextseq = nxtseq;4476 4477 /* If there is no gap, look for any OOO packets that are now4478 * contiguous. */4479 msp = msp_add_out_of_order(pinfo, msp, tcpd, seq);4480 }4481 } else {4482 /* If we have visited this frame before, look for the frame in the4483 * list of unused out of order segments. Since we know the gap will4484 * never be filled, we could pass it to the subdissector, but4485 * we want to be consistent between passes.4486 */4487 ooo_segment_item *fd;4488 fd = wmem_new0(pinfo->pool, ooo_segment_item)((ooo_segment_item*)wmem_alloc0((pinfo->pool), sizeof(ooo_segment_item
)))
;4489 fd->frame = pinfo->num;4490 fd->seq = seq;4491 fd->len = nxtseq - seq;4492 if (wmem_list_find_custom(tcpd->fwd->ooo_segments, fd, compare_ooo_segment_item)) {4493 has_gap = TRUE(!(0));4494 }4495 }4496 }4497 4498 /* If we are not processing out of order, update the max nextseq value if4499 * is later than our current value (or our first value.)4500 */4501 if (!reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001)) {4502 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4503 if (LT_SEQ(tcpd->fwd->maxnextseq, nxtseq)((gint32)((tcpd->fwd->maxnextseq) - (nxtseq)) < 0) || tcpd->fwd->maxnextseq == 0) {4504 tcpd->fwd->maxnextseq = nxtseq;4505 }4506 }4507 }4508 4509 if (msp && LE_SEQ(msp->seq, seq)((gint32)((msp->seq) - (seq)) <= 0) && GT_SEQ(msp->nxtpdu, seq)((gint32)((seq) - (msp->nxtpdu)) < 0)) {4510 int len;4511 4512 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4513 msp->last_frame=pinfo->num;4514 msp->last_frame_time=pinfo->abs_ts;4515 }4516 4517 /* OK, this PDU was found, which means the segment continues4518 * a higher-level PDU and that we must desegment it.4519 */4520 if (msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001) {4521 /* The dissector asked for the entire segment */4522 len = tvb_captured_length_remaining(tvb, offset);4523 } else {4524 /* Wraparound is possible, so subtraction does not4525 * distribute across MIN(x, y)4526 */4527 len = MIN(nxtseq - seq, msp->nxtpdu - seq)(((nxtseq - seq) < (msp->nxtpdu - seq)) ? (nxtseq - seq
) : (msp->nxtpdu - seq))
;4528 }4529 last_fragment_len = len;4530 4531 4532 if (reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001)) {4533 /*4534 * If the previous segment requested more data (setting4535 * FD_PARTIAL_REASSEMBLY as the next segment length is unknown), but4536 * subsequently an OoO segment was received (for an earlier hole),4537 * then "fragment_add" would truncate the reassembled PDU to the end4538 * of this OoO segment. To prevent that, explicitly specify the MSP4539 * length before calling "fragment_add".4540 *4541 * When a subdissector requests reassembly at the end of the4542 * connection (DESEGMENT_UNTIL_FIN), then it is not4543 * possible for an earlier segment to complete reassembly4544 * (more_frags for fragment_add is always TRUE). Thus we do not4545 * have to worry about increasing the fragment length here.4546 */4547 fragment_reset_tot_len(&tcp_reassembly_table, pinfo,4548 msp->first_frame, msp,4549 MAX(seq + len, msp->nxtpdu)(((seq + len) > (msp->nxtpdu)) ? (seq + len) : (msp->
nxtpdu))
- msp->seq);4550 }4551 4552 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,4553 pinfo, msp->first_frame, msp,4554 seq - msp->seq, len,4555 (LT_SEQ (nxtseq,msp->nxtpdu)((gint32)((nxtseq) - (msp->nxtpdu)) < 0)) );4556 4557 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && ipfd_head4558 && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001) {4559 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001);4560 4561 /* If we consumed the entire segment there is no4562 * other pdu starting anywhere inside this segment.4563 * So update nxtpdu to point at least to the start4564 * of the next segment.4565 * (If the subdissector asks for even more data we4566 * will advance nxtpdu even further later down in4567 * the code.)4568 */4569 if (LT_SEQ(msp->nxtpdu, nxtseq)((gint32)((msp->nxtpdu) - (nxtseq)) < 0)) {4570 msp->nxtpdu = nxtseq;4571 }4572 }4573 4574 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4575 /* Remember when all segments are ready to avoid subsequent4576 * out-of-order packets from extending this MSP. If a subsdissector4577 * needs more segments, the flag will be cleared below. */4578 if (ipfd_head) {4579 msp->flags |= MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002;4580 }4581 }4582 4583 if( (msp->nxtpdu < nxtseq)4584 && (msp->nxtpdu >= seq)4585 && (len > 0)) {4586 another_pdu_follows=msp->nxtpdu - seq;4587 }4588 } else if (has_gap) {4589 /* This is an OOO segment with a gap and past the known end of4590 * the current MSP, if any. We don't know for certain which MSP4591 * it belongs to, and the reassembly functions don't let us remove4592 * fragment items added by mistake. Keep it around in a separate4593 * structure, and add it later.4594 *4595 * On the second and later passes, we know that this gap will4596 * never be filled in, so we could hand the segment to the4597 * subdissector anyway. However, we want dissection to be4598 * consistent between passes.4599 */4600 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4601 ooo_segment_item *fd;4602 fd = wmem_new0(wmem_file_scope(), ooo_segment_item)((ooo_segment_item*)wmem_alloc0((wmem_file_scope()), sizeof(ooo_segment_item
)))
;4603 fd->frame = pinfo->num;4604 fd->seq = seq;4605 fd->len = nxtseq - seq;4606 /* We only enter here if dissect_tcp set can_desegment,4607 * which means that these bytes exist. */4608 fd->data = tvb_memdup(wmem_file_scope(), tvb, offset, fd->len);4609 wmem_list_insert_sorted(tcpd->fwd->ooo_segments, fd, compare_ooo_segment_item);4610 }4611 ipfd_head = NULL((void*)0);4612 } else {4613 /* This segment was not found in our table, so it doesn't4614 * contain a continuation of a higher-level PDU.4615 * Call the normal subdissector.4616 */4617 4618 /*4619 * Supply the sequence number of this segment. We set this here4620 * because this segment could be after another in the same packet,4621 * in which case seq was incremented at the end of the loop.4622 */4623 tcpinfo->seq = seq;4624 4625 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,4626 sport, dport, 0, 0, FALSE(0), tcpd, tcpinfo);4627 4628 /* Unless it failed to dissect any data at all, the subdissector4629 * might have changed the addresses and/or ports. Save them, and4630 * set them back to the original values temporarily so that the4631 * fragment functions work correctly (including in any later PDU.)4632 *4633 * (If we didn't dissect any data, the subdissector *shouldn't*4634 * have changed the addresses or ports, so don't save them, but4635 * restore them just in case.)4636 */4637 if (!(pinfo->desegment_len && pinfo->desegment_offset == 0)) {4638 save_endpoint(pinfo, &new_endpoint);4639 }4640 restore_endpoint(pinfo, &orig_endpoint);4641 called_dissector = TRUE(!(0));4642 4643 /* Did the subdissector ask us to desegment some more data4644 * before it could handle the packet?4645 * If so we'll have to handle that later.4646 */4647 if(pinfo->desegment_len) {4648 must_desegment = TRUE(!(0));4649 4650 /*4651 * Set "deseg_offset" to the offset in "tvb"4652 * of the first byte of data that the4653 * subdissector didn't process.4654 */4655 deseg_offset = offset + pinfo->desegment_offset;4656 }4657 4658 /* Either no desegmentation is necessary, or this is4659 * segment contains the beginning but not the end of4660 * a higher-level PDU and thus isn't completely4661 * desegmented.4662 */4663 ipfd_head = NULL((void*)0);4664 }4665 4666 4667 /* is it completely desegmented? */4668 if (ipfd_head) {4669 /*4670 * Yes, we think it is.4671 * We only call subdissector for the last segment.4672 * Note that the last segment may include more than what4673 * we needed.4674 */4675 if (ipfd_head->reassembled_in == pinfo->num && ipfd_head->reas_in_layer_num == pinfo->curr_layer_num) {4676 /*4677 * OK, this is the last segment.4678 * Let's call the subdissector with the desegmented4679 * data.4680 */4681 tvbuff_t *next_tvb;4682 4683 /* create a new TVB structure for desegmented data */4684 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);4685 4686 /* add desegmented data to the data source list */4687 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");4688 4689 /*4690 * Supply the sequence number of the first of the4691 * reassembled bytes.4692 */4693 tcpinfo->seq = msp->seq;4694 4695 /* indicate that this is reassembled data */4696 tcpinfo->is_reassembled = TRUE(!(0));4697 4698 /* call subdissector */4699 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, sport,4700 dport, 0, 0, FALSE(0), tcpd, tcpinfo);4701 4702 /* Unless it failed to dissect any data at all, the subdissector4703 * might have changed the addresses and/or ports. Save them, and4704 * set them back to the original values temporarily so that the4705 * fragment functions work correctly (including in any later PDU.)4706 *4707 * (If we didn't dissect any data, the subdissector *shouldn't*4708 * have changed the addresses or ports, so don't save them, but4709 * restore them just in case.)4710 */4711 if (!(pinfo->desegment_len && pinfo->desegment_offset == 0)) {4712 save_endpoint(pinfo, &new_endpoint);4713 }4714 restore_endpoint(pinfo, &orig_endpoint);4715 called_dissector = TRUE(!(0));4716 4717 /*4718 * OK, did the subdissector think it was completely4719 * desegmented, or does it think we need even more4720 * data?4721 */4722 if (pinfo->desegment_len) {4723 /*4724 * "desegment_len" isn't 0, so it needs more data4725 * to fully dissect the current MSP. msp->nxtpdu was4726 * not accurate and needs to be updated.4727 *4728 * This can happen if a dissector asked for one4729 * more segment (but didn't know exactly how much data)4730 * or if segments were added out of order.4731 *4732 * This is opposed to the current MSP being completely4733 * desegmented, but the stuff at the end of the4734 * current frame past last_fragment_len starting a new4735 * higher-level PDU that may also need desegmentation.4736 * That case is handled on the next loop.4737 *4738 * We want to keep the same dissection and protocol layer4739 * numbers on subsequent passes.4740 *4741 * If "desegment_offset" is 0, then nothing in the reassembled4742 * TCP segments was dissected, so remove the data source.4743 */4744 if (pinfo->desegment_offset == 0) {4745 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4746 msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002;4747 }4748 remove_last_data_source(pinfo);4749 fragment_set_partial_reassembly(&tcp_reassembly_table,4750 pinfo, msp->first_frame,4751 msp);4752 } else {4753 /* If "desegment_offset" is not 0, then a PDU in the4754 * reassembled segments was dissected, but some stuff4755 * that was added previously is part of a later PDU.4756 */4757 if (LE_SEQ(msp->seq + pinfo->desegment_offset, seq)((gint32)((msp->seq + pinfo->desegment_offset) - (seq))
<= 0)
) {4758 /* If we don't use anything from the current frame's4759 * segment, then we can't split the msp. The frames of4760 * the earlier PDU weren't reassembled until now, so4761 * they need to point to a reassembled_in frame here4762 * or later.4763 *4764 * Since this segment is the first of newly contiguous4765 * segments, this means the subdissector is asking for4766 * fewer bytes than it did before.4767 * XXX: Report this as a dissector bug?4768 */4769 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4770 msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002;4771 }4772 fragment_set_partial_reassembly(&tcp_reassembly_table,4773 pinfo, msp->first_frame,4774 msp);4775 } else {4776 /* If we did use bytes from the current segment, then4777 * we want to split the MSP; the earlier part is4778 * dissected in this frame on the first pass, so for4779 * consistency we want to do so on future passes, but4780 * the latter part we cannot dissect until later.4781 * We only need to do this on the first pass; split_msp4782 * truncates the msp so we don't get here a second4783 * time.4784 */4785 /* nxtpdu adjustment for the new msp is the same. */4786 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4787 /* We don't need to clear MSP_FLAGS_GOT_ALL_SEGMENTS4788 * since we are spliting the MSP.4789 */4790 msp = split_msp(pinfo, msp, tcpd);4791 }4792 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);4793 }4794 }4795 4796 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4797 /* Update msp->nxtpdu to point to the new next4798 * pdu boundary.4799 * We only do this on the first pass, though we shouldn't4800 * get here on a second pass (since we truncated the msp.)4801 */4802 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT0x0fffffff) {4803 /* We want reassembly of at least one4804 * more segment so set the nxtpdu4805 * boundary to one byte into the next4806 * segment.4807 * This means that the next segment4808 * will complete reassembly even if it4809 * is only one single byte in length.4810 * If this is an OoO segment, then increment4811 * the MSP end.4812 */4813 msp->nxtpdu = MAX(seq + tvb_reported_length_remaining(tvb, offset), msp->nxtpdu)(((seq + tvb_reported_length_remaining(tvb, offset)) > (msp
->nxtpdu)) ? (seq + tvb_reported_length_remaining(tvb, offset
)) : (msp->nxtpdu))
+ 1;4814 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001;4815 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) {4816 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001;4817 /* This is not the first segment, and we thought the4818 * reassembly would be done now, but now know we must4819 * desgment until FIN. (E.g., HTTP Response with headers4820 * split across segments, and no Content-Length or4821 * Transfer-Encoding (RFC 7230, Section 3.3.3, case 7.)4822 * For the same reasons as below when we encounter4823 * DESEGMENT_UNTIL_FIN on the first segment, give4824 * msp->nxtpdu a big (but not too big) offset so4825 * reassembly will pick up the segments later.4826 */4827 msp->nxtpdu = msp->seq + 0x40000000;4828 } else {4829 if (seq + last_fragment_len >= msp->nxtpdu) {4830 /* This is the segment (overlapping) the end of4831 * the MSP.4832 */4833 msp->nxtpdu = seq + last_fragment_len + pinfo->desegment_len;4834 } else {4835 /* This is a segment before the end of the MSP, so4836 * it must be an out-of-order segment that completed4837 * the MSP. The requested additional data is4838 * relative to that end.4839 */4840 msp->nxtpdu += pinfo->desegment_len;4841 }4842 }4843 }4844 4845 /* Since we need at least some more data4846 * there can be no pdu following in the4847 * tail of this segment.4848 */4849 another_pdu_follows = 0;4850 offset += last_fragment_len;4851 seq += last_fragment_len;4852 if (tvb_captured_length_remaining(tvb, offset) > 0)4853 goto again;4854 } else {4855 /*4856 * Show the stuff in this TCP segment as4857 * just raw TCP segment data.4858 */4859 nbytes = another_pdu_follows > 04860 ? another_pdu_follows4861 : tvb_reported_length_remaining(tvb, offset);4862 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,4863 nbytes, NULL((void*)0), "TCP segment data (%u byte%s)", nbytes,4864 plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s")));4865 4866 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);4867 }4868 }4869 }4870 4871 if (must_desegment) {4872 /*4873 * The sequence number at which the stuff to be desegmented4874 * starts is the sequence number of the byte at an offset4875 * of "deseg_offset" into "tvb".4876 *4877 * The sequence number of the byte at an offset of "offset"4878 * is "seq", i.e. the starting sequence number of this4879 * segment, so the sequence number of the byte at4880 * "deseg_offset" is "seq + (deseg_offset - offset)".4881 */4882 deseg_seq = seq + (deseg_offset - offset);4883 4884 /* We have to create some structures in our table but4885 * this is something we only do the first time we see this4886 * packet. */4887 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4888 /* If the dissector requested "reassemble until FIN"4889 * just set this flag for the flow and let reassembly4890 * proceed at normal. We will check/pick up these4891 * reassembled PDUs later down in dissect_tcp() when checking4892 * for the FIN flag.4893 */4894 if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) {4895 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001;4896 }4897 if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)) {4898 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT0x0fffffff) {4899 /* The subdissector asked to reassemble using the4900 * entire next segment.4901 * Just ask reassembly for one more byte4902 * but set this msp flag so we can pick it up4903 * above.4904 */4905 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,4906 nxtseq+1, tcpd->fwd->multisegment_pdus);4907 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001;4908 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) {4909 /*4910 * The subdissector asked to reassemble at the end of the4911 * connection. That will be done in dissect_tcp, but here we4912 * have to ask reassembly to collect all future segments.4913 * Note that TCP_FLOW_REASSEMBLE_UNTIL_FIN was set before,4914 * this ensures that OoO detection is skipped.4915 * The exact nxtpdu offset does not matter, but it should be4916 * smaller than half of the maximum 32-bit unsigned integer4917 * to allow detection of sequence number wraparound, and4918 * larger than the largest possible stream size. Hopefully4919 * 1GiB (0x40000000 bytes) should be enough.4920 */4921 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,4922 nxtseq+0x40000000, tcpd->fwd->multisegment_pdus);4923 } else {4924 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,4925 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);4926 }4927 4928 /* add this segment as the first one for this new pdu */4929 fragment_add(&tcp_reassembly_table, tvb, deseg_offset,4930 pinfo, msp->first_frame, msp,4931 0, nxtseq - deseg_seq,4932 LT_SEQ(nxtseq, msp->nxtpdu)((gint32)((nxtseq) - (msp->nxtpdu)) < 0));4933 }4934 } else {4935 /* If this is not the first time we have seen the packet, then4936 * the MSP should already be created. Retrieve it to see if we4937 * know what later frame the PDU is reassembled in.4938 */4939 if (tcpd && (msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, deseg_seq))) {4940 ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);4941 }4942 }4943 }4944 4945 if (!called_dissector || pinfo->desegment_len != 0) {4946 if (ipfd_head != NULL((void*)0) && ipfd_head->reassembled_in != 0 &&4947 ipfd_head->reassembled_in != pinfo->num &&4948 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY0x0040)) {4949 /*4950 * We know what other frame this PDU is reassembled in;4951 * let the user know.4952 */4953 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,4954 0, ipfd_head->reassembled_in);4955 proto_item_set_generated(item);4956 }4957 4958 /*4959 * Either we didn't call the subdissector at all (i.e.,4960 * this is a segment that contains the middle of a4961 * higher-level PDU, but contains neither the beginning4962 * nor the end), or the subdissector couldn't dissect it4963 * all, as some data was missing (i.e., it set4964 * "pinfo->desegment_len" to the amount of additional4965 * data it needs).4966 */4967 if (pinfo->desegment_offset == 0) {4968 /*4969 * It couldn't, in fact, dissect any of it (the4970 * first byte it couldn't dissect is at an offset4971 * of "pinfo->desegment_offset" from the beginning4972 * of the payload, and that's 0).4973 * Just mark this as TCP.4974 */4975 if (first_pdu && ipfd_head != NULL((void*)0) && ipfd_head->reassembled_in != 0) {4976 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[TCP PDU reassembled in %u]",4977 ipfd_head->reassembled_in);4978 }4979 }4980 4981 /*4982 * Show what's left in the packet as just raw TCP segment4983 * data. (It's possible that another PDU follows in the case4984 * of an out of order frame that is part of two MSPs.)4985 * XXX - remember what protocol the last subdissector4986 * was, and report it as a continuation of that, instead?4987 */4988 nbytes = another_pdu_follows ? another_pdu_follows : tvb_reported_length_remaining(tvb, deseg_offset);4989 4990 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, deseg_offset,4991 nbytes, NULL((void*)0), "TCP segment data (%u byte%s)", nbytes,4992 plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s")));4993 }4994 pinfo->can_desegment = 0;4995 pinfo->desegment_offset = 0;4996 pinfo->desegment_len = 0;4997 4998 if(another_pdu_follows) {4999 /* there was another pdu following this one. */5000 pinfo->can_desegment = 2;5001 /* we also have to prevent the dissector from changing the5002 * PROTOCOL and INFO columns since what follows may be an5003 * incomplete PDU and we don't want it be changed back from5004 * <Protocol> to <TCP>5005 */5006 col_set_fence(pinfo->cinfo, COL_INFO);5007 cleared_writable |= col_get_writable(pinfo->cinfo, COL_PROTOCOL);5008 col_set_writable(pinfo->cinfo, COL_PROTOCOL, FALSE(0));5009 first_pdu = FALSE(0);5010 offset += another_pdu_follows;5011 seq += another_pdu_follows;5012 goto again;5013 } else {5014 /* remove any blocking set above otherwise the5015 * proto,colinfo tap will break5016 */5017 if(cleared_writable) {5018 col_set_writable(pinfo->cinfo, COL_PROTOCOL, TRUE(!(0)));5019 }5020 }5021 5022clean_exit:5023 /* Restore the addresses and ports to whatever they were after5024 * the last segment that successfully dissected some data, if any.5025 */5026 restore_endpoint(pinfo, &new_endpoint);5027}5028 5029void5030tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,5031 gboolean proto_desegment, guint fixed_len,5032 guint (*get_pdu_len)(packet_info *, tvbuff_t *, int, void*),5033 dissector_t dissect_pdu, void* dissector_data)5034{5035 volatile int offset = 0;5036 int offset_before;5037 guint captured_length_remaining;5038 volatile guint plen;5039 guint length;5040 tvbuff_t *next_tvb;5041 proto_item *item=NULL((void*)0);5042 const char *saved_proto;5043 guint8 curr_layer_num;5044 wmem_list_frame_t *frame;5045 5046 tcp_endpoint_t orig_endpoint;5047 5048 save_endpoint(pinfo, &orig_endpoint);5049 5050 while (tvb_reported_length_remaining(tvb, offset) > 0) {5051 /*5052 * We use "tvb_ensure_captured_length_remaining()" to make5053 * sure there actually *is* data remaining. The protocol5054 * we're handling could conceivably consists of a sequence of5055 * fixed-length PDUs, and therefore the "get_pdu_len" routine5056 * might not actually fetch anything from the tvbuff, and thus5057 * might not cause an exception to be thrown if we've run past5058 * the end of the tvbuff.5059 *5060 * This means we're guaranteed that "captured_length_remaining" is positive.5061 */5062 captured_length_remaining = tvb_ensure_captured_length_remaining(tvb, offset);5063 5064 /*5065 * Can we do reassembly?5066 */5067 if (proto_desegment && pinfo->can_desegment) {5068 /*5069 * Yes - is the fixed-length part of the PDU split across segment5070 * boundaries?5071 */5072 if (captured_length_remaining < fixed_len) {5073 /*5074 * Yes. Tell the TCP dissector where the data for this message5075 * starts in the data it handed us and that we need "some more5076 * data." Don't tell it exactly how many bytes we need because5077 * if/when we ask for even more (after the header) that will5078 * break reassembly.5079 */5080 pinfo->desegment_offset = offset;5081 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;5082 return;5083 }5084 }5085 5086 /*5087 * Get the length of the PDU.5088 */5089 plen = (*get_pdu_len)(pinfo, tvb, offset, dissector_data);5090 if (plen == 0) {5091 /*5092 * Support protocols which have a variable length which cannot5093 * always be determined within the given fixed_len.5094 */5095 /*5096 * If another segment was requested but we can't do reassembly,5097 * abort and warn about the unreassembled packet.5098 */5099 THROW_ON(!(proto_desegment && pinfo->can_desegment), FragmentBoundsError)do { if ((!(proto_desegment && pinfo->can_desegment
))) except_throw(1, (4), ((void*)0)); } while (0)
;5100 /*5101 * Tell the TCP dissector where the data for this message5102 * starts in the data it handed us, and that we need one5103 * more segment, and return.5104 */5105 pinfo->desegment_offset = offset;5106 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;5107 return;5108 }5109 if (plen < fixed_len) {5110 /*5111 * Either:5112 *5113 * 1) the length value extracted from the fixed-length portion5114 * doesn't include the fixed-length portion's length, and5115 * was so large that, when the fixed-length portion's5116 * length was added to it, the total length overflowed;5117 *5118 * 2) the length value extracted from the fixed-length portion5119 * includes the fixed-length portion's length, and the value5120 * was less than the fixed-length portion's length, i.e. it5121 * was bogus.5122 *5123 * Report this as a bounds error.5124 */5125 show_reported_bounds_error(tvb, pinfo, tree);5126 return;5127 }5128 5129 /* give a hint to TCP where the next PDU starts5130 * so that it can attempt to find it in case it starts5131 * somewhere in the middle of a segment.5132 */5133 if(!pinfo->fd->visited && tcp_analyze_seq) {5134 guint remaining_bytes;5135 remaining_bytes = tvb_reported_length_remaining(tvb, offset);5136 if(plen>remaining_bytes) {5137 pinfo->want_pdu_tracking=2;5138 pinfo->bytes_until_next_pdu=plen-remaining_bytes;5139 }5140 }5141 5142 /*5143 * Can we do reassembly?5144 */5145 if (proto_desegment && pinfo->can_desegment) {5146 /*5147 * Yes - is the PDU split across segment boundaries?5148 */5149 if (captured_length_remaining < plen) {5150 /*5151 * Yes. Tell the TCP dissector where the data for this message5152 * starts in the data it handed us, and how many more bytes we5153 * need, and return.5154 */5155 pinfo->desegment_offset = offset;5156 pinfo->desegment_len = plen - captured_length_remaining;5157 return;5158 }5159 }5160 5161 curr_layer_num = pinfo->curr_layer_num-1;5162 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));5163 while (frame && (proto_tcp != (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))((guint) (gulong) (wmem_list_frame_data(frame))))) {5164 frame = wmem_list_frame_prev(frame);5165 curr_layer_num--;5166 }5167#if 05168 if (captured_length_remaining >= plen || there are more packets)5169 {5170#endif5171 /*5172 * Display the PDU length as a field5173 */5174 item=proto_tree_add_uint((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_tcp, curr_layer_num),5175 hf_tcp_pdu_size,5176 tvb, offset, plen, plen);5177 proto_item_set_generated(item);5178#if 05179 } else {5180 item = proto_tree_add_expert_format((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_tcp, curr_layer_num),5181 tvb, offset, -1,5182 "PDU Size: %u cut short at %u",plen,captured_length_remaining);5183 proto_item_set_generated(item);5184 }5185#endif5186 5187 /*5188 * Construct a tvbuff containing the amount of the payload we have5189 * available. Make its reported length the amount of data in the PDU.5190 */5191 length = captured_length_remaining;5192 if (length > plen)5193 length = plen;5194 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, plen);5195 if (!(proto_desegment && pinfo->can_desegment)) {5196 if (plen > length) {5197 /* If we can't do reassembly but the PDU is split across5198 * segment boundaries, mark the tvbuff as a fragment so5199 * we throw FragmentBoundsError instead of malformed5200 * errors.5201 */5202 tvb_set_fragment(next_tvb);5203 }5204 }5205 5206 5207 /*5208 * Dissect the PDU.5209 *5210 * If it gets an error that means there's no point in5211 * dissecting any more PDUs, rethrow the exception in5212 * question.5213 *5214 * If it gets any other error, report it and continue, as that5215 * means that PDU got an error, but that doesn't mean we should5216 * stop dissecting PDUs within this frame or chunk of reassembled5217 * data.5218 */5219 saved_proto = pinfo->current_proto;5220 restore_endpoint(pinfo, &orig_endpoint);5221 TRY{ except_t *volatile exc; volatile int except_state = 0; static
const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode
except_sn; struct except_catch except_ch; except_setup_try(&
except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch
.except_jmp)) *(&exc) = &except_ch.except_obj; else *
(&exc) = 0; if(except_state & 1) except_state |= 2; except_state
&= ~1; if (except_state == 0 && exc == 0)
{5222 (*dissect_pdu)(next_tvb, pinfo, tree, dissector_data);5223 }5224 CATCH_NONFATAL_ERRORSif (except_state == 0 && exc != 0 && (exc->
except_id.except_code == (3) || exc->except_id.except_code
== (2) || exc->except_id.except_code == (7) || exc->except_id
.except_code == (9)) && (except_state|=1))
{5225 show_exception(tvb, pinfo, tree, EXCEPT_CODE((exc)->except_id.except_code), GET_MESSAGE((exc)->except_message));5226 5227 /*5228 * Restore the saved protocol as well; we do this after5229 * show_exception(), so that the "Malformed packet" indication5230 * shows the protocol for which dissection failed.5231 */5232 pinfo->current_proto = saved_proto;5233 }5234 ENDTRYif(!(except_state&1) && exc != 0) except_rethrow(
exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}
;5235 5236 /*5237 * Step to the next PDU.5238 * Make sure we don't overflow.5239 */5240 offset_before = offset;5241 offset += plen;5242 if (offset <= offset_before)5243 break;5244 }5245}5246 5247static void5248tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val)5249{5250 /* fstr(" %s=%u", abbrev, val) */5251 col_append_str_uint(pinfo->cinfo, COL_INFO, abbrev, val, " ");5252}5253 5254static void5255tcp_info_append_hex_uint(packet_info *pinfo, const char *abbrev, guint32 val)5256{5257 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%X", abbrev, val);5258}5259 5260static gboolean5261tcp_option_len_check(proto_item* length_item, packet_info *pinfo, guint len, guint optlen)5262{5263 if (len != optlen) {5264 /* Bogus - option length isn't what it's supposed to be for this option. */5265 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,5266 "option length should be %u", optlen);5267 return FALSE(0);5268 }5269 5270 return TRUE(!(0));5271}5272 5273static int5274dissect_tcpopt_unknown(tvbuff_t *tvb, packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, void* data _U___attribute__((unused)))5275{5276 proto_item *item;5277 proto_tree *exp_tree;5278 int offset = 0, optlen = tvb_reported_length(tvb);5279 5280 item = proto_tree_add_item(tree, proto_tcp_option_unknown, tvb, offset, -1, ENC_NA0x00000000);5281 exp_tree = proto_item_add_subtree(item, ett_tcp_unknown_opt);5282 5283 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5284 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);5285 if (optlen > 2)5286 proto_tree_add_item(exp_tree, hf_tcp_option_unknown_payload, tvb, offset + 2, optlen - 2, ENC_NA0x00000000);5287 5288 return tvb_captured_length(tvb);5289}5290 5291static int5292dissect_tcpopt_default_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, int ett)5293{5294 proto_item *item;5295 proto_tree *exp_tree;5296 proto_item *length_item;5297 int offset = 0;5298 5299 item = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA0x00000000);5300 exp_tree = proto_item_add_subtree(item, ett);5301 5302 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5303 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);5304 5305 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), 2))5306 return tvb_captured_length(tvb);5307 5308 return tvb_captured_length(tvb);5309}5310 5311static int5312dissect_tcpopt_recbound(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))5313{5314 return dissect_tcpopt_default_option(tvb, pinfo, tree, proto_tcp_option_scpsrec, ett_tcp_opt_recbound);5315}5316 5317static int5318dissect_tcpopt_correxp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))5319{5320 return dissect_tcpopt_default_option(tvb, pinfo, tree, proto_tcp_option_scpscor, ett_tcp_opt_scpscor);5321}5322 5323static void5324dissect_tcpopt_tfo_payload(tvbuff_t *tvb, int offset, guint optlen,5325 packet_info *pinfo, proto_tree *exp_tree, void *data)5326{5327 proto_item *ti;5328 struct tcpheader *tcph = (struct tcpheader*)data;5329 struct tcp_analysis *tcpd;5330 5331 if (optlen == 2) {5332 /* Fast Open Cookie Request */5333 proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie_request,5334 tvb, offset, 2, ENC_NA0x00000000);5335 col_append_str(pinfo->cinfo, COL_INFO, " TFO=R");5336 } else if (optlen > 2) {5337 /* Fast Open Cookie */5338 ti = proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie,5339 tvb, offset + 2, optlen - 2, ENC_NA0x00000000);5340 col_append_str(pinfo->cinfo, COL_INFO, " TFO=C");5341 if ((tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == TH_SYN0x0002) {5342 expert_add_info(pinfo, ti, &ei_tcp_analysis_tfo_syn);5343 5344 /* Is this a SYN with data and the cookie? */5345 if (tcph->th_have_seglen && tcph->th_seglen) {5346 tcpd = get_tcp_conversation_data(NULL((void*)0), pinfo);5347 if (tcpd) {5348 tcpd->tfo_syn_data = 1;5349 }5350 }5351 }5352 }5353}5354 5355static int5356dissect_tcpopt_tfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))5357{5358 proto_item *item;5359 proto_tree *exp_tree;5360 int offset = 0;5361 5362 item = proto_tree_add_item(tree, proto_tcp_option_tfo, tvb, offset, -1, ENC_NA0x00000000);5363 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);5364 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5365 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);5366 5367 dissect_tcpopt_tfo_payload(tvb, offset, tvb_reported_length(tvb), pinfo, exp_tree, data);5368 return tvb_captured_length(tvb);5369}5370 5371/*5372 * TCP ACK Rate Request option is based on5373 * https://datatracker.ietf.org/doc/html/draft-gomez-tcpm-ack-rate-request-065374 */5375 5376#define TCPOPT_TARR_RATE_MASK0xfe 0xfe5377#define TCPOPT_TARR_RESERVED_MASK0x01 0x015378#define TCPOPT_TARR_RATE_SHIFT1 15379 5380static void5381dissect_tcpopt_tarr_data(tvbuff_t *tvb, int data_offset, guint data_len,5382 packet_info *pinfo, proto_tree *tree, proto_item *item, void *data _U___attribute__((unused)))5383{5384 guint8 rate;5385 5386 switch (data_len) {5387 case 0:5388 col_append_str(pinfo->cinfo, COL_INFO, " TARR");5389 break;5390 case 1:5391 rate = (tvb_get_guint8(tvb, data_offset) & TCPOPT_TARR_RATE_MASK0xfe) >> TCPOPT_TARR_RATE_SHIFT1;5392 proto_tree_add_item(tree, hf_tcp_option_tarr_rate, tvb, data_offset, 1, ENC_BIG_ENDIAN0x00000000);5393 proto_tree_add_item(tree, hf_tcp_option_tarr_reserved, tvb, data_offset, 1, ENC_BIG_ENDIAN0x00000000);5394 tcp_info_append_uint(pinfo, "TARR", rate);5395 proto_item_append_text(item, " %u", rate);5396 break;5397 }5398}5399 5400static void5401dissect_tcpopt_acc_ecn_data(tvbuff_t *tvb, int data_offset, guint data_len,5402 gboolean is_order_0, packet_info *pinfo, proto_tree *tree, proto_item *item, void *data _U___attribute__((unused)))5403{5404 struct tcp_analysis *tcpd;5405 guint32 ee0b, eceb, ee1b;5406 5407 switch (data_len) {5408 case 0:5409 col_append_str(pinfo->cinfo, COL_INFO, " AccECN");5410 break;5411 case 3:5412 if (is_order_0) {5413 ee0b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000);5414 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000);5415 proto_item_append_text(item, " (Order 0): EE0B %u", ee0b);5416 tcp_info_append_uint(pinfo, "EE0B", ee0b);5417 } else {5418 ee1b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000);5419 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000);5420 proto_item_append_text(item, " (Order 1): EE1B %u", ee1b);5421 tcp_info_append_uint(pinfo, "EE1B", ee1b);5422 }5423 break;5424 case 6:5425 if (is_order_0) {5426 ee0b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000);5427 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000);5428 tcp_info_append_uint(pinfo, "EE0B", ee0b);5429 } else {5430 ee1b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000);5431 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000);5432 tcp_info_append_uint(pinfo, "EE1B", ee1b);5433 }5434 eceb = tvb_get_guint24(tvb, data_offset + 3, ENC_BIG_ENDIAN0x00000000);5435 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_eceb, tvb, data_offset + 3, 3, ENC_BIG_ENDIAN0x00000000);5436 tcp_info_append_uint(pinfo, "ECEB", eceb);5437 if (is_order_0) {5438 proto_item_append_text(item, " (Order 0): EE0B %u, ECEB %u", ee0b, eceb);5439 } else {5440 proto_item_append_text(item, " (Order 1): EE1B %u, ECEB %u", ee1b, eceb);5441 }5442 break;5443 case 9:5444 if (is_order_0) {5445 ee0b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000);5446 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000);5447 tcp_info_append_uint(pinfo, "EE0B", ee0b);5448 } else {5449 ee1b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000);5450 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000);5451 tcp_info_append_uint(pinfo, "EE1B", ee1b);5452 }5453 eceb = tvb_get_guint24(tvb, data_offset + 3, ENC_BIG_ENDIAN0x00000000);5454 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_eceb, tvb, data_offset + 3, 3, ENC_BIG_ENDIAN0x00000000);5455 tcp_info_append_uint(pinfo, "ECEB", eceb);5456 if (is_order_0) {5457 ee1b = tvb_get_guint24(tvb, data_offset + 6, ENC_BIG_ENDIAN0x00000000);5458 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset + 6, 3, ENC_BIG_ENDIAN0x00000000);5459 tcp_info_append_uint(pinfo, "EE1B", ee1b);5460 proto_item_append_text(item, " (Order 0): EE0B %u, ECEB %u, EE1B %u", ee0b, eceb, ee1b);5461 } else {5462 ee0b = tvb_get_guint24(tvb, data_offset + 6, ENC_BIG_ENDIAN0x00000000);5463 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset + 6, 3, ENC_BIG_ENDIAN0x00000000);5464 tcp_info_append_uint(pinfo, "EE0B", ee0b);5465 proto_item_append_text(item, " (Order 1): EE1B %u, ECEB %u, EE0B %u", ee1b, eceb, ee0b);5466 }5467 break;5468 }5469 tcpd = get_tcp_conversation_data(NULL((void*)0), pinfo);5470 if (tcpd != NULL((void*)0)) {5471 tcpd->had_acc_ecn_option = TRUE(!(0));5472 }5473}5474 5475static int5476dissect_tcpopt_acc_ecn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))5477{5478 proto_item *length_item, *item;5479 proto_tree *acc_ecn_tree;5480 int offset;5481 guint8 kind, length;5482 5483 offset = 0;5484 item = proto_tree_add_item(tree, proto_tcp_option_acc_ecn, tvb, offset, -1, ENC_NA0x00000000);5485 acc_ecn_tree = proto_item_add_subtree(item, ett_tcp_option_acc_ecn);5486 kind = tvb_get_guint8(tvb, offset);5487 proto_tree_add_item(acc_ecn_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5488 offset += 1;5489 length = tvb_get_guint8(tvb, offset);5490 length_item = proto_tree_add_item(acc_ecn_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5491 offset += 1;5492 if (length != 2 && length != 5 && length != 8 && length != 11) {5493 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,5494 "option length should be 2, 5, 8, or 11 instead of %u", length);5495 } else {5496 dissect_tcpopt_acc_ecn_data(tvb, offset, length - 2, kind == TCPOPT_ACC_ECN_00xac, pinfo, acc_ecn_tree, item, data);5497 }5498 return tvb_captured_length(tvb);5499}5500 5501static int5502dissect_tcpopt_exp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))5503{5504 proto_item *item, *length_item;5505 proto_tree *exp_tree;5506 guint16 exid;5507 guint8 kind;5508 gint offset = 0, optlen = tvb_reported_length(tvb);5509 5510 item = proto_tree_add_item(tree, proto_tcp_option_exp, tvb, offset, -1, ENC_NA0x00000000);5511 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);5512 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5513 kind = tvb_get_guint8(tvb, offset);5514 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);5515 if (tcp_exp_options_rfc6994) {5516 if (optlen >= TCPOLEN_EXP_MIN4) {5517 exid = tvb_get_ntohs(tvb, offset + 2);5518 proto_tree_add_item(exp_tree, hf_tcp_option_exp_exid, tvb,5519 offset + 2, 2, ENC_BIG_ENDIAN0x00000000);5520 proto_item_append_text(item, ": %s", val_to_str_const(exid, tcp_exid_vs, "Unknown"));5521 switch (exid) {5522 case TCPEXID_TARR0x00ac:5523 if (optlen != 4 && optlen != 5) {5524 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,5525 "option length should be 4 or 5 instead of %d",5526 optlen);5527 } else {5528 dissect_tcpopt_tarr_data(tvb, offset + 4, optlen - 4,5529 pinfo, exp_tree, item, data);5530 }5531 break;5532 case 0xACC0: /* draft-ietf-tcpm-accurate-ecn-20 */5533 case 0xACC1:5534 if (optlen != 4 && optlen != 7 && optlen != 10 && optlen != 13) {5535 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,5536 "option length should be 4, 7, 10, or 13 instead of %d",5537 optlen);5538 } else {5539 proto_item_append_text(item, ": Accurate ECN");5540 dissect_tcpopt_acc_ecn_data(tvb, offset + 4, optlen - 4,5541 exid == 0xACC0, pinfo, exp_tree,5542 item, data);5543 }5544 break;5545 case TCPEXID_FO0xf989:5546 dissect_tcpopt_tfo_payload(tvb, offset + 2, optlen - 2, pinfo, exp_tree, data);5547 break;5548 default:5549 if (optlen > TCPOLEN_EXP_MIN4) {5550 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,5551 offset + TCPOLEN_EXP_MIN4,5552 optlen - TCPOLEN_EXP_MIN4, ENC_NA0x00000000);5553 }5554 tcp_info_append_hex_uint(pinfo, "ExID", exid);5555 break;5556 }5557 } else {5558 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,5559 "option length %u smaller than 4", optlen);5560 }5561 } else {5562 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,5563 offset + 2, optlen - 2, ENC_NA0x00000000);5564 tcp_info_append_uint(pinfo, "Exp", (kind == TCPOPT_EXP_FD0xfd) ? 1 : 2);5565 }5566 return tvb_captured_length(tvb);5567}5568 5569static int5570dissect_tcpopt_sack_perm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)5571{5572 proto_item *item;5573 proto_tree *exp_tree;5574 proto_item *length_item;5575 int offset = 0;5576 struct tcpheader *tcph = (struct tcpheader *)data;5577 5578 item = proto_tree_add_item(tree, proto_tcp_option_sack_perm, tvb, offset, -1, ENC_NA0x00000000);5579 exp_tree = proto_item_add_subtree(item, ett_tcp_option_sack_perm);5580 5581 if (!(tcph->th_flags & TH_SYN0x0002))5582 {5583 expert_add_info(pinfo, item, &ei_tcp_option_sack_perm_present);5584 }5585 5586 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5587 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);5588 5589 col_append_str(pinfo->cinfo, COL_INFO, " SACK_PERM");5590 5591 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SACK_PERM2))5592 return tvb_captured_length(tvb);5593 5594 return tvb_captured_length(tvb);5595}5596 5597static int5598dissect_tcpopt_mss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)5599{5600 proto_item *item;5601 proto_tree *exp_tree;5602 proto_item *length_item;5603 int offset = 0;5604 struct tcpheader *tcph = (struct tcpheader *)data;5605 guint32 mss;5606 5607 item = proto_tree_add_item(tree, proto_tcp_option_mss, tvb, offset, -1, ENC_NA0x00000000);5608 exp_tree = proto_item_add_subtree(item, ett_tcp_option_mss);5609 5610 if (!(tcph->th_flags & TH_SYN0x0002))5611 {5612 expert_add_info(pinfo, item, &ei_tcp_option_mss_present);5613 }5614 5615 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5616 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);5617 5618 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_MSS4))5619 return tvb_captured_length(tvb);5620 5621 proto_tree_add_item_ret_uint(exp_tree, hf_tcp_option_mss_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000, &mss);5622 proto_item_append_text(item, ": %u bytes", mss);5623 tcp_info_append_uint(pinfo, "MSS", mss);5624 5625 return tvb_captured_length(tvb);5626}5627 5628/* The window scale extension is defined in RFC 1323 */5629static int5630dissect_tcpopt_wscale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))5631{5632 guint8 val;5633 guint32 shift;5634 proto_item *wscale_pi, *shift_pi, *gen_pi;5635 proto_tree *wscale_tree;5636 proto_item *length_item;5637 int offset = 0;5638 struct tcp_analysis *tcpd;5639 5640 conversation_t *stratconv = find_conversation_strat(pinfo);5641 tcpd=get_tcp_conversation_data(stratconv,pinfo);5642 5643 wscale_pi = proto_tree_add_item(tree, proto_tcp_option_wscale, tvb, offset, -1, ENC_NA0x00000000);5644 wscale_tree = proto_item_add_subtree(wscale_pi, ett_tcp_option_wscale);5645 5646 proto_tree_add_item(wscale_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5647 offset += 1;5648 5649 length_item = proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5650 offset += 1;5651 5652 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_WINDOW3))5653 return tvb_captured_length(tvb);5654 5655 shift_pi = proto_tree_add_item_ret_uint(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &shift);5656 if (shift > 14) {5657 /* RFC 1323: "If a Window Scale option is received with a shift.cnt5658 * value exceeding 14, the TCP should log the error but use 14 instead5659 * of the specified value." */5660 shift = 14;5661 expert_add_info(pinfo, shift_pi, &ei_tcp_option_wscale_shift_invalid);5662 }5663 5664 gen_pi = proto_tree_add_uint(wscale_tree, hf_tcp_option_wscale_multiplier, tvb,5665 offset, 1, 1 << shift);5666 proto_item_set_generated(gen_pi);5667 val = tvb_get_guint8(tvb, offset);5668 5669 proto_item_append_text(wscale_pi, ": %u (multiply by %u)", val, 1 << shift);5670 5671 tcp_info_append_uint(pinfo, "WS", 1 << shift);5672 5673 if(!pinfo->fd->visited) {5674 pdu_store_window_scale_option(shift, tcpd);5675 }5676 5677 return tvb_captured_length(tvb);5678}5679 5680static int5681dissect_tcpopt_sack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)5682{5683 proto_tree *field_tree = NULL((void*)0);5684 proto_item *tf, *ti;5685 guint32 leftedge, rightedge;5686 struct tcp_analysis *tcpd=NULL((void*)0);5687 struct tcpheader *tcph = (struct tcpheader *)data;

1

'tcph' initialized here

5688 guint32 base_ack=0;5689 guint num_sack_ranges = 0;5690 int offset = 0;5691 int sackoffset;5692 int optlen = tvb_reported_length(tvb);5693 5694 /*5695 * SEQ analysis is the condition for both relative analysis obviously,5696 * and SACK handling for the in-flight update5697 */5698 if(tcp_analyze_seq) {

2

Assuming 'tcp_analyze_seq' is false

5699 /* find(or create if needed) the conversation for this tcp session */5700 tcpd=get_tcp_conversation_data(NULL((void*)0),pinfo);5701 5702 if (tcpd) {5703 if (tcp_relative_seq) {5704 base_ack=tcpd->rev->base_seq;5705 }5706 5707 /*5708 * initialize the number of SACK blocks to 0, it will be5709 * updated some lines later5710 */5711 if (tcp_track_bytes_in_flight && tcpd->fwd->tcp_analyze_seq_info) {5712 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = 0;5713 }5714 }5715 }5716 5717 /* Late discovery of a 'false' Window Update in presence of SACK option,5718 * which means we are dealing with a Dup ACK rather than a Window Update.5719 * Classify accordingly by removing the UPDATE and adding the DUP flags.5720 * Mostly a copy/paste from tcp_analyze_sequence_number(), ensure consistency5721 * whenever the latter changes.5722 * see Issue #149375723 */5724 if( tcp_analyze_seq

2.1

'tcp_analyze_seq' is false
&& tcpd && tcpd->ta && tcpd->ta->flags&TCP_A_WINDOW_UPDATE0x0800 ) {5725 5726 /* MPTCP tolerates duplicate acks in some circ*mstances, see RFC 8684 4. */5727 if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) {5728 /* just ignore this DUPLICATE ACK */5729 } else {5730 tcpd->fwd->tcp_analyze_seq_info->dupacknum++;5731 5732 /* no initialization required of the tcpd->ta as this code would5733 * be unreachable otherwise5734 */5735 tcpd->ta->flags &= ~TCP_A_WINDOW_UPDATE0x0800;5736 tcpd->ta->flags |= TCP_A_DUPLICATE_ACK0x0010;5737 tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum;5738 tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack;5739 }5740 }5741 5742 ti = proto_tree_add_item(tree, proto_tcp_option_sack, tvb, offset, -1, ENC_NA0x00000000);5743 field_tree = proto_item_add_subtree(ti, ett_tcp_option_sack);5744 5745 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,5746 offset, 1, ENC_BIG_ENDIAN0x00000000);5747 proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,5748 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);5749 5750 offset += 2; /* skip past type and length */5751 optlen -= 2; /* subtract size of type and length */5752 5753 sackoffset = offset;5754 while (optlen > 0) {

3

Assuming 'optlen' is > 0

4

Loop condition is true. Entering loop body

13

Assuming 'optlen' is <= 0

14

Loop condition is false. Execution continues on line 5800

5755 if (optlen < 4) {

5

Assuming 'optlen' is >= 4

6

Taking false branch

5756 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_suboption_malformed, tvb, offset, optlen);5757 break;5758 }5759 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;5760 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,5761 offset, 4, leftedge,5762 "left edge = %u%s", leftedge,5763 (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");

7

Assuming 'tcp_analyze_seq' is false

5764 optlen -= 4;5765 if (optlen < 4) {

8

Assuming 'optlen' is >= 4

9

Taking false branch

5766 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_suboption_malformed, tvb, offset, optlen);5767 break;5768 }5769 /* XXX - check whether it goes past end of packet */5770 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;5771 optlen -= 4;5772 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,5773 offset+4, 4, rightedge,5774 "right edge = %u%s", rightedge,5775 (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");

10

Assuming 'tcp_analyze_seq' is false

5776 tcp_info_append_uint(pinfo, "SLE", leftedge);5777 tcp_info_append_uint(pinfo, "SRE", rightedge);5778 num_sack_ranges++;5779 5780 /* Store blocks for BiF analysis */5781 if (tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info && tcp_track_bytes_in_flight && num_sack_ranges < MAX_TCP_SACK_RANGES4) {

11

Assuming 'tcp_analyze_seq' is false

5782 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = num_sack_ranges;5783 tcpd->fwd->tcp_analyze_seq_info->sack_left_edge[num_sack_ranges] = leftedge;5784 tcpd->fwd->tcp_analyze_seq_info->sack_right_edge[num_sack_ranges] = rightedge;5785 }5786 5787 /* Update tap info */5788 if (tcph != NULL((void*)0) && (tcph->num_sack_ranges < MAX_TCP_SACK_RANGES4)) {

12

Assuming 'tcph' is equal to NULL

5789 tcph->sack_left_edge[tcph->num_sack_ranges] = leftedge;5790 tcph->sack_right_edge[tcph->num_sack_ranges] = rightedge;5791 tcph->num_sack_ranges++;5792 }5793 5794 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);5795 offset += 8;5796 }5797 5798 5799 /* Show number of SACK ranges in this option as a generated field */5800 tf = proto_tree_add_uint(field_tree, hf_tcp_option_sack_range_count,5801 tvb, 0, 0, num_sack_ranges);5802 proto_item_set_generated(tf);5803 5804 /* RFC 2883 "An Extension to the Selective Acknowledgement (SACK) Option for TCP" aka "D-SACK"5805 * Section 45806 * Conditions: Either the first sack-block is inside the already acknowledged range or5807 * the first sack block is inside the second sack block.5808 *5809 * Maybe add later:5810 * (1) A D-SACK block is only used to report a duplicate contiguous sequence of data received by5811 * the receiver in the most recent packet.5812 */5813 if (LE_SEQ(tcph->sack_right_edge[0], tcph->th_ack)((gint32)((tcph->sack_right_edge[0]) - (tcph->th_ack)) <=
0)
||

15

Array access (via field 'sack_right_edge') results in a null pointer dereference
5814 (tcph->num_sack_ranges > 1 &&5815 LT_SEQ(tcph->sack_left_edge[1], tcph->sack_right_edge[0])((gint32)((tcph->sack_left_edge[1]) - (tcph->sack_right_edge
[0])) < 0)
&&5816 GE_SEQ(tcph->sack_right_edge[1], tcph->sack_right_edge[0])((gint32)((tcph->sack_right_edge[0]) - (tcph->sack_right_edge
[1])) <= 0)
)5817 ) {5818 leftedge = tvb_get_ntohl(tvb, sackoffset)-base_ack;5819 tf = proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_dsack_le, tvb, sackoffset, 4, leftedge,5820 "D-SACK Left Edge = %u%s", leftedge, (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");5821 proto_item_set_generated(tf);5822 rightedge = tvb_get_ntohl(tvb, sackoffset+4)-base_ack;5823 tf = proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_dsack_re, tvb, sackoffset+4, 4, rightedge,5824 "D-SACK Right Edge = %u%s", rightedge, (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");5825 proto_item_set_generated(tf);5826 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_option_sack_dsack, tvb, sackoffset, 8);5827 }5828 5829 return tvb_captured_length(tvb);5830}5831 5832static int5833dissect_tcpopt_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))5834{5835 proto_tree *field_tree;5836 proto_item *item;5837 proto_item *length_item;5838 guint32 echo;5839 int offset = 0;5840 5841 item = proto_tree_add_item(tree, proto_tcp_option_echo, tvb, offset, -1, ENC_NA0x00000000);5842 field_tree = proto_item_add_subtree(item, ett_tcp_opt_echo);5843 5844 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,5845 offset, 1, ENC_BIG_ENDIAN0x00000000);5846 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,5847 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);5848 5849 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_ECHO6))5850 return tvb_captured_length(tvb);5851 5852 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_echo, tvb,5853 offset + 2, 4, ENC_BIG_ENDIAN0x00000000, &echo);5854 5855 proto_item_append_text(item, ": %u", echo);5856 tcp_info_append_uint(pinfo, "ECHO", echo);5857 5858 return tvb_captured_length(tvb);5859}5860 5861/* If set, do not put the TCP timestamp information on the summary line */5862static bool_Bool tcp_ignore_timestamps;5863 5864static int5865dissect_tcpopt_timestamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))5866{5867 proto_item *ti, *tsval_ti;5868 proto_tree *ts_tree;5869 proto_item *length_item;5870 int offset = 0;5871 guint32 ts_val, ts_ecr;5872 int len = tvb_reported_length(tvb);5873 5874 ti = proto_tree_add_item(tree, proto_tcp_option_timestamp, tvb, offset, -1, ENC_NA0x00000000);5875 ts_tree = proto_item_add_subtree(ti, ett_tcp_option_timestamp);5876 5877 proto_tree_add_item(ts_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5878 offset += 1;5879 5880 length_item = proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);5881 offset += 1;5882 5883 if (!tcp_option_len_check(length_item, pinfo, len, TCPOLEN_TIMESTAMP10))5884 return tvb_captured_length(tvb);5885 5886 tsval_ti = proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset,5887 4, ENC_BIG_ENDIAN0x00000000, &ts_val);5888 5889 proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset + 4,5890 4, ENC_BIG_ENDIAN0x00000000, &ts_ecr);5891 5892 proto_item_append_text(ti, ": TSval %u, TSecr %u", ts_val, ts_ecr);5893 if (tcp_ignore_timestamps == FALSE(0)) {5894 tcp_info_append_uint(pinfo, "TSval", ts_val);5895 tcp_info_append_uint(pinfo, "TSecr", ts_ecr);5896 }5897 5898 if (read_seq_as_syn_cookie) {5899 proto_item_append_text(ti, " (syn cookie)");5900 proto_item* syncookie_ti = proto_item_add_subtree(tsval_ti, ett_tcp_syncookie_option);5901 guint32 timestamp = tvb_get_bits32(tvb, offset * 8, 26, ENC_NA0x00000000) << 6;5902 proto_tree_add_uint_bits_format_value(syncookie_ti, hf_tcp_syncookie_option_timestamp, tvb, offset * 8,5903 26, timestamp, ENC_TIME_SECS0x00000012, "%s", abs_time_secs_to_str(pinfo->pool, timestamp, ABSOLUTE_TIME_LOCAL, TRUE)abs_time_secs_to_str_ex(pinfo->pool, timestamp, ABSOLUTE_TIME_LOCAL
, ((!(0))) ? (1U << 0) : 0)
);5904 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_ecn, tvb, offset * 8 + 26, 1, ENC_NA0x00000000);5905 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_sack, tvb, offset * 8 + 27, 1, ENC_NA0x00000000);5906 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_wscale, tvb, offset * 8 + 28, 4, ENC_NA0x00000000);5907 }5908 5909 return tvb_captured_length(tvb);5910}5911 5912static struct mptcp_analysis*5913mptcp_alloc_analysis(struct tcp_analysis* tcpd) {5914 5915 struct mptcp_analysis* mptcpd;5916 5917 DISSECTOR_ASSERT(tcpd->mptcp_analysis == 0)((void) ((tcpd->mptcp_analysis == 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c"
, 5917, "tcpd->mptcp_analysis == 0"))))
;5918 5919 mptcpd = (struct mptcp_analysis*)wmem_new0(wmem_file_scope(), struct mptcp_analysis)((struct mptcp_analysis*)wmem_alloc0((wmem_file_scope()), sizeof
(struct mptcp_analysis)))
;5920 mptcpd->subflows = wmem_list_new(wmem_file_scope());5921 5922 mptcpd->stream = mptcp_stream_count++;5923 tcpd->mptcp_analysis = mptcpd;5924 5925 memset(&mptcpd->meta_flow, 0, 2*sizeof(mptcp_meta_flow_t));5926 5927 /* arbitrary assignment. Callers may override this */5928 tcpd->fwd->mptcp_subflow->meta = &mptcpd->meta_flow[0];5929 tcpd->rev->mptcp_subflow->meta = &mptcpd->meta_flow[1];5930 5931 return mptcpd;5932}5933 5934 5935/* will create necessary structure if fails to find a match on the token */5936static struct mptcp_analysis*5937mptcp_get_meta_from_token(struct tcp_analysis* tcpd, tcp_flow_t *tcp_flow, guint32 token) {5938 5939 struct mptcp_analysis* result = NULL((void*)0);5940 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;5941 guint8 assignedMetaId = 0; /* array id < 2 */5942 5943 DISSECTOR_ASSERT(tcp_flow == tcpd->fwd || tcp_flow == tcpd->rev)((void) ((tcp_flow == tcpd->fwd || tcp_flow == tcpd->rev
) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 5943, "tcp_flow == tcpd->fwd || tcp_flow == tcpd->rev"
))))
;5944 5945 5946 5947 /* if token already set for this meta */5948 if( tcp_flow->mptcp_subflow->meta && (tcp_flow->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_TOKEN0x04)) {5949 return mptcpd;5950 }5951 5952 /* else look for a registered meta with this token */5953 result = (struct mptcp_analysis*)wmem_tree_lookup32(mptcp_tokens, token);5954 5955 /* if token already registered than just share it across TCP connections */5956 if(result) {5957 mptcpd = result;5958 mptcp_attach_subflow(mptcpd, tcpd);5959 }5960 else {5961 /* we create it if this connection */5962 if(!mptcpd) {5963 /* don't care which meta to choose assign each meta to a direction */5964 mptcpd = mptcp_alloc_analysis(tcpd);5965 mptcp_attach_subflow(mptcpd, tcpd);5966 }5967 else {5968 5969 /* already exists, thus some meta may already have been configured */5970 if(mptcpd->meta_flow[0].static_flags & MPTCP_META_HAS_TOKEN0x04) {5971 assignedMetaId = 1;5972 }5973 else if(mptcpd->meta_flow[1].static_flags & MPTCP_META_HAS_TOKEN0x04) {5974 assignedMetaId = 0;5975 }5976 else {5977 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/dissectors/packet-tcp.c", 5977))
;5978 }5979 tcp_flow->mptcp_subflow->meta = &mptcpd->meta_flow[assignedMetaId];5980 }5981 DISSECTOR_ASSERT(tcp_flow->mptcp_subflow->meta)((void) ((tcp_flow->mptcp_subflow->meta) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c"
, 5981, "tcp_flow->mptcp_subflow->meta"))))
;5982 5983 tcp_flow->mptcp_subflow->meta->token = token;5984 tcp_flow->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_TOKEN0x04;5985 5986 wmem_tree_insert32(mptcp_tokens, token, mptcpd);5987 }5988 5989 DISSECTOR_ASSERT(mptcpd)((void) ((mptcpd) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 5989, "mptcpd"))))
;5990 5991 5992 /* compute the meta id assigned to tcp_flow */5993 assignedMetaId = (tcp_flow->mptcp_subflow->meta == &mptcpd->meta_flow[0]) ? 0 : 1;5994 5995 /* computes the metaId tcpd->fwd should be assigned to */5996 assignedMetaId = (tcp_flow == tcpd->fwd) ? assignedMetaId : (assignedMetaId +1) %2;5997 5998 tcpd->fwd->mptcp_subflow->meta = &mptcpd->meta_flow[ (assignedMetaId) ];5999 tcpd->rev->mptcp_subflow->meta = &mptcpd->meta_flow[ (assignedMetaId +1) %2];6000 6001 return mptcpd;6002}6003 6004/* setup from_key */6005static6006struct mptcp_analysis*6007get_or_create_mptcpd_from_key(struct tcp_analysis* tcpd, tcp_flow_t *fwd, guint8 version, guint64 key, guint8 hmac_algo _U___attribute__((unused))) {6008 6009 guint32 token = 0;6010 guint64 expected_idsn= 0;6011 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;6012 6013 if(fwd->mptcp_subflow->meta && (fwd->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_KEY0x03)) {6014 return mptcpd;6015 }6016 6017 /* MPTCP v0 only standardizes SHA1, and v1 SHA256. */6018 if (version == 0)6019 mptcp_cryptodata_sha1(key, &token, &expected_idsn);6020 else if (version == 1)6021 mptcp_cryptodata_sha256(key, &token, &expected_idsn);6022 6023 mptcpd = mptcp_get_meta_from_token(tcpd, fwd, token);6024 6025 DISSECTOR_ASSERT(fwd->mptcp_subflow->meta)((void) ((fwd->mptcp_subflow->meta) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c"
, 6025, "fwd->mptcp_subflow->meta"))))
;6026 6027 fwd->mptcp_subflow->meta->version = version;6028 fwd->mptcp_subflow->meta->key = key;6029 fwd->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_KEY0x03;6030 fwd->mptcp_subflow->meta->base_dsn = expected_idsn;6031 return mptcpd;6032}6033 6034/* record this mapping */6035static6036void analyze_mapping(struct tcp_analysis *tcpd, packet_info *pinfo, guint16 len, guint64 dsn, gboolean extended, guint32 ssn) {6037 6038 /* store mapping only if analysis is enabled and mapping is not unlimited */6039 if (!mptcp_analyze_mappings || !len) {6040 return;6041 }6042 6043 if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {6044 return;6045 }6046 6047 /* register SSN range described by the mapping into a subflow interval_tree */6048 mptcp_dss_mapping_t *mapping = NULL((void*)0);6049 mapping = wmem_new0(wmem_file_scope(), mptcp_dss_mapping_t)((mptcp_dss_mapping_t*)wmem_alloc0((wmem_file_scope()), sizeof
(mptcp_dss_mapping_t)))
;6050 6051 mapping->rawdsn = dsn;6052 mapping->extended_dsn = extended;6053 mapping->frame = pinfo->fd->num;6054 mapping->ssn_low = ssn;6055 mapping->ssn_high = ssn + len - 1;6056 6057 wmem_itree_insert(tcpd->fwd->mptcp_subflow->ssn2dsn_mappings,6058 mapping->ssn_low,6059 mapping->ssn_high,6060 mapping6061 );6062}6063 6064/*6065 * The TCP Extensions for Multipath Operation with Multiple Addresses6066 * are defined in RFC 68246067 *6068 * https://tools.ietf.org/html/rfc68246069 *6070 * Author: Andrei Maruseac <[emailprotected]>6071 * Matthieu Coudron <[emailprotected]>6072 *6073 * This function just generates the mptcpheader, i.e. the generation of6074 * datastructures is delayed/delegated to mptcp_analyze6075 */6076static int6077dissect_tcpopt_mptcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)6078{6079 proto_item *item,*main_item;6080 proto_tree *mptcp_tree;6081 6082 guint32 version;6083 guint8 subtype;6084 guint8 ipver;6085 int offset = 0;6086 int optlen = tvb_reported_length(tvb);6087 int start_offset = offset;6088 struct tcp_analysis *tcpd = NULL((void*)0);6089 struct mptcp_analysis* mptcpd = NULL((void*)0);6090 struct tcpheader *tcph = (struct tcpheader *)data;6091 6092 /* There may be several MPTCP options per packet, don't duplicate the structure */6093 struct mptcpheader* mph = tcph->th_mptcp;6094 6095 if(!mph) {6096 mph = wmem_new0(pinfo->pool, struct mptcpheader)((struct mptcpheader*)wmem_alloc0((pinfo->pool), sizeof(struct
mptcpheader)))
;6097 tcph->th_mptcp = mph;6098 }6099 6100 tcpd=get_tcp_conversation_data(NULL((void*)0),pinfo);6101 mptcpd=tcpd->mptcp_analysis;6102 6103 /* seeing an MPTCP packet on the subflow automatically qualifies it as an mptcp subflow */6104 if(!tcpd->fwd->mptcp_subflow) {6105 mptcp_init_subflow(tcpd->fwd);6106 }6107 if(!tcpd->rev->mptcp_subflow) {6108 mptcp_init_subflow(tcpd->rev);6109 }6110 6111 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPTCP");6112 main_item = proto_tree_add_item(tree, proto_mptcp, tvb, offset, -1, ENC_NA0x00000000);6113 mptcp_tree = proto_item_add_subtree(main_item, ett_tcp_option_mptcp);6114 6115 proto_tree_add_item(mptcp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);6116 offset += 1;6117 6118 proto_tree_add_item(mptcp_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);6119 offset += 1;6120 6121 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_subtype, tvb,6122 offset, 1, ENC_BIG_ENDIAN0x00000000);6123 6124 subtype = tvb_get_guint8(tvb, offset) >> 4;6125 proto_item_append_text(main_item, ": %s", val_to_str(subtype, mptcp_subtype_vs, "Unknown (%d)"));6126 6127 /** preemptively allocate mptcpd when subtype won't allow to find a meta */6128 if(!mptcpd && (subtype > TCPOPT_MPTCP_MP_JOIN0x1)) {6129 mptcpd = mptcp_alloc_analysis(tcpd);6130 }6131 6132 switch (subtype) {6133 case TCPOPT_MPTCP_MP_CAPABLE0x0:6134 mph->mh_mpc = TRUE(!(0));6135 6136 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_version, tvb,6137 offset, 1, ENC_BIG_ENDIAN0x00000000, &version);6138 offset += 1;6139 6140 item = proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,6141 ett_tcp_option_mptcp,6142 version == 1 ? tcp_option_mptcp_capable_v1_flags : tcp_option_mptcp_capable_v0_flags,6143 ENC_BIG_ENDIAN0x00000000);6144 mph->mh_capable_flags = tvb_get_guint8(tvb, offset);6145 if ((mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK0x3F) == 0) {6146 expert_add_info(pinfo, item, &ei_mptcp_analysis_missing_algorithm);6147 }6148 if ((mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK0x3F) != MPTCP_HMAC_SHA) {6149 expert_add_info(pinfo, item, &ei_mptcp_analysis_unsupported_algorithm);6150 }6151 offset += 1;6152 6153 /* optlen == 12 => SYN or SYN/ACK; optlen == 20 => ACK;6154 * optlen == 22 => ACK + data (v1 only);6155 * optlen == 24 => ACK + data + csum (v1 only)6156 */6157 if (optlen == 12 || optlen == 20 || optlen == 22 || optlen == 24) {6158 6159 mph->mh_key = tvb_get_ntoh64(tvb,offset);6160 proto_tree_add_uint64(mptcp_tree, hf_tcp_option_mptcp_sender_key, tvb, offset, 8, mph->mh_key);6161 offset += 8;6162 6163 mptcpd = get_or_create_mptcpd_from_key(tcpd, tcpd->fwd, version, mph->mh_key, mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK0x3F);6164 mptcpd->master = tcpd;6165 6166 item = proto_tree_add_uint(mptcp_tree,6167 hf_mptcp_expected_token, tvb, offset, 0, tcpd->fwd->mptcp_subflow->meta->token);6168 proto_item_set_generated(item);6169 6170 item = proto_tree_add_uint64(mptcp_tree,6171 hf_mptcp_expected_idsn, tvb, offset, 0, tcpd->fwd->mptcp_subflow->meta->base_dsn);6172 proto_item_set_generated(item);6173 6174 /* last ACK of 3WHS, repeats both keys */6175 if (optlen >= 20) {6176 guint64 recv_key = tvb_get_ntoh64(tvb,offset);6177 proto_tree_add_uint64(mptcp_tree, hf_tcp_option_mptcp_recv_key, tvb, offset, 8, recv_key);6178 offset += 8;6179 6180 if(tcpd->rev->mptcp_subflow->meta6181 && (tcpd->rev->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_KEY0x03)) {6182 6183 /* compare the echoed key with the server key */6184 if(tcpd->rev->mptcp_subflow->meta->key != recv_key) {6185 expert_add_info(pinfo, item, &ei_mptcp_analysis_echoed_key_mismatch);6186 }6187 }6188 else {6189 mptcpd = get_or_create_mptcpd_from_key(tcpd, tcpd->rev, version, recv_key, mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK0x3F);6190 }6191 }6192 6193 /* MPTCP v1 ACK + data, contains data_len and optional checksum */6194 if (optlen >= 22) {6195 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_lvl_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);6196 mph->mh_dss_length = tvb_get_ntohs(tvb,offset);6197 offset += 2;6198 6199 if (mph->mh_dss_length == 0) {6200 expert_add_info(pinfo, mptcp_tree, &ei_mptcp_infinite_mapping);6201 }6202 6203 /* when data len is present, this MP_CAPABLE also carries an implicit mapping ... */6204 analyze_mapping(tcpd, pinfo, mph->mh_dss_length, tcpd->fwd->mptcp_subflow->meta->base_dsn + 1, TRUE(!(0)), tcph->th_seq);6205 6206 /* ... with optional checksum */6207 if (optlen == 24)6208 {6209 proto_tree_add_checksum(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_checksum, -1, NULL((void*)0), pinfo, 0, ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00);6210 }6211 }6212 }6213 break;6214 6215 case TCPOPT_MPTCP_MP_JOIN0x1:6216 mph->mh_join = TRUE(!(0));6217 if(optlen != 12 && !mptcpd) {6218 mptcpd = mptcp_alloc_analysis(tcpd);6219 }6220 switch (optlen) {6221 /* Syn */6222 case 12:6223 {6224 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,6225 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,6226 ENC_BIG_ENDIAN0x00000000);6227 offset += 1;6228 tcpd->fwd->mptcp_subflow->address_id = tvb_get_guint8(tvb, offset);6229 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,6230 1, ENC_BIG_ENDIAN0x00000000);6231 offset += 1;6232 6233 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_recv_token, tvb, offset,6234 4, ENC_BIG_ENDIAN0x00000000, &mph->mh_token);6235 offset += 4;6236 6237 mptcpd = mptcp_get_meta_from_token(tcpd, tcpd->rev, mph->mh_token);6238 if (tcpd->fwd->mptcp_subflow->meta->version == 1) {6239 mptcp_meta_flow_t *tmp = tcpd->fwd->mptcp_subflow->meta;6240 6241 /* if the negotiated version is v1 the first key was exchanged on SYN/ACK packet: we must swap the meta */6242 tcpd->fwd->mptcp_subflow->meta = tcpd->rev->mptcp_subflow->meta;6243 tcpd->rev->mptcp_subflow->meta = tmp;6244 }6245 6246 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_sender_rand, tvb, offset,6247 4, ENC_BIG_ENDIAN0x00000000, &tcpd->fwd->mptcp_subflow->nonce);6248 6249 }6250 break;6251 6252 6253 case 16: /* Syn/Ack */6254 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,6255 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,6256 ENC_BIG_ENDIAN0x00000000);6257 offset += 1;6258 6259 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,6260 1, ENC_BIG_ENDIAN0x00000000);6261 offset += 1;6262 6263 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_trunc_hmac, tvb, offset,6264 8, ENC_BIG_ENDIAN0x00000000);6265 offset += 8;6266 6267 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_rand, tvb, offset,6268 4, ENC_BIG_ENDIAN0x00000000);6269 break;6270 6271 case 24: /* Ack */6272 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_reserved, tvb, offset,6273 2, ENC_BIG_ENDIAN0x00000000);6274 offset += 2;6275 6276 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_hmac, tvb, offset,6277 20, ENC_NA0x00000000);6278 break;6279 6280 default:6281 break;6282 }6283 break;6284 6285 /* display only *raw* values since it is harder to guess a correct value than for TCP.6286 One needs to enable mptcp_analysis to get more interesting data6287 */6288 case TCPOPT_MPTCP_DSS0x2:6289 mph->mh_dss = TRUE(!(0));6290 6291 offset += 1;6292 mph->mh_dss_flags = tvb_get_guint8(tvb, offset) & 0x1F;6293 6294 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,6295 ett_tcp_option_mptcp, tcp_option_mptcp_dss_flags,6296 ENC_BIG_ENDIAN0x00000000);6297 offset += 1;6298 6299 /* displays "raw" DataAck , ie does not convert it to its 64 bits form6300 to do so you need to enable6301 */6302 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_PRESENT0x01) {6303 6304 guint64 dack64;6305 6306 /* 64bits ack */6307 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02) {6308 6309 mph->mh_dss_rawack = tvb_get_ntoh64(tvb,offset);6310 proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_ack_raw, tvb, offset, 8, mph->mh_dss_rawack, "%" PRIu64"l" "u" " (64bits)", mph->mh_dss_rawack);6311 offset += 8;6312 }6313 /* 32bits ack */6314 else {6315 mph->mh_dss_rawack = tvb_get_ntohl(tvb,offset);6316 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_ack_raw, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);6317 offset += 4;6318 }6319 6320 if(mptcp_convert_dsn(mph->mh_dss_rawack, tcpd->rev->mptcp_subflow->meta,6321 (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02) ? DSN_CONV_NONE : DSN_CONV_32_TO_64, mptcp_relative_seq, &dack64)) {6322 item = proto_tree_add_uint64(mptcp_tree, hf_mptcp_ack, tvb, 0, 0, dack64);6323 if (mptcp_relative_seq) {6324 proto_item_append_text(item, " (Relative)");6325 }6326 6327 proto_item_set_generated(item);6328 }6329 else {6330 /* ignore and continue */6331 }6332 6333 }6334 6335 /* Mapping present */6336 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_MAPPING_PRESENT0x04) {6337 6338 guint64 dsn;6339 6340 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DSN_8BYTES0x08) {6341 6342 dsn = tvb_get_ntoh64(tvb,offset);6343 proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 8, dsn, "%" PRIu64"l" "u" " (64bits version)", dsn);6344 6345 /* if we have the opportunity to complete the 32 Most Significant Bits of the6346 *6347 */6348 if(!(tcpd->fwd->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_BASE_DSN_MSB0x01)) {6349 tcpd->fwd->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_BASE_DSN_MSB0x01;6350 tcpd->fwd->mptcp_subflow->meta->base_dsn |= (dsn & (guint32) 0);6351 }6352 offset += 8;6353 } else {6354 dsn = tvb_get_ntohl(tvb,offset);6355 proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 4, dsn, "%" PRIu64"l" "u" " (32bits version)", dsn);6356 offset += 4;6357 }6358 mph->mh_dss_rawdsn = dsn;6359 6360 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_subflow_seq_no, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &mph->mh_dss_ssn);6361 offset += 4;6362 6363 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_lvl_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);6364 mph->mh_dss_length = tvb_get_ntohs(tvb,offset);6365 offset += 2;6366 6367 if(mph->mh_dss_length == 0) {6368 expert_add_info(pinfo, mptcp_tree, &ei_mptcp_infinite_mapping);6369 }6370 6371 /* print head & tail dsn */6372 if(mptcp_convert_dsn(mph->mh_dss_rawdsn, tcpd->fwd->mptcp_subflow->meta,6373 (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02) ? DSN_CONV_NONE : DSN_CONV_32_TO_64, mptcp_relative_seq, &dsn)) {6374 item = proto_tree_add_uint64(mptcp_tree, hf_mptcp_dss_dsn, tvb, 0, 0, dsn);6375 if (mptcp_relative_seq) {6376 proto_item_append_text(item, " (Relative)");6377 }6378 6379 proto_item_set_generated(item);6380 }6381 else {6382 /* ignore and continue */6383 }6384 6385 analyze_mapping(tcpd, pinfo, mph->mh_dss_length, mph->mh_dss_rawdsn, mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02, mph->mh_dss_ssn);6386 6387 if ((int)optlen >= offset-start_offset+4)6388 {6389 proto_tree_add_checksum(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_checksum, -1, NULL((void*)0), pinfo, 0, ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00);6390 }6391 }6392 break;6393 6394 case TCPOPT_MPTCP_ADD_ADDR0x3:6395 mph->mh_add = TRUE(!(0));6396 ipver = tvb_get_guint8(tvb, offset) & 0x0F;6397 if (ipver == 4 || ipver == 6)6398 proto_tree_add_item(mptcp_tree,6399 hf_tcp_option_mptcp_ipver, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);6400 else6401 proto_tree_add_item(mptcp_tree,6402 hf_tcp_option_mptcp_echo, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);6403 offset += 1;6404 6405 proto_tree_add_item(mptcp_tree,6406 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);6407 offset += 1;6408 6409 if (optlen == 8 || optlen == 10 || optlen == 16 || optlen == 18) {6410 proto_tree_add_item(mptcp_tree,6411 hf_tcp_option_mptcp_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);6412 offset += 4;6413 }6414 6415 if (optlen == 20 || optlen == 22 || optlen == 28 || optlen == 30) {6416 proto_tree_add_item(mptcp_tree,6417 hf_tcp_option_mptcp_ipv6, tvb, offset, 16, ENC_NA0x00000000);6418 offset += 16;6419 }6420 6421 if (optlen == 10 || optlen == 18 || optlen == 22 || optlen == 30) {6422 proto_tree_add_item(mptcp_tree,6423 hf_tcp_option_mptcp_port, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);6424 offset += 2;6425 }6426 6427 if (optlen == 16 || optlen == 18 || optlen == 28 || optlen == 30) {6428 proto_tree_add_item(mptcp_tree,6429 hf_tcp_option_mptcp_addaddr_trunc_hmac, tvb, offset, 8, ENC_BIG_ENDIAN0x00000000);6430 }6431 break;6432 6433 case TCPOPT_MPTCP_REMOVE_ADDR0x4:6434 mph->mh_remove = TRUE(!(0));6435 item = proto_tree_add_uint(mptcp_tree, hf_mptcp_number_of_removed_addresses, tvb, start_offset+2,6436 1, optlen - 3);6437 proto_item_set_generated(item);6438 offset += 1;6439 while(offset < start_offset + (int)optlen) {6440 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,6441 1, ENC_BIG_ENDIAN0x00000000);6442 offset += 1;6443 }6444 break;6445 6446 case TCPOPT_MPTCP_MP_PRIO0x5:6447 mph->mh_prio = TRUE(!(0));6448 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,6449 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,6450 ENC_BIG_ENDIAN0x00000000);6451 offset += 1;6452 6453 if (optlen == 4) {6454 proto_tree_add_item(mptcp_tree,6455 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);6456 }6457 break;6458 6459 case TCPOPT_MPTCP_MP_FAIL0x6:6460 mph->mh_fail = TRUE(!(0));6461 proto_tree_add_item(mptcp_tree,6462 hf_tcp_option_mptcp_reserved, tvb, offset,2, ENC_BIG_ENDIAN0x00000000);6463 offset += 2;6464 6465 proto_tree_add_item(mptcp_tree,6466 hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 8, ENC_BIG_ENDIAN0x00000000);6467 break;6468 6469 case TCPOPT_MPTCP_MP_FASTCLOSE0x7:6470 mph->mh_fastclose = TRUE(!(0));6471 proto_tree_add_item(mptcp_tree,6472 hf_tcp_option_mptcp_reserved, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);6473 offset += 2;6474 6475 proto_tree_add_item(mptcp_tree,6476 hf_tcp_option_mptcp_recv_key, tvb, offset, 8, ENC_BIG_ENDIAN0x00000000);6477 mph->mh_key = tvb_get_ntoh64(tvb,offset);6478 break;6479 6480 case TCPOPT_MPTCP_MP_TCPRST0x8:6481 mph->mh_tcprst = TRUE(!(0));6482 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,6483 ett_tcp_option_mptcp, tcp_option_mptcp_tcprst_flags,6484 ENC_BIG_ENDIAN0x00000000);6485 offset += 1;6486 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_tcprst_reason, tvb, offset, 1,6487 ENC_BIG_ENDIAN0x00000000);6488 break;6489 6490 default:6491 break;6492 }6493 6494 if ((mptcpd != NULL((void*)0)) && (tcpd->mptcp_analysis != NULL((void*)0))) {6495 6496 /* if mptcpd just got allocated, remember the initial addresses6497 * which will serve as identifiers for the conversation filter6498 */6499 if(tcpd->fwd->mptcp_subflow->meta->ip_src.len == 0) {6500 6501 copy_address_wmem(wmem_file_scope(), &tcpd->fwd->mptcp_subflow->meta->ip_src, &tcph->ip_src);6502 copy_address_wmem(wmem_file_scope(), &tcpd->fwd->mptcp_subflow->meta->ip_dst, &tcph->ip_dst);6503 6504 copy_address_shallow(&tcpd->rev->mptcp_subflow->meta->ip_src, &tcpd->fwd->mptcp_subflow->meta->ip_dst);6505 copy_address_shallow(&tcpd->rev->mptcp_subflow->meta->ip_dst, &tcpd->fwd->mptcp_subflow->meta->ip_src);6506 6507 tcpd->fwd->mptcp_subflow->meta->sport = tcph->th_sport;6508 tcpd->fwd->mptcp_subflow->meta->dport = tcph->th_dport;6509 }6510 6511 mph->mh_stream = tcpd->mptcp_analysis->stream;6512 }6513 6514 return tvb_captured_length(tvb);6515}6516 6517static int6518dissect_tcpopt_cc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))6519{6520 proto_tree *field_tree;6521 proto_item *item;6522 proto_item *length_item;6523 int offset = 0;6524 guint32 cc;6525 6526 item = proto_tree_add_item(tree, proto_tcp_option_cc, tvb, offset, -1, ENC_NA0x00000000);6527 field_tree = proto_item_add_subtree(item, ett_tcp_opt_cc);6528 6529 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,6530 offset, 1, ENC_BIG_ENDIAN0x00000000);6531 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,6532 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);6533 6534 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_CC6))6535 return tvb_captured_length(tvb);6536 6537 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_cc, tvb,6538 offset + 2, 4, ENC_BIG_ENDIAN0x00000000, &cc);6539 6540 tcp_info_append_uint(pinfo, "CC", cc);6541 return tvb_captured_length(tvb);6542}6543 6544static int6545dissect_tcpopt_md5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))6546{6547 proto_tree *field_tree;6548 proto_item *item;6549 proto_item *length_item;6550 int offset = 0, optlen = tvb_reported_length(tvb);6551 6552 item = proto_tree_add_item(tree, proto_tcp_option_md5, tvb, offset, -1, ENC_NA0x00000000);6553 field_tree = proto_item_add_subtree(item, ett_tcp_opt_md5);6554 6555 col_append_lstr(pinfo->cinfo, COL_INFO, " MD5", COL_ADD_LSTR_TERMINATOR(const char *) -1);6556 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,6557 offset, 1, ENC_BIG_ENDIAN0x00000000);6558 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,6559 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);6560 6561 if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_MD518))6562 return tvb_captured_length(tvb);6563 6564 proto_tree_add_item(field_tree, hf_tcp_option_md5_digest, tvb,6565 offset + 2, optlen - 2, ENC_NA0x00000000);6566 6567 return tvb_captured_length(tvb);6568}6569 6570static int6571dissect_tcpopt_ao(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))6572{6573 proto_tree *field_tree;6574 proto_item *item;6575 proto_item *length_item;6576 int offset = 0, optlen = tvb_reported_length(tvb);6577 6578 item = proto_tree_add_item(tree, proto_tcp_option_ao, tvb, offset, -1, ENC_NA0x00000000);6579 field_tree = proto_item_add_subtree(item, ett_tcp_opt_ao);6580 6581 col_append_lstr(pinfo->cinfo, COL_INFO, "TCP AO", COL_ADD_LSTR_TERMINATOR(const char *) -1);6582 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,6583 offset, 1, ENC_BIG_ENDIAN0x00000000);6584 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,6585 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);6586 6587 if (optlen < 4) {6588 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,6589 "option length should be >= than 4");6590 return tvb_captured_length(tvb);6591 }6592 6593 proto_tree_add_item(field_tree, hf_tcp_option_ao_keyid, tvb,6594 offset + 2, 1, ENC_NA0x00000000);6595 6596 proto_tree_add_item(field_tree, hf_tcp_option_ao_rnextkeyid, tvb,6597 offset + 3, 1, ENC_NA0x00000000);6598 6599 if (optlen > 4)6600 proto_tree_add_item(field_tree, hf_tcp_option_ao_mac, tvb,6601 offset + 4, optlen - 4, ENC_NA0x00000000);6602 6603 return tvb_captured_length(tvb);6604}6605 6606static int6607dissect_tcpopt_qs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))6608{6609 proto_tree *field_tree;6610 proto_item *item;6611 proto_item *length_item;6612 guint8 rate;6613 int offset = 0;6614 6615 item = proto_tree_add_item(tree, proto_tcp_option_qs, tvb, offset, -1, ENC_NA0x00000000);6616 field_tree = proto_item_add_subtree(item, ett_tcp_opt_qs);6617 6618 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,6619 offset, 1, ENC_BIG_ENDIAN0x00000000);6620 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,6621 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);6622 6623 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_QS8))6624 return tvb_captured_length(tvb);6625 6626 rate = tvb_get_guint8(tvb, offset + 2) & 0x0f;6627 col_append_lstr(pinfo->cinfo, COL_INFO,6628 " QSresp=", val_to_str_ext_const(rate, &qs_rate_vals_ext, "Unknown"),6629 COL_ADD_LSTR_TERMINATOR(const char *) -1);6630 proto_tree_add_item(field_tree, hf_tcp_option_qs_rate, tvb,6631 offset + 2, 1, ENC_BIG_ENDIAN0x00000000);6632 proto_tree_add_item(field_tree, hf_tcp_option_qs_ttl_diff, tvb,6633 offset + 3, 1, ENC_BIG_ENDIAN0x00000000);6634 6635 return tvb_captured_length(tvb);6636}6637 6638static int6639dissect_tcpopt_scps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))6640{6641 struct tcp_analysis *tcpd;6642 proto_tree *field_tree = NULL((void*)0);6643 tcp_flow_t *flow;6644 int direction;6645 proto_item *tf = NULL((void*)0), *item;6646 proto_tree *flags_tree = NULL((void*)0);6647 guint8 capvector;6648 guint8 connid;6649 int offset = 0, optlen = tvb_reported_length(tvb);6650 6651 tcpd = get_tcp_conversation_data(NULL((void*)0),pinfo);6652 6653 /* check direction and get ua lists */6654 direction=cmp_address(&pinfo->src, &pinfo->dst);6655 6656 /* if the addresses are equal, match the ports instead */6657 if(direction==0) {6658 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;6659 }6660 6661 if(direction>=0)6662 flow =&(tcpd->flow1);6663 else6664 flow =&(tcpd->flow2);6665 6666 item = proto_tree_add_item(tree, proto_tcp_option_scps,6667 tvb, offset, -1, ENC_NA0x00000000);6668 field_tree = proto_item_add_subtree(item, ett_tcp_option_scps);6669 6670 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,6671 offset, 1, ENC_BIG_ENDIAN0x00000000);6672 proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,6673 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);6674 6675 /* If the option length == 4, this is a real SCPS capability option6676 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol6677 * (SCPS-TP)" Section 3.2.3 for definition.6678 */6679 if (optlen == 4) {6680 tf = proto_tree_add_item(field_tree, hf_tcp_option_scps_vector, tvb,6681 offset + 2, 1, ENC_BIG_ENDIAN0x00000000);6682 flags_tree = proto_item_add_subtree(tf, ett_tcp_scpsoption_flags);6683 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_bets, tvb,6684 offset + 2, 1, ENC_BIG_ENDIAN0x00000000);6685 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack1, tvb,6686 offset + 2, 1, ENC_BIG_ENDIAN0x00000000);6687 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack2, tvb,6688 offset + 2, 1, ENC_BIG_ENDIAN0x00000000);6689 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_compress, tvb,6690 offset + 2, 1, ENC_BIG_ENDIAN0x00000000);6691 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_nlts, tvb,6692 offset + 2, 1, ENC_BIG_ENDIAN0x00000000);6693 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_reserved, tvb,6694 offset + 2, 1, ENC_BIG_ENDIAN0x00000000);6695 capvector = tvb_get_guint8(tvb, offset + 2);6696 6697 if (capvector) {6698 struct capvec6699 {6700 guint8 mask;6701 const gchar *str;6702 } capvecs[] = {6703 {0x80, "BETS"},6704 {0x40, "SNACK1"},6705 {0x20, "SNACK2"},6706 {0x10, "COMP"},6707 {0x08, "NLTS"},6708 {0x07, "RESERVED"}6709 };6710 gboolean anyflag = FALSE(0);6711 guint i;6712 6713 col_append_str(pinfo->cinfo, COL_INFO, " SCPS[");6714 for (i = 0; i < sizeof(capvecs)/sizeof(struct capvec); i++) {6715 if (capvector & capvecs[i].mask) {6716 proto_item_append_text(tf, "%s%s", anyflag ? ", " : " (",6717 capvecs[i].str);6718 col_append_lstr(pinfo->cinfo, COL_INFO,6719 anyflag ? ", " : "",6720 capvecs[i].str,6721 COL_ADD_LSTR_TERMINATOR(const char *) -1);6722 anyflag = TRUE(!(0));6723 }6724 }6725 col_append_str(pinfo->cinfo, COL_INFO, "]");6726 proto_item_append_text(tf, ")");6727 }6728 6729 proto_tree_add_item(field_tree, hf_tcp_scpsoption_connection_id, tvb,6730 offset + 3, 1, ENC_BIG_ENDIAN0x00000000);6731 connid = tvb_get_guint8(tvb, offset + 3);6732 flow->scps_capable = 1;6733 6734 if (connid)6735 tcp_info_append_uint(pinfo, "Connection ID", connid);6736 } else {6737 /* The option length != 4, so this is an infamous "extended capabilities6738 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS6739 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.6740 *6741 * As the format of this option is only partially defined (it is6742 * a community (or more likely vendor) defined format beyond that, so6743 * at least for now, we only parse the standardized portion of the option.6744 */6745 guint8 local_offset = 2;6746 guint8 binding_space;6747 guint8 extended_cap_length;6748 6749 if (flow->scps_capable != 1) {6750 /* There was no SCPS capabilities option preceding this */6751 proto_item_set_text(item,6752 "Illegal SCPS Extended Capabilities (%u bytes)",6753 optlen);6754 } else {6755 proto_item_set_text(item,6756 "SCPS Extended Capabilities (%u bytes)",6757 optlen);6758 6759 /* There may be multiple binding spaces included in a single option,6760 * so we will semi-parse each of the stacked binding spaces - skipping6761 * over the octets following the binding space identifier and length.6762 */6763 while (optlen > local_offset) {6764 6765 /* 1st octet is Extended Capability Binding Space */6766 binding_space = tvb_get_guint8(tvb, (offset + local_offset));6767 6768 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.6769 * As defined by the specification, this length is exclusive of the6770 * octets containing the extended capability type and length6771 */6772 extended_cap_length =6773 (tvb_get_guint8(tvb, (offset + local_offset + 1)) >> 4);6774 6775 /* Convert the extended capabilities length into bytes for display */6776 extended_cap_length = (extended_cap_length << 1);6777 6778 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding, tvb, offset + local_offset, 1, ENC_BIG_ENDIAN0x00000000);6779 proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding_len, tvb, offset + local_offset + 1, 1, extended_cap_length);6780 6781 /* Step past the binding space and length octets */6782 local_offset += 2;6783 6784 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding_data, tvb, offset + local_offset, extended_cap_length, ENC_NA0x00000000);6785 6786 tcp_info_append_uint(pinfo, "EXCAP", binding_space);6787 6788 /* Step past the Extended capability data6789 * Treat the extended capability data area as opaque;6790 * If one desires to parse the extended capability data6791 * (say, in a vendor aware build of wireshark), it would6792 * be triggered here.6793 */6794 local_offset += extended_cap_length;6795 }6796 }6797 }6798 6799 return tvb_captured_length(tvb);6800}6801 6802static int6803dissect_tcpopt_user_to(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))6804{6805 proto_item *tf;6806 proto_tree *field_tree;6807 proto_item *length_item;6808 guint16 to;6809 int offset = 0;6810 6811 tf = proto_tree_add_item(tree, proto_tcp_option_user_to, tvb, offset, -1, ENC_NA0x00000000);6812 field_tree = proto_item_add_subtree(tf, ett_tcp_option_user_to);6813 6814 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,6815 offset, 1, ENC_BIG_ENDIAN0x00000000);6816 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,6817 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);6818 6819 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_USER_TO4))6820 return tvb_captured_length(tvb);6821 6822 proto_tree_add_item(field_tree, hf_tcp_option_user_to_granularity, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000);6823 to = tvb_get_ntohs(tvb, offset + 2) & 0x7FFF;6824 proto_tree_add_item(field_tree, hf_tcp_option_user_to_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000);6825 6826 tcp_info_append_uint(pinfo, "USER_TO", to);6827 return tvb_captured_length(tvb);6828}6829 6830/* This is called for SYN+ACK packets and the purpose is to verify that6831 * the SCPS capabilities option has been successfully negotiated for the flow.6832 * If the SCPS capabilities option was offered by only one party, the6833 * proactively set scps_capable attribute of the flow (set upon seeing6834 * the first instance of the SCPS option) is revoked.6835 */6836static void6837verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd)6838{6839 tf_syn = 0x0;6840 6841 if(tcpd) {6842 if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) {6843 tcpd->flow1.scps_capable = 0;6844 tcpd->flow2.scps_capable = 0;6845 } else {6846 expert_add_info(pinfo, tf_syn, &ei_tcp_scps_capable);6847 }6848 }6849}6850 6851/* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS6852 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option6853 */6854static int6855dissect_tcpopt_snack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))6856{6857 struct tcp_analysis *tcpd=NULL((void*)0);6858 guint32 relative_hole_offset;6859 guint32 relative_hole_size;6860 guint16 base_mss = 0;6861 guint32 ack;6862 guint32 hole_start;6863 guint32 hole_end;6864 int offset = 0;6865 proto_item *hidden_item, *tf;6866 proto_tree *field_tree;6867 proto_item *length_item;6868 6869 tf = proto_tree_add_item(tree, proto_tcp_option_snack, tvb, offset, -1, ENC_NA0x00000000);6870 field_tree = proto_item_add_subtree(tf, ett_tcp_option_snack);6871 6872 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,6873 offset, 1, ENC_BIG_ENDIAN0x00000000);6874 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,6875 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);6876 6877 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SNACK6))6878 return tvb_captured_length(tvb);6879 6880 tcpd = get_tcp_conversation_data(NULL((void*)0),pinfo);6881 6882 /* The SNACK option reports missing data with a granularity of segments. */6883 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_snack_offset,6884 tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000, &relative_hole_offset);6885 6886 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_snack_size,6887 tvb, offset + 4, 2, ENC_BIG_ENDIAN0x00000000, &relative_hole_size);6888 6889 ack = tvb_get_ntohl(tvb, 8);6890 6891 if (tcp_analyze_seq && tcp_relative_seq) {6892 ack -= tcpd->rev->base_seq;6893 }6894 6895 /* To aid analysis, we can use a simple but generally effective heuristic6896 * to report the most likely boundaries of the missing data. If the6897 * flow is scps_capable, we track the maximum sized segment that was6898 * acknowledged by the receiver and use that as the reporting granularity.6899 * This may be different from the negotiated MTU due to PMTUD or flows6900 * that do not send max-sized segments.6901 */6902 base_mss = tcpd->fwd->maxsizeacked;6903 6904 if (base_mss) {6905 /* Scale the reported offset and hole size by the largest segment acked */6906 hole_start = ack + (base_mss * relative_hole_offset);6907 hole_end = hole_start + (base_mss * relative_hole_size);6908 6909 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_snack_le,6910 tvb, offset + 2, 2, hole_start);6911 proto_item_set_hidden(hidden_item);6912 6913 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_snack_re,6914 tvb, offset + 4, 2, hole_end);6915 proto_item_set_hidden(hidden_item);6916 6917 proto_tree_add_expert_format(field_tree, pinfo, &ei_tcp_option_snack_sequence, tvb, offset+2, 4,6918 "SNACK Sequence %u - %u%s", hole_start, hole_end, ((tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : ""));6919 6920 tcp_info_append_uint(pinfo, "SNLE", hole_start);6921 tcp_info_append_uint(pinfo, "SNRE", hole_end);6922 }6923 6924 return tvb_captured_length(tvb);6925}6926 6927enum6928{6929 PROBE_VERSION_UNSPEC = 0,6930 PROBE_VERSION_1 = 1,6931 PROBE_VERSION_2 = 2,6932 PROBE_VERSION_MAX6933};6934 6935/* Probe type definition. */6936enum6937{6938 PROBE_QUERY = 0,6939 PROBE_RESPONSE = 1,6940 PROBE_INTERNAL = 2,6941 PROBE_TRACE = 3,6942 PROBE_QUERY_SH = 4,6943 PROBE_RESPONSE_SH = 5,6944 PROBE_QUERY_INFO = 6,6945 PROBE_RESPONSE_INFO = 7,6946 PROBE_QUERY_INFO_SH = 8,6947 PROBE_QUERY_INFO_SID = 9,6948 PROBE_RST = 10,6949 PROBE_TYPE_MAX6950};6951 6952static const value_string rvbd_probe_type_vs[] = {6953 { PROBE_QUERY, "Probe Query" },6954 { PROBE_RESPONSE, "Probe Response" },6955 { PROBE_INTERNAL, "Probe Internal" },6956 { PROBE_TRACE, "Probe Trace" },6957 { PROBE_QUERY_SH, "Probe Query SH" },6958 { PROBE_RESPONSE_SH, "Probe Response SH" },6959 { PROBE_QUERY_INFO, "Probe Query Info" },6960 { PROBE_RESPONSE_INFO, "Probe Response Info" },6961 { PROBE_QUERY_INFO_SH, "Probe Query Info SH" },6962 { PROBE_QUERY_INFO_SID, "Probe Query Info Store ID" },6963 { PROBE_RST, "Probe Reset" },6964 { 0, NULL((void*)0) }6965};6966 6967#define PROBE_OPTLEN_OFFSET1 16968 6969#define PROBE_VERSION_TYPE_OFFSET2 26970#define PROBE_V1_RESERVED_OFFSET3 36971#define PROBE_V1_PROBER_OFFSET4 46972#define PROBE_V1_APPLI_VERSION_OFFSET8 86973#define PROBE_V1_PROXY_ADDR_OFFSET8 86974#define PROBE_V1_PROXY_PORT_OFFSET12 126975#define PROBE_V1_SH_CLIENT_ADDR_OFFSET8 86976#define PROBE_V1_SH_PROXY_ADDR_OFFSET12 126977#define PROBE_V1_SH_PROXY_PORT_OFFSET16 166978 6979#define PROBE_V2_INFO_OFFSET3 36980 6981#define PROBE_V2_INFO_CLIENT_ADDR_OFFSET4 46982#define PROBE_V2_INFO_STOREID_OFFSET4 46983 6984#define PROBE_VERSION_MASK0x01 0x016985 6986/* Probe Query Extra Info flags */6987#define RVBD_FLAGS_PROBE_LAST0x01 0x016988#define RVBD_FLAGS_PROBE_NCFE0x04 0x046989 6990/* Probe Response Extra Info flags */6991#define RVBD_FLAGS_PROBE_SERVER0x01 0x016992#define RVBD_FLAGS_PROBE_SSLCERT0x02 0x026993#define RVBD_FLAGS_PROBE0x10 0x106994 6995typedef struct rvbd_option_data6996{6997 gboolean valid;6998 guint8 type;6999 guint8 probe_flags;7000 7001} rvbd_option_data;7002 7003static void7004rvbd_probe_decode_version_type(const guint8 vt, guint8 *ver, guint8 *type)7005{7006 if (vt & PROBE_VERSION_MASK0x01) {7007 *ver = PROBE_VERSION_1;7008 *type = vt >> 4;7009 } else {7010 *ver = PROBE_VERSION_2;7011 *type = vt >> 1;7012 }7013}7014 7015static void7016rvbd_probe_resp_add_info(proto_item *pitem, packet_info *pinfo, tvbuff_t *tvb, int ip_offset, guint16 port)7017{7018 proto_item_append_text(pitem, ", Server Steelhead: %s:%u", tvb_ip_to_str(pinfo->pool, tvb, ip_offset)tvb_address_to_str(pinfo->pool, tvb, AT_IPv4, ip_offset), port);7019 7020 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA+, ");7021}7022 7023static int7024dissect_tcpopt_rvbd_probe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)7025{7026 guint8 ver, type;7027 proto_tree *field_tree;7028 proto_item *pitem;7029 proto_item *length_item;7030 int offset = 0,7031 optlen = tvb_reported_length(tvb);7032 struct tcpheader *tcph = (struct tcpheader*)data;7033 7034 pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_probe, tvb, offset, -1, ENC_NA0x00000000);7035 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe);7036 7037 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,7038 offset, 1, ENC_BIG_ENDIAN0x00000000);7039 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,7040 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);7041 7042 if (optlen < TCPOLEN_RVBD_PROBE_MIN3) {7043 /* Bogus - option length is less than what it's supposed to be for7044 this option. */7045 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,7046 "option length should be >= %u)",7047 TCPOLEN_RVBD_PROBE_MIN3);7048 return tvb_captured_length(tvb);7049 }7050 7051 rvbd_probe_decode_version_type(7052 tvb_get_guint8(tvb, offset + PROBE_VERSION_TYPE_OFFSET2),7053 &ver, &type);7054 7055 proto_item_append_text(pitem, ": %s", val_to_str_const(type, rvbd_probe_type_vs, "Probe Unknown"));7056 7057 if (type >= PROBE_TYPE_MAX)7058 return tvb_captured_length(tvb);7059 7060 if (ver == PROBE_VERSION_1) {7061 guint16 port;7062 7063 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type1, tvb,7064 offset + PROBE_VERSION_TYPE_OFFSET2, 1, ENC_BIG_ENDIAN0x00000000);7065 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,7066 offset + PROBE_VERSION_TYPE_OFFSET2, 1, ENC_BIG_ENDIAN0x00000000);7067 7068 if (type == PROBE_INTERNAL)7069 return offset + PROBE_VERSION_TYPE_OFFSET2;7070 7071 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_reserved, tvb, offset + PROBE_V1_RESERVED_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000);7072 7073 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_prober, tvb,7074 offset + PROBE_V1_PROBER_OFFSET4, 4, ENC_BIG_ENDIAN0x00000000);7075 7076 switch (type) {7077 7078 case PROBE_QUERY:7079 case PROBE_QUERY_SH:7080 case PROBE_TRACE:7081 {7082 rvbd_option_data* option_data;7083 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_appli_ver, tvb,7084 offset + PROBE_V1_APPLI_VERSION_OFFSET8, 2,7085 ENC_BIG_ENDIAN0x00000000);7086 7087 proto_item_append_text(pitem, ", CSH IP: %s", tvb_ip_to_str(pinfo->pool, tvb, offset + PROBE_V1_PROBER_OFFSET)tvb_address_to_str(pinfo->pool, tvb, AT_IPv4, offset + 4));7088 7089 option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);7090 if (option_data == NULL((void*)0))7091 {7092 option_data = wmem_new0(pinfo->pool, rvbd_option_data)((rvbd_option_data*)wmem_alloc0((pinfo->pool), sizeof(rvbd_option_data
)))
;7093 p_add_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num, option_data);7094 }7095 7096 option_data->valid = TRUE(!(0));7097 option_data->type = type;7098 7099 }7100 break;7101 7102 case PROBE_RESPONSE:7103 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,7104 offset + PROBE_V1_PROXY_ADDR_OFFSET8, 4, ENC_BIG_ENDIAN0x00000000);7105 7106 port = tvb_get_ntohs(tvb, offset + PROBE_V1_PROXY_PORT_OFFSET12);7107 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,7108 offset + PROBE_V1_PROXY_PORT_OFFSET12, 2, ENC_BIG_ENDIAN0x00000000);7109 7110 rvbd_probe_resp_add_info(pitem, pinfo, tvb, offset + PROBE_V1_PROXY_ADDR_OFFSET8, port);7111 break;7112 7113 case PROBE_RESPONSE_SH:7114 proto_tree_add_item(field_tree,7115 hf_tcp_option_rvbd_probe_client, tvb,7116 offset + PROBE_V1_SH_CLIENT_ADDR_OFFSET8, 4,7117 ENC_BIG_ENDIAN0x00000000);7118 7119 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,7120 offset + PROBE_V1_SH_PROXY_ADDR_OFFSET12, 4, ENC_BIG_ENDIAN0x00000000);7121 7122 port = tvb_get_ntohs(tvb, offset + PROBE_V1_SH_PROXY_PORT_OFFSET16);7123 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,7124 offset + PROBE_V1_SH_PROXY_PORT_OFFSET16, 2, ENC_BIG_ENDIAN0x00000000);7125 7126 rvbd_probe_resp_add_info(pitem, pinfo, tvb, offset + PROBE_V1_SH_PROXY_ADDR_OFFSET12, port);7127 break;7128 }7129 }7130 else if (ver == PROBE_VERSION_2) {7131 proto_item *ver_pi;7132 proto_item *flag_pi;7133 proto_tree *flag_tree;7134 guint8 flags;7135 7136 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type2, tvb,7137 offset + PROBE_VERSION_TYPE_OFFSET2, 1, ENC_BIG_ENDIAN0x00000000);7138 7139 proto_tree_add_uint_format_value(7140 field_tree, hf_tcp_option_rvbd_probe_version2, tvb,7141 offset + PROBE_VERSION_TYPE_OFFSET2, 1, ver, "%u", ver);7142 /* Use version1 for filtering purposes because version2 packet7143 value is 0, but filtering is usually done for value 2 */7144 ver_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,7145 offset + PROBE_VERSION_TYPE_OFFSET2, 1, ver);7146 proto_item_set_hidden(ver_pi);7147 7148 switch (type) {7149 7150 case PROBE_QUERY_INFO:7151 case PROBE_QUERY_INFO_SH:7152 case PROBE_QUERY_INFO_SID:7153 flags = tvb_get_guint8(tvb, offset + PROBE_V2_INFO_OFFSET3);7154 flag_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_flags,7155 tvb, offset + PROBE_V2_INFO_OFFSET3,7156 1, flags);7157 7158 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);7159 proto_tree_add_item(flag_tree,7160 hf_tcp_option_rvbd_probe_flag_not_cfe,7161 tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000);7162 proto_tree_add_item(flag_tree,7163 hf_tcp_option_rvbd_probe_flag_last_notify,7164 tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000);7165 7166 switch (type)7167 {7168 case PROBE_QUERY_INFO:7169 {7170 rvbd_option_data* option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);7171 if (option_data == NULL((void*)0))7172 {7173 option_data = wmem_new0(pinfo->pool, rvbd_option_data)((rvbd_option_data*)wmem_alloc0((pinfo->pool), sizeof(rvbd_option_data
)))
;7174 p_add_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num, option_data);7175 }7176 7177 option_data->probe_flags = flags;7178 }7179 break;7180 case PROBE_QUERY_INFO_SH:7181 proto_tree_add_item(flag_tree,7182 hf_tcp_option_rvbd_probe_client, tvb,7183 offset + PROBE_V2_INFO_CLIENT_ADDR_OFFSET4,7184 4, ENC_BIG_ENDIAN0x00000000);7185 break;7186 case PROBE_QUERY_INFO_SID:7187 proto_tree_add_item(flag_tree,7188 hf_tcp_option_rvbd_probe_storeid, tvb,7189 offset + PROBE_V2_INFO_STOREID_OFFSET4,7190 4, ENC_BIG_ENDIAN0x00000000);7191 break;7192 }7193 7194 if (type != PROBE_QUERY_INFO_SID &&7195 tcph != NULL((void*)0) &&7196 (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == (TH_SYN0x0002|TH_ACK0x0010) &&7197 (flags & RVBD_FLAGS_PROBE_LAST0x01)) {7198 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA++, ");7199 }7200 7201 break;7202 7203 case PROBE_RESPONSE_INFO:7204 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,7205 tvb, offset + PROBE_V2_INFO_OFFSET3,7206 1, ENC_BIG_ENDIAN0x00000000);7207 7208 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);7209 proto_tree_add_item(flag_tree,7210 hf_tcp_option_rvbd_probe_flag_probe_cache,7211 tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000);7212 proto_tree_add_item(flag_tree,7213 hf_tcp_option_rvbd_probe_flag_sslcert,7214 tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000);7215 proto_tree_add_item(flag_tree,7216 hf_tcp_option_rvbd_probe_flag_server_connected,7217 tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000);7218 break;7219 7220 case PROBE_RST:7221 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,7222 tvb, offset + PROBE_V2_INFO_OFFSET3,7223 1, ENC_BIG_ENDIAN0x00000000);7224 break;7225 }7226 }7227 7228 return tvb_captured_length(tvb);7229}7230 7231enum {7232 TRPY_OPTNUM_OFFSET = 0,7233 TRPY_OPTLEN_OFFSET = 1,7234 7235 TRPY_OPTIONS_OFFSET = 2,7236 TRPY_SRC_ADDR_OFFSET = 4,7237 TRPY_DST_ADDR_OFFSET = 8,7238 TRPY_SRC_PORT_OFFSET = 12,7239 TRPY_DST_PORT_OFFSET = 14,7240 TRPY_CLIENT_PORT_OFFSET = 167241};7242 7243/* Trpy Flags */7244#define RVBD_FLAGS_TRPY_MODE0x0001 0x00017245#define RVBD_FLAGS_TRPY_OOB0x0002 0x00027246#define RVBD_FLAGS_TRPY_CHKSUM0x0004 0x00047247#define RVBD_FLAGS_TRPY_FW_RST0x0100 0x01007248#define RVBD_FLAGS_TRPY_FW_RST_INNER0x0200 0x02007249#define RVBD_FLAGS_TRPY_FW_RST_PROBE0x0400 0x04007250 7251static const true_false_string trpy_mode_str = {7252 "Port Transparency",7253 "Full Transparency"7254};7255 7256static int7257dissect_tcpopt_rvbd_trpy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))7258{7259 proto_tree *field_tree;7260 proto_item *pitem;7261 proto_item *length_item;7262 guint16 sport, dport, flags;7263 int offset = 0,7264 optlen = tvb_reported_length(tvb);7265 static int * const rvbd_trpy_flags[] = {7266 &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,7267 &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,7268 &hf_tcp_option_rvbd_trpy_flag_fw_rst,7269 &hf_tcp_option_rvbd_trpy_flag_chksum,7270 &hf_tcp_option_rvbd_trpy_flag_oob,7271 &hf_tcp_option_rvbd_trpy_flag_mode,7272 NULL((void*)0)7273 };7274 7275 col_prepend_fstr(pinfo->cinfo, COL_INFO, "TRPY, ");7276 7277 pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_trpy, tvb, offset, -1, ENC_NA0x00000000);7278 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_trpy);7279 7280 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,7281 offset, 1, ENC_BIG_ENDIAN0x00000000);7282 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,7283 offset + 1, 1, ENC_BIG_ENDIAN0x00000000);7284 7285 if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_RVBD_TRPY_MIN16))7286 return tvb_captured_length(tvb);7287 7288 flags = tvb_get_ntohs(tvb, offset + TRPY_OPTIONS_OFFSET);7289 proto_tree_add_bitmask_with_flags(field_tree, tvb, offset + TRPY_OPTIONS_OFFSET, hf_tcp_option_rvbd_trpy_flags,7290 ett_tcp_opt_rvbd_trpy_flags, rvbd_trpy_flags, ENC_NA0x00000000, BMT_NO_APPEND0x01);7291 7292 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src,7293 tvb, offset + TRPY_SRC_ADDR_OFFSET, 4, ENC_BIG_ENDIAN0x00000000);7294 7295 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst,7296 tvb, offset + TRPY_DST_ADDR_OFFSET, 4, ENC_BIG_ENDIAN0x00000000);7297 7298 sport = tvb_get_ntohs(tvb, offset + TRPY_SRC_PORT_OFFSET);7299 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src_port,7300 tvb, offset + TRPY_SRC_PORT_OFFSET, 2, ENC_BIG_ENDIAN0x00000000);7301 7302 dport = tvb_get_ntohs(tvb, offset + TRPY_DST_PORT_OFFSET);7303 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst_port,7304 tvb, offset + TRPY_DST_PORT_OFFSET, 2, ENC_BIG_ENDIAN0x00000000);7305 7306 proto_item_append_text(pitem, " %s:%u -> %s:%u",7307 tvb_ip_to_str(pinfo->pool, tvb, offset + TRPY_SRC_ADDR_OFFSET)tvb_address_to_str(pinfo->pool, tvb, AT_IPv4, offset + TRPY_SRC_ADDR_OFFSET
)
, sport,7308 tvb_ip_to_str(pinfo->pool, tvb, offset + TRPY_DST_ADDR_OFFSET)tvb_address_to_str(pinfo->pool, tvb, AT_IPv4, offset + TRPY_DST_ADDR_OFFSET
)
, dport);7309 7310 /* Client port only set on SYN: optlen == 18 */7311 if ((flags & RVBD_FLAGS_TRPY_OOB0x0002) && (optlen > TCPOLEN_RVBD_TRPY_MIN16))7312 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_client_port,7313 tvb, offset + TRPY_CLIENT_PORT_OFFSET, 2, ENC_BIG_ENDIAN0x00000000);7314 7315 /* Despite that we have the right TCP ports for other protocols,7316 * the data is related to the Riverbed Optimization Protocol and7317 * not understandable by normal protocol dissectors. If the sport7318 * protocol is available then use that, otherwise just output it7319 * as a hex-dump.7320 */7321 if (sport_handle != NULL((void*)0)) {7322 conversation_t *conversation;7323 conversation = find_or_create_conversation(pinfo);7324 if (conversation_get_dissector(conversation, pinfo->num) != sport_handle) {7325 conversation_set_dissector(conversation, sport_handle);7326 }7327 } else if (data_handle != NULL((void*)0)) {7328 conversation_t *conversation;7329 conversation = find_or_create_conversation(pinfo);7330 if (conversation_get_dissector(conversation, pinfo->num) != data_handle) {7331 conversation_set_dissector(conversation, data_handle);7332 }7333 }7334 7335 return tvb_captured_length(tvb);7336}7337 7338 /* Started as a copy of dissect_ip_tcp_options(), but was changed to support7339 options as a dissector table */7340static void7341tcp_dissect_options(tvbuff_t *tvb, int offset, guint length,7342 packet_info *pinfo, proto_tree *opt_tree,7343 proto_item *opt_item, void * data)7344{7345 guchar opt;7346 guint optlen, nop_count = 0;7347 proto_tree *field_tree;7348 const char *name;7349 dissector_handle_t option_dissector;7350 tvbuff_t *next_tvb;7351 struct tcpheader *tcph = (struct tcpheader *)data;7352 gboolean mss_seen = FALSE(0);7353 gboolean eol_seen = FALSE(0);7354 gboolean sack_perm_seen = FALSE(0);7355 7356 while (length > 0) {7357 opt = tvb_get_guint8(tvb, offset);7358 if (eol_seen && opt != TCPOPT_EOL0) {7359 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_non_zero_bytes_after_eol, tvb, offset, length,7360 "Non-zero header padding");7361 return;7362 }7363 --length; /* account for type byte */7364 if ((opt == TCPOPT_EOL0) || (opt == TCPOPT_NOP1)) {7365 int local_proto;7366 proto_item* field_item;7367 7368 /* We assume that the only options with no length are EOL and7369 NOP options, so that we can treat unknown options as having7370 a minimum length of 2, and at least be able to move on to7371 the next option by using the length in the option. */7372 if (opt == TCPOPT_EOL0) {7373 local_proto = proto_tcp_option_eol;7374 eol_seen = true1;7375 } else if (opt == TCPOPT_NOP1) {7376 local_proto = proto_tcp_option_nop;7377 7378 if (opt_item && (nop_count == 0 || offset % 4)) {7379 /* Count number of NOP in a row within a uint32 */7380 nop_count++;7381 7382 if (nop_count == 4) {7383 expert_add_info(pinfo, opt_item, &ei_tcp_nop);7384 }7385 } else {7386 nop_count = 0;7387 }7388 } else {7389 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/dissectors/packet-tcp.c", 7389))
;7390 }7391 7392 field_item = proto_tree_add_item(opt_tree, local_proto, tvb, offset, 1, ENC_NA0x00000000);7393 field_tree = proto_item_add_subtree(field_item, ett_tcp_option_other);7394 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);7395 proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", proto_get_protocol_short_name(find_protocol_by_id(local_proto)));7396 offset += 1;7397 } else {7398 option_dissector = dissector_get_uint_handle(tcp_option_table, opt);7399 if (option_dissector == NULL((void*)0)) {7400 name = wmem_strdup_printf(pinfo->pool, "Unknown (0x%02x)", opt);7401 option_dissector = tcp_opt_unknown_handle;7402 } else {7403 name = dissector_handle_get_protocol_short_name(option_dissector);7404 }7405 7406 /* Option has a length. Is it in the packet? */7407 if (length == 0) {7408 /* Bogus - packet must at least include option code byte and7409 length byte! */7410 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, 1,7411 "%s (length byte past end of options)", name);7412 return;7413 }7414 7415 optlen = tvb_get_guint8(tvb, offset + 1); /* total including type, len */7416 --length; /* account for length byte */7417 7418 if (optlen < 2) {7419 /* Bogus - option length is too short to include option code and7420 option length. */7421 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, 2,7422 "%s (with too-short option length = %u byte%s)",7423 name, optlen, plurality(optlen, "", "s")((optlen) == 1 ? ("") : ("s")));7424 return;7425 } else if (optlen - 2 > length) {7426 /* Bogus - option goes past the end of the header. */7427 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, length,7428 "%s (option length = %u byte%s says option goes past end of options)",7429 name, optlen, plurality(optlen, "", "s")((optlen) == 1 ? ("") : ("s")));7430 return;7431 }7432 7433 if (opt == TCPOPT_MSS2)7434 {7435 mss_seen = TRUE(!(0));7436 } else if (opt == TCPOPT_SACK_PERM4)7437 {7438 sack_perm_seen = TRUE(!(0));7439 }7440 7441 next_tvb = tvb_new_subset_length(tvb, offset, optlen);7442 call_dissector_with_data(option_dissector, next_tvb, pinfo, opt_tree/* tree */, data);7443 proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name);7444 7445 offset += optlen;7446 length -= (optlen-2); //already accounted for type and len bytes7447 }7448 }7449 7450 if (tcph->th_flags & TH_SYN0x0002)7451 {7452 if (mss_seen == FALSE(0))7453 {7454 expert_add_info(pinfo, opt_item, &ei_tcp_option_mss_absent);7455 }7456 if (sack_perm_seen == FALSE(0))7457 {7458 expert_add_info(pinfo, opt_item, &ei_tcp_option_sack_perm_absent);7459 }7460 }7461}7462 7463/* Determine if there is a sub-dissector and call it; return TRUE7464 if there was a sub-dissector, FALSE otherwise.7465 7466 This has been separated into a stand alone routine to other protocol7467 dissectors can call to it, e.g., SOCKS. */7468 7469static bool_Bool try_heuristic_first;7470 7471 7472/* this function can be called with tcpd==NULL as from the msproxy dissector */7473gboolean7474decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,7475 proto_tree *tree, int src_port, int dst_port,7476 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)7477{7478 tvbuff_t *next_tvb;7479 int low_port, high_port;7480 int save_desegment_offset;7481 gboolean try_low_port, try_high_port, try_server_port;7482 guint32 save_desegment_len;7483 heur_dtbl_entry_t *hdtbl_entry;7484 exp_pdu_data_t *exp_pdu_data;7485 7486 /* Don't call subdissectors for keepalives. Even though they do contain7487 * payload "data", it's just garbage. Display any data the keepalive7488 * packet might contain though.7489 */7490 if(tcpd && tcpd->ta) {7491 if(tcpd->ta->flags&TCP_A_KEEP_ALIVE0x0008) {7492 next_tvb = tvb_new_subset_remaining(tvb, offset);7493 call_dissector(data_handle, next_tvb, pinfo, tree);7494 return TRUE(!(0));7495 }7496 }7497 7498 if (tcp_no_subdissector_on_error && !(tcp_desegment && tcp_reassemble_out_of_order) &&7499 tcpd && tcpd->ta && tcpd->ta->flags & (TCP_A_RETRANSMISSION0x0001 | TCP_A_OUT_OF_ORDER0x0200)) {7500 /* Don't try to dissect a retransmission high chance that it will mess7501 * subdissectors for protocols that require in-order delivery of the7502 * PDUs. (i.e. DCE/RPCoverHTTP and encryption)7503 * If OoO reassembly is enabled and if this segment was previously lost,7504 * then this retransmission could have finished reassembly, so continue.7505 * XXX should this option be removed? "tcp_reassemble_out_of_order"7506 * should have addressed the above in-order requirement.7507 */7508 return FALSE(0);7509 }7510 next_tvb = tvb_new_subset_remaining(tvb, offset);7511 7512 save_desegment_offset = pinfo->desegment_offset;7513 save_desegment_len = pinfo->desegment_len;7514 7515/* determine if this packet is part of a conversation and call dissector */7516/* for the conversation if available */7517 7518 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, CONVERSATION_TCP,7519 src_port, dst_port, next_tvb, pinfo, tree, tcpinfo, 0)) {7520 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7521 handle_export_pdu_conversation(pinfo, next_tvb, src_port, dst_port, tcpinfo);7522 return TRUE(!(0));7523 }7524 7525 /* If the user has manually configured one of the server, low, or high7526 * ports to a dissector other than the default (via Decode As or the7527 * preferences associated with Decode As), try those first, in that order.7528 */7529 try_server_port = FALSE(0);7530 if (tcpd && tcpd->server_port != 0) {7531 if (dissector_is_uint_changed(subdissector_table, tcpd->server_port)) {7532 if (dissector_try_uint_new(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) {7533 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7534 handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo);7535 return TRUE(!(0));7536 }7537 } else {7538 /* The default; try it later */7539 try_server_port = TRUE(!(0));7540 }7541 }7542 7543 if (src_port > dst_port) {7544 low_port = dst_port;7545 high_port = src_port;7546 } else {7547 low_port = src_port;7548 high_port = dst_port;7549 }7550 7551 try_low_port = FALSE(0);7552 if (low_port != 0) {7553 if (dissector_is_uint_changed(subdissector_table, low_port)) {7554 if (dissector_try_uint_new(subdissector_table, low_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) {7555 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7556 handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo);7557 return TRUE(!(0));7558 }7559 } else {7560 /* The default; try it later */7561 try_low_port = TRUE(!(0));7562 }7563 }7564 7565 try_high_port = FALSE(0);7566 if (high_port != 0) {7567 if (dissector_is_uint_changed(subdissector_table, high_port)) {7568 if (dissector_try_uint_new(subdissector_table, high_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) {7569 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7570 handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo);7571 return TRUE(!(0));7572 }7573 } else {7574 /* The default; try it later */7575 try_high_port = TRUE(!(0));7576 }7577 }7578 7579 if (try_heuristic_first) {7580 /* do lookup with the heuristic subdissector table */7581 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) {7582 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7583 handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo);7584 return TRUE(!(0));7585 }7586 }7587 7588 /* Do lookups with the subdissector table.7589 Try the server port captured on the SYN or SYN|ACK packet. After that7590 try the port number with the lower value first, followed by the7591 port number with the higher value. This means that, for packets7592 where a dissector is registered for *both* port numbers:7593 7594 1) we pick the same dissector for traffic going in both directions;7595 7596 2) we prefer the port number that's more likely to be the right7597 one (as that prefers well-known ports to reserved ports);7598 7599 although there is, of course, no guarantee that any such strategy7600 will always pick the right port number.7601 7602 XXX - we ignore port numbers of 0, as some dissectors use a port7603 number of 0 to disable the port. */7604 7605 if (try_server_port &&7606 dissector_try_uint_new(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) {7607 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7608 handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo);7609 return TRUE(!(0));7610 }7611 7612 if (try_low_port &&7613 dissector_try_uint_new(subdissector_table, low_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) {7614 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7615 handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo);7616 return TRUE(!(0));7617 }7618 if (try_high_port &&7619 dissector_try_uint_new(subdissector_table, high_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) {7620 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7621 handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo);7622 return TRUE(!(0));7623 }7624 7625 if (!try_heuristic_first) {7626 /* do lookup with the heuristic subdissector table */7627 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) {7628 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7629 handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo);7630 return TRUE(!(0));7631 }7632 }7633 7634 /*7635 * heuristic / conversation / port registered dissectors rejected the packet;7636 * make sure they didn't also request desegmentation (we could just override7637 * the request, but rejecting a packet *and* requesting desegmentation is a sign7638 * of the dissector's code needing clearer thought, so we fail so that the7639 * problem is made more obvious).7640 */7641 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&((void) ((save_desegment_offset == pinfo->desegment_offset
&& save_desegment_len == pinfo->desegment_len) ? (
void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 7642, "save_desegment_offset == pinfo->desegment_offset && save_desegment_len == pinfo->desegment_len"
))))
7642 save_desegment_len == pinfo->desegment_len)((void) ((save_desegment_offset == pinfo->desegment_offset
&& save_desegment_len == pinfo->desegment_len) ? (
void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-tcp.c", 7642, "save_desegment_offset == pinfo->desegment_offset && save_desegment_len == pinfo->desegment_len"
))))
;7643 7644 /* Oh, well, we don't know this; dissect it as data. */7645 call_dissector(data_handle,next_tvb, pinfo, tree);7646 7647 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);7648 if (have_tap_listener(exported_pdu_tap)) {7649 exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME12);7650 exp_pdu_data->tvb_captured_length = tvb_captured_length(next_tvb);7651 exp_pdu_data->tvb_reported_length = tvb_reported_length(next_tvb);7652 exp_pdu_data->pdu_tvb = next_tvb;7653 7654 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);7655 }7656 return FALSE(0);7657}7658 7659static void7660process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,7661 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,7662 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,7663 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)7664{7665 pinfo->want_pdu_tracking=0;7666 7667 TRY{ except_t *volatile exc; volatile int except_state = 0; static
const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode
except_sn; struct except_catch except_ch; except_setup_try(&
except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch
.except_jmp)) *(&exc) = &except_ch.except_obj; else *
(&exc) = 0; if(except_state & 1) except_state |= 2; except_state
&= ~1; if (except_state == 0 && exc == 0)
{7668 if(is_tcp_segment) {7669 /*qqq see if it is an unaligned PDU */7670 if(tcpd && tcp_analyze_seq && (!tcp_desegment)) {7671 if(seq || nxtseq) {7672 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,7673 seq, nxtseq, tcpd->fwd->multisegment_pdus);7674 }7675 }7676 }7677 /* if offset is -1 this means that this segment is known7678 * to be fully inside a previously detected pdu7679 * so we don't even need to try to dissect it either.7680 */7681 if( (offset!=-1) &&7682 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,7683 dst_port, tcpd, tcpinfo) ) {7684 /*7685 * We succeeded in handing off to a subdissector.7686 *7687 * Is this a TCP segment or a reassembled chunk of7688 * TCP payload?7689 */7690 if(is_tcp_segment) {7691 /* if !visited, check want_pdu_tracking and7692 store it in table */7693 if(tcpd && (!pinfo->fd->visited) &&7694 tcp_analyze_seq && pinfo->want_pdu_tracking) {7695 if(seq || nxtseq) {7696 pdu_store_sequencenumber_of_next_pdu(7697 pinfo,7698 seq,7699 nxtseq+pinfo->bytes_until_next_pdu,7700 tcpd->fwd->multisegment_pdus);7701 }7702 }7703 }7704 }7705 }7706 CATCH_ALLif (except_state == 0 && exc != 0 && (except_state
|=1))
{7707 /* We got an exception. At this point the dissection is7708 * completely aborted and execution will be transferred back7709 * to (probably) the frame dissector.7710 * Here we have to place whatever we want the dissector7711 * to do before aborting the tcp dissection.7712 */7713 /*7714 * Is this a TCP segment or a reassembled chunk of TCP7715 * payload?7716 */7717 if(is_tcp_segment) {7718 /*7719 * It's from a TCP segment.7720 *7721 * if !visited, check want_pdu_tracking and store it7722 * in table7723 */7724 if(tcpd && (!pinfo->fd->visited) && tcp_analyze_seq && pinfo->want_pdu_tracking) {7725 if(seq || nxtseq) {7726 pdu_store_sequencenumber_of_next_pdu(pinfo,7727 seq,7728 nxtseq+pinfo->bytes_until_next_pdu,7729 tcpd->fwd->multisegment_pdus);7730 }7731 }7732 }7733 RETHROW{ do { if ((1) && !(except_state == 1)) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/dissectors/packet-tcp.c", 7733, __func__
, "assertion failed: %s", "except_state == 1"); } while (0); longjmp
(except_ch.except_jmp,1); }
;7734 }7735 ENDTRYif(!(except_state&1) && exc != 0) except_rethrow(
exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}
;7736}7737 7738void7739dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,7740 guint32 nxtseq, guint32 sport, guint32 dport,7741 proto_tree *tree, proto_tree *tcp_tree,7742 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)7743{7744 gint nbytes;7745 gboolean save_fragmented;7746 7747 nbytes = tvb_reported_length_remaining(tvb, offset);7748 proto_tree_add_bytes_format(tcp_tree, hf_tcp_payload, tvb, offset,7749 -1, NULL((void*)0), "TCP payload (%u byte%s)", nbytes,7750 plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s")));7751 7752 /* Can we desegment this segment? */7753 if (pinfo->can_desegment) {7754 /* Yes. */7755 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,7756 tcp_tree, tcpd, tcpinfo);7757 } else {7758 /* No - just call the subdissector.7759 Mark this as fragmented, so if somebody throws an exception,7760 we don't report it as a malformed frame. */7761 save_fragmented = pinfo->fragmented;7762 pinfo->fragmented = TRUE(!(0));7763 7764 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,7765 seq, nxtseq, TRUE(!(0)), tcpd, tcpinfo);7766 pinfo->fragmented = save_fragmented;7767 }7768}7769 7770static gboolean7771capture_tcp(const guchar *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header)7772{7773 guint16 src_port, dst_port, low_port, high_port;7774 7775 if (!BYTES_ARE_IN_FRAME(offset, len, 4)((guint)(offset) + (guint)(4) > (guint)(offset) &&
(guint)(offset) + (guint)(4) <= (guint)(len))
)7776 return FALSE(0);7777 7778 capture_dissector_increment_count(cpinfo, proto_tcp);7779 7780 src_port = pntoh16(&pd[offset]);7781 dst_port = pntoh16(&pd[offset+2]);7782 7783 if (src_port > dst_port) {7784 low_port = dst_port;7785 high_port = src_port;7786 } else {7787 low_port = src_port;7788 high_port = dst_port;7789 }7790 7791 if (low_port != 0 &&7792 try_capture_dissector("tcp.port", low_port, pd, offset+20, len, cpinfo, pseudo_header))7793 return TRUE(!(0));7794 7795 if (high_port != 0 &&7796 try_capture_dissector("tcp.port", high_port, pd, offset+20, len, cpinfo, pseudo_header))7797 return TRUE(!(0));7798 7799 /* We've at least identified one type of packet, so this shouldn't be "other" */7800 return TRUE(!(0));7801}7802 7803typedef struct _tcp_tap_cleanup_t {7804 7805 packet_info *pinfo;7806 struct tcpheader *tcph;7807 7808} tcp_tap_cleanup_t;7809 7810static void tcp_tap_cleanup(void *data)7811{7812 tcp_tap_cleanup_t *cleanup = (tcp_tap_cleanup_t *)data;7813 7814 tap_queue_packet(tcp_tap, cleanup->pinfo, cleanup->tcph);7815}7816 7817static int7818dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))7819{7820 guint8 th_off_x2; /* combines th_off and th_x2 */7821 guint16 th_sum;7822 guint32 th_urp;7823 proto_tree *tcp_tree = NULL((void*)0), *field_tree = NULL((void*)0);7824 proto_item *ti = NULL((void*)0), *tf, *hidden_item;7825 proto_item *options_item, *hide_seqack_abs_item;7826 proto_tree *options_tree;7827 int offset = 0;7828 char *flags_str, *flags_str_first_letter;7829 guint optlen;7830 guint32 nxtseq = 0;7831 guint reported_len;7832 vec_t cksum_vec[4];7833 guint32 phdr[2];7834 guint16 computed_cksum;7835 guint16 real_window;7836 guint captured_length_remaining;7837 gboolean desegment_ok;7838 struct tcpinfo tcpinfo;7839 struct tcpheader *tcph;7840 proto_item *tf_syn = NULL((void*)0), *tf_fin = NULL((void*)0), *tf_rst = NULL((void*)0), *scaled_pi;7841 conversation_t *conv=NULL((void*)0);7842 struct tcp_analysis *tcpd=NULL((void*)0);7843 struct tcp_per_packet_data_t *tcppd=NULL((void*)0);7844 proto_item *item;7845 proto_tree *checksum_tree;7846 gboolean icmp_ip = FALSE(0);7847 guint8 conversation_completeness = 0;7848 gboolean conversation_is_new = FALSE(0);7849 guint8 ace;7850 7851 tcph = wmem_new0(pinfo->pool, struct tcpheader)((struct tcpheader*)wmem_alloc0((pinfo->pool), sizeof(struct
tcpheader)))
;7852 tcph->th_sport = tvb_get_ntohs(tvb, offset);7853 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);7854 copy_address_shallow(&tcph->ip_src, &pinfo->src);7855 copy_address_shallow(&tcph->ip_dst, &pinfo->dst);7856 7857 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");7858 col_clear(pinfo->cinfo, COL_INFO);7859 col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, tcph->th_sport, tcph->th_dport);7860 7861 if (tree) {7862 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, ENC_NA0x00000000);7863 if (tcp_summary_in_tree) {7864 proto_item_append_text(ti, ", Src Port: %s, Dst Port: %s",7865 port_with_resolution_to_str(pinfo->pool, PT_TCP, tcph->th_sport),7866 port_with_resolution_to_str(pinfo->pool, PT_TCP, tcph->th_dport));7867 }7868 tcp_tree = proto_item_add_subtree(ti, ett_tcp);7869 p_add_proto_data(pinfo->pool, pinfo, proto_tcp, pinfo->curr_layer_num, tcp_tree);7870 7871 proto_tree_add_item(tcp_tree, hf_tcp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);7872 proto_tree_add_item(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000);7873 hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);7874 proto_item_set_hidden(hidden_item);7875 hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000);7876 proto_item_set_hidden(hidden_item);7877 7878 /* If we're dissecting the headers of a TCP packet in an ICMP packet7879 * then go ahead and put the sequence numbers in the tree now (because7880 * they won't be put in later because the ICMP packet only contains up7881 * to the sequence number).7882 * We should only need to do this for IPv4 since IPv6 will hopefully7883 * carry enough TCP payload for this dissector to put the sequence7884 * numbers in via the regular code path.7885 */7886 {7887 wmem_list_frame_t *frame;7888 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));7889 if (proto_ip == (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))((guint) (gulong) (wmem_list_frame_data(frame)))) {7890 frame = wmem_list_frame_prev(frame);7891 if (proto_icmp == (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))((guint) (gulong) (wmem_list_frame_data(frame)))) {7892 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, ENC_BIG_ENDIAN0x00000000);7893 icmp_ip = TRUE(!(0));7894 }7895 }7896 }7897 }7898 7899 /* Set the source and destination port numbers as soon as we get them,7900 so that they're available to the "Follow TCP Stream" code even if7901 we throw an exception dissecting the rest of the TCP header. */7902 pinfo->ptype = PT_TCP;7903 pinfo->srcport = tcph->th_sport;7904 pinfo->destport = tcph->th_dport;7905 7906 p_add_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num, GUINT_TO_POINTER(tcph->th_sport)((gpointer) (gulong) (tcph->th_sport)));7907 p_add_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num, GUINT_TO_POINTER(tcph->th_dport)((gpointer) (gulong) (tcph->th_dport)));7908 7909 tcph->th_rawseq = tvb_get_ntohl(tvb, offset + 4);7910 tcph->th_seq = tcph->th_rawseq;7911 tcph->th_rawack = tvb_get_ntohl(tvb, offset + 8);7912 tcph->th_ack = tcph->th_rawack;7913 th_off_x2 = tvb_get_guint8(tvb, offset + 12);7914 tcpinfo.flags = tcph->th_flags = tvb_get_ntohs(tvb, offset + 12) & TH_MASK0x0FFF;7915 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);7916 real_window = tcph->th_win;7917 tcph->th_hlen = hi_nibble(th_off_x2)(((th_off_x2) & 0xf0) >> 4) * 4; /* TCP header length, in bytes */7918 7919 /* find(or create if needed) the conversation for this tcp session7920 * This is a slight deviation from find_or_create_conversation so it's7921 * done manually. This is done to avoid conversation overlapping when7922 * reusing ports (see issue 15097), as find_or_create_conversation automatically7923 * extends the conversation found. This extension is done later.7924 */7925 gboolean is_ordinary_conv = TRUE(!(0));7926 7927 /* deinterlacing requested */7928 if(prefs.conversation_deinterlacing_key>0) {7929 guint conv_type;7930 guint32 dtlc_iface = 0;7931 guint32 dtlc_vlan = 0;7932 7933 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_INTERFACE0x02 &&7934 pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID0x00000004) {7935 7936 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN0x08 &&7937 pinfo->vlan_id>0) {7938 7939 conv_type = CONVERSATION_ETH_IV;7940 dtlc_vlan = pinfo->vlan_id;7941 }7942 else {7943 conv_type = CONVERSATION_ETH_IN;7944 }7945 dtlc_iface = pinfo->rec->rec_header.packet_header.interface_id;7946 }7947 else {7948 7949 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN0x08 &&7950 pinfo->vlan_id>0) {7951 7952 conv_type = CONVERSATION_ETH_NV;7953 dtlc_vlan = pinfo->vlan_id;7954 }7955 else {7956 conv_type = CONVERSATION_ETH_NN;7957 }7958 }7959 conversation_t *underlying_conv = find_conversation_deinterlacer(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, conv_type, dtlc_iface, dtlc_vlan , 0);7960 if(underlying_conv) {7961 is_ordinary_conv = FALSE(0);7962 7963 conv = find_conversation_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, pinfo->srcport, pinfo->destport, underlying_conv->conv_index, 0);7964 if(!conv) {7965 conv = conversation_new_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP,7966 pinfo->srcport, pinfo->destport, underlying_conv->conv_index, 0);7967 conversation_is_new = TRUE(!(0));7968 }7969 }7970 }7971 7972 /*7973 * When it's not asked to deinterlace, or if deinterlacing failed (no related IP conversation),7974 * just proceed the ordinary way.7975 */7976 if(is_ordinary_conv) {7977 7978 conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, pinfo->srcport, pinfo->destport, 0);7979 if(!conv) {7980 conv = conversation_new(pinfo->num, &pinfo->src,7981 &pinfo->dst, CONVERSATION_TCP,7982 pinfo->srcport, pinfo->destport, 0);7983 /* we need to know when a conversation is new then we initialize the completeness correctly */7984 conversation_is_new = TRUE(!(0));7985 }7986 }7987 tcpd=get_tcp_conversation_data(conv,pinfo);7988 7989 /* If this is a SYN packet, then check if its seq-nr is different7990 * from the base_seq of the retrieved conversation. If this is the7991 * case, create a new conversation with the same addresses and ports7992 * and set the TA_PORTS_REUSED flag. (XXX: There is a small chance7993 * that this is an old duplicate SYN received after the connection7994 * is ESTABLISHED on both sides, the other side will respond with7995 * an appropriate ACK, and this SYN ought to be ignored rather than7996 * create a new conversation.)7997 *7998 * If the seq-nr is the same as the base_seq, it might be a simple7999 * retransmission, reattempting a handshake that was reset (due8000 * to a half-open connection) with the same sequence number, or8001 * (unlikely) a new connection that happens to use the same sequence8002 * number as the previous one.8003 *8004 * If we have received a RST or FIN on the retrieved conversation,8005 * create a new conversation in order to clear out the follow info,8006 * sequence analysis, desegmentation, etc.8007 * If not, it's probably a retransmission, and will be marked8008 * as one later, but restore some flow values to reduce the8009 * sequence analysis warnings if our capture file is missing a RST8010 * or FIN segment that was present on the network.8011 *8012 * XXX - Is this affected by MPTCP which can use multiple SYNs?8013 */8014 if (tcpd != NULL((void*)0) && (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == TH_SYN0x0002) {8015 if (tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET0x01) {8016 if(tcph->th_seq!=tcpd->fwd->base_seq || (tcpd->conversation_completeness & TCP_COMPLETENESS_RST0x20) || (tcpd->conversation_completeness & TCP_COMPLETENESS_FIN0x10)) {8017 if (!(pinfo->fd->visited)) {8018 8019 conv=conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, pinfo->srcport, pinfo->destport, 0);8020 tcpd=get_tcp_conversation_data(conv,pinfo);8021 8022 if(!tcpd->ta)8023 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, TRUE(!(0)), tcpd);8024 tcpd->ta->flags|=TCP_A_REUSED_PORTS0x2000;8025 8026 /* As above, a new conversation starting with a SYN implies conversation completeness value 1 */8027 conversation_is_new = TRUE(!(0));8028 }8029 } else {8030 if (!(pinfo->fd->visited)) {8031 /*8032 * Sometimes we need to restore the nextseq value.8033 * As stated in RFC 793 3.4 a RST packet might be8034 * sent with SEQ being equal to the ACK received,8035 * thus breaking our flow monitoring. (issue 17616)8036 */8037 if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info) {8038 tcpd->fwd->tcp_analyze_seq_info->nextseq = tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked;8039 }8040 8041 if(!tcpd->ta)8042 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, TRUE(!(0)), tcpd);8043 }8044 }8045 }8046 else {8047 /*8048 * TCP_S_BASE_SEQ_SET being not set, we are dealing with a new conversation,8049 * either created ad hoc above (general case), or by a higher protocol such as FTP.8050 * Track this information, as the Completeness value will be initialized later.8051 * See issue 19092.8052 */8053 if (!(pinfo->fd->visited))8054 conversation_is_new = TRUE(!(0));8055 }8056 tcpd->had_acc_ecn_setup_syn = (tcph->th_flags & (TH_AE0x0100|TH_CWR0x0080|TH_ECE0x0040)) == (TH_AE0x0100|TH_CWR0x0080|TH_ECE0x0040);8057 }8058 8059 /* If this is a SYN/ACK packet, then check if its seq-nr is different8060 * from the base_seq of the retrieved conversation. If this is the8061 * case, set the TA_PORTS_REUSED flag and override the base seq.8062 * (XXX: Should this create a new conversation, as above with a8063 * SYN packet? We might have received the new connection's SYN/ACK before8064 * the SYN packet, or the SYN might be missing from the capture file.)8065 * If the seq-nr is the same as the base_seq, then do nothing so it8066 * will be marked as a retransmission later.8067 * XXX - Is this affected by MPTCP which can use multiple SYNs?8068 */8069 if (tcpd != NULL((void*)0) && (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == (TH_SYN0x0002|TH_ACK0x0010)) {8070 if ((tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET0x01) &&8071 (tcph->th_seq != tcpd->fwd->base_seq)) {8072 8073 /* the retrieved conversation might have a different base_seq (issue 16944) */8074 /* XXX: Shouldn't this create a new conversation? Changing the8075 * base_seq will change how the previous packets in the conversation8076 * are processed in the second pass.8077 */8078 tcpd->fwd->base_seq = tcph->th_seq;8079 8080 if(!tcpd->ta)8081 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, TRUE(!(0)), tcpd);8082 tcpd->ta->flags|=TCP_A_REUSED_PORTS0x2000;8083 }8084 tcpd->had_acc_ecn_setup_syn_ack = ((tcph->th_flags & (TH_AE0x0100|TH_CWR0x0080)) == TH_CWR0x0080) ||8085 ((tcph->th_flags & (TH_AE0x0100|TH_ECE0x0040)) == TH_AE0x0100);8086 }8087 8088 /* Do we need to calculate timestamps relative to the tcp-stream? */8089 if (tcp_calculate_ts) {8090 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);8091 8092 /*8093 * Calculate the timestamps relative to this conversation (but only on8094 * the first run when frames are accessed sequentially)8095 */8096 if (!(pinfo->fd->visited))8097 tcp_calculate_timestamps(pinfo, tcpd, tcppd);8098 }8099 8100 if (tcpd) {8101 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, tcpd->stream);8102 proto_item_set_generated(item);8103 8104 if (tcppd) {8105 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream_pnum, tvb, offset, 0, tcppd->pnum);8106 proto_item_set_generated(item);8107 }8108 8109 /* Display the completeness of this TCP conversation */8110 static int* const completeness_fields[] = {8111 &hf_tcp_completeness_rst,8112 &hf_tcp_completeness_fin,8113 &hf_tcp_completeness_data,8114 &hf_tcp_completeness_ack,8115 &hf_tcp_completeness_syn_ack,8116 &hf_tcp_completeness_syn,8117 NULL((void*)0)};8118 8119 item = proto_tree_add_bitmask_value_with_flags(tcp_tree, NULL((void*)0), 0,8120 hf_tcp_completeness, ett_tcp_completeness, completeness_fields,8121 tcpd->conversation_completeness, BMT_NO_APPEND0x01);8122 proto_item_set_generated(item);8123 field_tree = proto_item_add_subtree(item, ett_tcp_completeness);8124 8125 flags_str_first_letter = tcpd->conversation_completeness_str;8126 item = proto_tree_add_string(field_tree, hf_tcp_completeness_str, tvb, 0, 0, flags_str_first_letter);8127 proto_item_set_generated(item);8128 8129 /* Copy the stream index into the header as well to make it available8130 * to tap listeners.8131 */8132 tcph->th_stream = tcpd->stream;8133 8134 /* Copy the stream index into pinfo as well to make it available8135 * to callback functions (essentially conversation following events in GUI)8136 */8137 pinfo->stream_id = tcpd->stream;8138 8139 /* initialize the SACK blocks seen to 0 */8140 if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info) {8141 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = 0;8142 }8143 }8144 8145 /* is there any manual analysis waiting ? */8146 if(pinfo->fd->tcp_snd_manual_analysis > 0) {8147 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);8148 tcppd->tcp_snd_manual_analysis = pinfo->fd->tcp_snd_manual_analysis;8149 }8150 8151 /*8152 * If we've been handed an IP fragment, we don't know how big the TCP8153 * segment is, so don't do anything that requires that we know that.8154 *8155 * The same applies if we're part of an error packet. (XXX - if the8156 * ICMP and ICMPv6 dissectors could set a "this is how big the IP8157 * header says it is" length in the tvbuff, we could use that; such8158 * a length might also be useful for handling packets where the IP8159 * length is bigger than the actual data available in the frame; the8160 * dissectors should trust that length, and then throw a8161 * ReportedBoundsError exception when they go past the end of the frame.)8162 *8163 * We also can't determine the segment length if the reported length8164 * of the TCP packet is less than the TCP header length.8165 */8166 reported_len = tvb_reported_length(tvb);8167 8168 if (!pinfo->fragmented && !pinfo->flags.in_error_pkt) {8169 if (reported_len < tcph->th_hlen) {8170 proto_tree_add_expert_format(tcp_tree, pinfo, &ei_tcp_short_segment, tvb, offset, 0,8171 "Short segment. Segment/fragment does not contain a full TCP header"8172 " (might be NMAP or someone else deliberately sending unusual packets)");8173 tcph->th_have_seglen = FALSE(0);8174 } else {8175 proto_item *pi;8176 8177 /* Compute the length of data in this segment. */8178 tcph->th_seglen = reported_len - tcph->th_hlen;8179 tcph->th_have_seglen = TRUE(!(0));8180 8181 pi = proto_tree_add_uint(ti, hf_tcp_len, tvb, 0, 0, tcph->th_seglen);8182 proto_item_set_generated(pi);8183 8184 /* initialize base_seq numbers */8185 if(!(pinfo->fd->visited) && tcpd) {8186 /* if this is the first segment for this list we need to store the8187 * base_seq8188 * We use TCP_S_SAW_SYN/SYNACK to distinguish between client and server8189 *8190 * Start relative seq and ack numbers at 1 if this8191 * is not a SYN packet. This makes the relative8192 * seq/ack numbers to be displayed correctly in the8193 * event that the SYN or SYN/ACK packet is not seen8194 * (this solves bug 1542)8195 */8196 if( !(tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET0x01)) {8197 if(tcph->th_flags & TH_SYN0x0002) {8198 tcpd->fwd->base_seq = tcph->th_seq;8199 tcpd->fwd->static_flags |= (tcph->th_flags & TH_ACK0x0010) ? TCP_S_SAW_SYNACK0x05 : TCP_S_SAW_SYN0x03;8200 }8201 else {8202 tcpd->fwd->base_seq = tcph->th_seq-1;8203 }8204 tcpd->fwd->static_flags |= TCP_S_BASE_SEQ_SET0x01;8205 }8206 8207 /* Only store reverse sequence if this isn't the SYN8208 * There's no guarantee that the ACK field of a SYN8209 * contains zeros; get the ISN from the first segment8210 * with the ACK bit set instead (usually the SYN/ACK).8211 *8212 * If the SYN and SYN/ACK were received out-of-order,8213 * the ISN is ack-1. If we missed the SYN/ACK, but got8214 * the last ACK of the 3WHS, the ISN is ack-1. For all8215 * other packets the ISN is unknown, so ack-1 is8216 * as good a guess as ack.8217 */8218 if( !(tcpd->rev->static_flags & TCP_S_BASE_SEQ_SET0x01) && (tcph->th_flags & TH_ACK0x0010) ) {8219 tcpd->rev->base_seq = tcph->th_ack-1;8220 tcpd->rev->static_flags |= TCP_S_BASE_SEQ_SET0x01;8221 }8222 }8223 8224 /* handle TCP seq# analysis parse all new segments we see */8225 if(tcp_analyze_seq) {8226 if(!(pinfo->fd->visited)) {8227 tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd, tcppd);8228 }8229 if(tcpd && tcp_relative_seq) {8230 (tcph->th_seq) -= tcpd->fwd->base_seq;8231 if (tcph->th_flags & TH_ACK0x0010) {8232 (tcph->th_ack) -= tcpd->rev->base_seq;8233 }8234 }8235 }8236 8237 /* re-calculate window size, based on scaling factor */8238 if (!(tcph->th_flags&TH_SYN0x0002)) { /* SYNs are never scaled */8239 if (tcpd && (tcpd->fwd->win_scale>=0)) {8240 (tcph->th_win)<<=tcpd->fwd->win_scale;8241 }8242 else if (tcpd && (tcpd->fwd->win_scale == -1)) {8243 /* i.e. Unknown, but wasn't signalled with no scaling, so use preference setting instead! */8244 if (tcp_default_window_scaling>=0) {8245 (tcph->th_win)<<=tcp_default_window_scaling;8246 }8247 }8248 }8249 8250 /* Compute the sequence number of next octet after this segment. */8251 nxtseq = tcph->th_seq + tcph->th_seglen;8252 }8253 } else8254 tcph->th_have_seglen = FALSE(0);8255 8256 /*8257 * Decode the ECN related flags as ACE if it is not a SYN segment,8258 * and an AccECN-setup SYN and SYN ACK have been observed, or an8259 * AccECN option was observed (this covers the case where Wireshark8260 * did not observe the initial handshake).8261 */8262 tcph->th_use_ace = (tcph->th_flags & TH_SYN0x0002) == 0 &&8263 tcpd != NULL((void*)0) &&8264 ((tcpd->had_acc_ecn_setup_syn && tcpd->had_acc_ecn_setup_syn_ack) ||8265 tcpd->had_acc_ecn_option);8266 flags_str = tcp_flags_to_str(pinfo->pool, tcph);8267 flags_str_first_letter = tcp_flags_to_str_first_letter(pinfo->pool, tcph);8268 8269 col_append_lstr(pinfo->cinfo, COL_INFO,8270 " [", flags_str, "]",8271 COL_ADD_LSTR_TERMINATOR(const char *) -1);8272 tcp_info_append_uint(pinfo, "Seq", tcph->th_seq);8273 if (tcph->th_flags&TH_ACK0x0010)8274 tcp_info_append_uint(pinfo, "Ack", tcph->th_ack);8275 8276 tcp_info_append_uint(pinfo, "Win", tcph->th_win);8277 8278 if (tcp_summary_in_tree) {8279 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);8280 }8281 8282 if (!icmp_ip) {8283 if(tcp_relative_seq && tcp_analyze_seq) {8284 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq, "%u (relative sequence number)", tcph->th_seq);8285 item = proto_tree_add_uint(tcp_tree, hf_tcp_seq_abs, tvb, offset + 4, 4, tcph->th_rawseq);8286 if (read_seq_as_syn_cookie) {8287 proto_item* syncookie_ti = NULL((void*)0);8288 proto_item_append_text(item, " (syn cookie)");8289 syncookie_ti = proto_item_add_subtree(item, ett_tcp_syncookie);8290 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_time, tvb, (offset + 4) * 8, 5, ENC_NA0x00000000);8291 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_mss, tvb, (offset + 4) * 8 + 5, 3, ENC_NA0x00000000);8292 proto_tree_add_item(syncookie_ti, hf_tcp_syncookie_hash, tvb, offset + 4 + 1, 3, ENC_NA0x00000000);8293 }8294 8295 } else {8296 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);8297 hide_seqack_abs_item = proto_tree_add_uint(tcp_tree, hf_tcp_seq_abs, tvb, offset + 4, 4, tcph->th_rawseq);8298 proto_item_set_hidden(hide_seqack_abs_item);8299 }8300 }8301 8302 if (tcph->th_hlen < TCPH_MIN_LEN20) {8303 /* Give up at this point; we put the source and destination port in8304 the tree, before fetching the header length, so that they'll8305 show up if this is in the failing packet in an ICMP error packet,8306 but it's now time to give up if the header length is bogus. */8307 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",8308 tcph->th_hlen, TCPH_MIN_LEN20);8309 if (tree) {8310 tf = proto_tree_add_uint_bits_format_value(tcp_tree, hf_tcp_hdr_len, tvb, (offset + 12) << 3, 4, tcph->th_hlen,8311 ENC_BIG_ENDIAN0x00000000, "%u bytes (%u)", tcph->th_hlen, tcph->th_hlen >> 2);8312 expert_add_info_format(pinfo, tf, &ei_tcp_bogus_header_length,8313 "Bogus TCP header length (%u, must be at least %u)", tcph->th_hlen, TCPH_MIN_LEN20);8314 }8315 return offset+12;8316 }8317 8318 /* Now we certainly have enough information to be willing to send8319 * the header information to the tap. The options can add information8320 * about the SACKs, but the other taps don't really *require* that.8321 * Add a CLEANUP function so that the tap_queue_packet gets called8322 * if any exception is thrown.8323 *8324 * XXX: Could we move this earlier, before the window size and urgent8325 * pointer, for example? Probably, but if so, remember to8326 * CLEANUP_CALL_AND_POP before any return statements, such as the8327 * one above.8328 */8329 8330 tcp_tap_cleanup_t *cleanup = wmem_new(pinfo->pool, tcp_tap_cleanup_t)((tcp_tap_cleanup_t*)wmem_alloc((pinfo->pool), sizeof(tcp_tap_cleanup_t
)))
;8331 cleanup->pinfo = pinfo;8332 cleanup->tcph = tcph;8333 CLEANUP_PUSH(tcp_tap_cleanup, cleanup){ struct except_stacknode except_sn; struct except_cleanup except_cl
; except_setup_clean(&except_sn, &except_cl, (tcp_tap_cleanup
), (cleanup))
;8334 8335 /* initialize or move forward the conversation completeness */8336 if(tcpd) {8337 if(conversation_is_new) { /* pure SYN must be sought in new conversations only */8338 if((tcph->th_flags&(TH_SYN0x0002|TH_ACK0x0010))==TH_SYN0x0002) {8339 conversation_completeness |= TCP_COMPLETENESS_SYNSENT0x01;8340 if(tcph->th_seglen > 0) { /* TCP Fast Open */8341 conversation_completeness |= TCP_COMPLETENESS_DATA0x08;8342 }8343 }8344 }8345 else {8346 /* Explicitly and immediately move forward the conversation last_frame,8347 * although it would one way or another be changed later8348 * in the conversation helper functions.8349 */8350 if (!(pinfo->fd->visited)) {8351 if (pinfo->num > conv->last_frame) {8352 conv->last_frame = pinfo->num;8353 }8354 }8355 8356 conversation_completeness = tcpd->conversation_completeness ;8357 }8358 8359 /* SYN-ACK */8360 if((tcph->th_flags&(TH_SYN0x0002|TH_ACK0x0010))==(TH_SYN0x0002|TH_ACK0x0010)) {8361 conversation_completeness |= TCP_COMPLETENESS_SYNACK0x02;8362 }8363 8364 /* ACKs */8365 if((tcph->th_flags&(TH_SYN0x0002|TH_ACK0x0010))==(TH_ACK0x0010)) {8366 if(tcph->th_seglen>0) { /* transporting some data */8367 conversation_completeness |= TCP_COMPLETENESS_DATA0x08;8368 }8369 else { /* pure ACK */8370 conversation_completeness |= TCP_COMPLETENESS_ACK0x04;8371 }8372 }8373 8374 /* FIN-ACK */8375 if((tcph->th_flags&(TH_FIN0x0001|TH_ACK0x0010))==(TH_FIN0x0001|TH_ACK0x0010)) {8376 conversation_completeness |= TCP_COMPLETENESS_FIN0x10;8377 }8378 8379 /* RST */8380 /* XXX: A RST segment should be validated (RFC 9293 3.5.3),8381 * and if not valid should not change the conversation state.8382 */8383 if(tcph->th_flags&(TH_RST0x0004)) {8384 conversation_completeness |= TCP_COMPLETENESS_RST0x20;8385 }8386 8387 /* Store the completeness at the conversation level,8388 * both as numerical and as Flag First Letters string, to avoid8389 * computing many times the same thing.8390 */8391 if (tcpd->conversation_completeness) {8392 if (tcpd->conversation_completeness != conversation_completeness) {8393 tcpd->conversation_completeness = conversation_completeness;8394 tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ;8395 }8396 }8397 else {8398 tcpd->conversation_completeness = conversation_completeness;8399 tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ;8400 }8401 }8402 8403 if (tcp_summary_in_tree) {8404 if(tcph->th_flags&TH_ACK0x0010) {8405 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);8406 }8407 if (tcph->th_have_seglen)8408 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);8409 }8410 proto_item_set_len(ti, tcph->th_hlen);8411 if (tcph->th_have_seglen) {8412 if(tcp_relative_seq && tcp_analyze_seq) {8413 if (tcph->th_flags&(TH_SYN0x0002|TH_FIN0x0001)) {8414 tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq + 1, "%u (relative sequence number)", nxtseq + 1);8415 } else {8416 tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "%u (relative sequence number)", nxtseq);8417 }8418 } else {8419 if (tcph->th_flags&(TH_SYN0x0002|TH_FIN0x0001)) {8420 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq + 1);8421 } else {8422 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);8423 }8424 }8425 proto_item_set_generated(tf);8426 }8427 8428 tf = proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);8429 hide_seqack_abs_item = proto_tree_add_uint(tcp_tree, hf_tcp_ack_abs, tvb, offset + 8, 4, tcph->th_rawack);8430 if (tcph->th_flags & TH_ACK0x0010) {8431 if (tcp_relative_seq && tcp_analyze_seq) {8432 proto_item_append_text(tf, " (relative ack number)");8433 } else {8434 proto_item_set_hidden(hide_seqack_abs_item);8435 }8436 if ((tcph->th_flags & TH_SYN0x0002) && tcp_analyze_seq) {8437 if ((tcp_relative_seq && tcph->th_ack > 1) ||8438 (!tcp_relative_seq && tcpd && (tcph->th_ack - tcpd->rev->base_seq) > 1)) {8439 expert_add_info(pinfo, tf, &ei_tcp_analysis_tfo_ack);8440 } else if (tcpd && tcpd->tfo_syn_data) {8441 expert_add_info(pinfo, tf, &ei_tcp_analysis_tfo_ignored);8442 }8443 }8444 } else {8445 /* Note if the ACK field is non-zero */8446 if (tvb_get_ntohl(tvb, offset+8) != 0) {8447 expert_add_info(pinfo, tf, &ei_tcp_ack_nonzero);8448 }8449 }8450 8451 if (tree) {8452 // This should be consistent with ip.hdr_len.8453 proto_tree_add_uint_bits_format_value(tcp_tree, hf_tcp_hdr_len, tvb, (offset + 12) << 3, 4, tcph->th_hlen,8454 ENC_BIG_ENDIAN0x00000000, "%u bytes (%u)", tcph->th_hlen, tcph->th_hlen>>2);8455 tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 12, 2,8456 tcph->th_flags, "Flags: 0x%03x (%s)", tcph->th_flags, flags_str);8457 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);8458 proto_tree_add_boolean(field_tree, hf_tcp_flags_res, tvb, offset + 12, 1, tcph->th_flags);8459 if (tcph->th_use_ace) {8460 ace = tcp_get_ace(tcph);8461 proto_tree_add_uint_format(field_tree, hf_tcp_flags_ace, tvb, 12, 2, ace,8462 "...%c %c%c.. .... = ACE: %u",8463 ace & 0x04 ? '1' : '0',8464 ace & 0x02 ? '1' : '0',8465 ace & 0x01 ? '1' : '0',8466 ace);8467 } else {8468 proto_tree_add_boolean(field_tree, hf_tcp_flags_ae, tvb, offset + 12, 1, tcph->th_flags);8469 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);8470 proto_tree_add_boolean(field_tree, hf_tcp_flags_ece, tvb, offset + 13, 1, tcph->th_flags);8471 }8472 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);8473 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);8474 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);8475 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);8476 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);8477 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);8478 8479 tf = proto_tree_add_string(field_tree, hf_tcp_flags_str, tvb, offset + 12, 2, flags_str_first_letter);8480 proto_item_set_generated(tf);8481 /* As discussed in bug 5541, it is better to use two separate8482 * fields for the real and calculated window size.8483 */8484 proto_tree_add_uint(tcp_tree, hf_tcp_window_size_value, tvb, offset + 14, 2, real_window);8485 scaled_pi = proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win);8486 proto_item_set_generated(scaled_pi);8487 8488 if( !(tcph->th_flags&TH_SYN0x0002) && tcpd ) {8489 switch (tcpd->fwd->win_scale) {8490 8491 case -1:8492 /* Unknown */8493 {8494 gint16 win_scale = tcpd->fwd->win_scale;8495 gboolean override_with_pref = FALSE(0);8496 8497 /* Use preference setting (if set) */8498 if (tcp_default_window_scaling != WindowScaling_NotKnown) {8499 win_scale = (1 << tcp_default_window_scaling);8500 override_with_pref = TRUE(!(0));8501 }8502 8503 scaled_pi = proto_tree_add_int_format_value(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2,8504 win_scale, "%d (%s)",8505 win_scale,8506 (override_with_pref) ? "missing - taken from preference" : "unknown");8507 proto_item_set_generated(scaled_pi);8508 }8509 break;8510 8511 case -2:8512 /* No window scaling used */8513 scaled_pi = proto_tree_add_int_format_value(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2, tcpd->fwd->win_scale, "%d (no window scaling used)", tcpd->fwd->win_scale);8514 proto_item_set_generated(scaled_pi);8515 break;8516 8517 default:8518 /* Scaling from signalled value */8519 scaled_pi = proto_tree_add_int_format_value(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2, 1<<tcpd->fwd->win_scale, "%d", 1<<tcpd->fwd->win_scale);8520 proto_item_set_generated(scaled_pi);8521 }8522 }8523 }8524 8525 if(tcph->th_flags & TH_SYN0x0002) {8526 if(tcph->th_flags & TH_ACK0x0010) {8527 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_synack,8528 "Connection establish acknowledge (SYN+ACK): server port %u", tcph->th_sport);8529 /* Save the server port to help determine dissector used */8530 tcpd->server_port = tcph->th_sport;8531 }8532 else {8533 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_syn,8534 "Connection establish request (SYN): server port %u", tcph->th_dport);8535 /* Save the server port to help determine dissector used */8536 tcpd->server_port = tcph->th_dport;8537 tcpd->ts_mru_syn = pinfo->abs_ts;8538 }8539 /* Remember where the next segment will start. */8540 if (tcp_desegment && tcp_reassemble_out_of_order && tcpd && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {8541 if (tcpd->fwd->maxnextseq == 0) {8542 tcpd->fwd->maxnextseq = tcph->th_seq + 1;8543 }8544 }8545 /* Initialize the is_first_ack */8546 tcpd->fwd->is_first_ack = TRUE(!(0));8547 }8548 if(tcph->th_flags & TH_FIN0x0001) {8549 /* XXX - find a way to know the server port and output only that one */8550 expert_add_info(pinfo, tf_fin, &ei_tcp_connection_fin);8551 8552 /* Track closing initiator.8553 If it was not already closed by the reverse flow, it means we are the first */8554 if(!tcpd->rev->closing_initiator) {8555 tcpd->fwd->closing_initiator = TRUE(!(0));8556 expert_add_info(pinfo, tf, &ei_tcp_connection_fin_active);8557 } else {8558 expert_add_info(pinfo, tf, &ei_tcp_connection_fin_passive);8559 }8560 }8561 if(tcph->th_flags & TH_RST0x0004)8562 /* XXX - find a way to know the server port and output only that one */8563 expert_add_info(pinfo, tf_rst, &ei_tcp_connection_rst);8564 8565 if(tcp_analyze_seq8566 && (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == TH_ACK0x00108567 && !nstime_is_zero(&tcpd->ts_mru_syn)8568 && nstime_is_zero(&tcpd->ts_first_rtt)) {8569 /* If all of the following:8570 * - we care (the pref is set)8571 * - this is a pure ACK8572 * - we have a timestamp for the most-recently-transmitted SYN8573 * - we haven't seen a pure ACK yet (no ts_first_rtt stored)8574 * then assume it's the last part of the handshake and store the initial8575 * RTT time8576 */8577 nstime_delta(&(tcpd->ts_first_rtt), &(pinfo->abs_ts), &(tcpd->ts_mru_syn));8578 }8579 8580 /*8581 * Remember if we have already seen at least one ACK,8582 * then we can neutralize the Window Scale side-effect at the beginning (issue 14690)8583 */8584 if(tcp_analyze_seq8585 && (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == TH_ACK0x0010) {8586 if(tcpd->fwd->is_first_ack) {8587 tcpd->fwd->is_first_ack = FALSE(0);8588 }8589 }8590 8591 /* Supply the sequence number of the first byte and of the first byte8592 after the segment. */8593 tcpinfo.seq = tcph->th_seq;8594 tcpinfo.nxtseq = nxtseq;8595 tcpinfo.lastackseq = tcph->th_ack;8596 8597 /* Assume we'll pass un-reassembled data to subdissectors. */8598 tcpinfo.is_reassembled = FALSE(0);8599 8600 /*8601 * Assume, initially, that we can't desegment.8602 */8603 pinfo->can_desegment = 0;8604 th_sum = tvb_get_ntohs(tvb, offset + 16);8605 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {8606 /* The packet isn't part of an un-reassembled fragmented datagram8607 and isn't truncated. This means we have all the data, and thus8608 can checksum it and, unless it's being returned in an error8609 packet, are willing to allow subdissectors to request reassembly8610 on it. */8611 8612 if (tcp_check_checksum) {8613 /* We haven't turned checksum checking off; checksum it. */8614 8615 /* Set up the fields of the pseudo-header. */8616 SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len)do { cksum_vec[0].ptr = ((const guint8 *)pinfo->src.data);
cksum_vec[0].len = (pinfo->src.len); } while (0)
;8617 SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data, pinfo->dst.len)do { cksum_vec[1].ptr = ((const guint8 *)pinfo->dst.data);
cksum_vec[1].len = (pinfo->dst.len); } while (0)
;8618 switch (pinfo->src.type) {8619 8620 case AT_IPv4:8621 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len)(((((guint32) ( (((guint32) ((6<<16) + reported_len) &
(guint32) 0x000000ffU) << 24) | (((guint32) ((6<<
16) + reported_len) & (guint32) 0x0000ff00U) << 8) |
(((guint32) ((6<<16) + reported_len) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) ((6<<16) + reported_len) &
(guint32) 0xff000000U) >> 24))))))
;8622 SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 4)do { cksum_vec[2].ptr = ((const guint8 *)phdr); cksum_vec[2].
len = (4); } while (0)
;8623 break;8624 8625 case AT_IPv6:8626 phdr[0] = g_htonl(reported_len)(((((guint32) ( (((guint32) (reported_len) & (guint32) 0x000000ffU
) << 24) | (((guint32) (reported_len) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (reported_len) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (reported_len) & (guint32) 0xff000000U
) >> 24))))))
;8627 phdr[1] = g_htonl(IP_PROTO_TCP)(((((guint32) ( (((guint32) (6) & (guint32) 0x000000ffU) <<
24) | (((guint32) (6) & (guint32) 0x0000ff00U) << 8
) | (((guint32) (6) & (guint32) 0x00ff0000U) >> 8) |
(((guint32) (6) & (guint32) 0xff000000U) >> 24))))
))
;8628 SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 8)do { cksum_vec[2].ptr = ((const guint8 *)phdr); cksum_vec[2].
len = (8); } while (0)
;8629 break;8630 8631 default:8632 /* TCP runs only atop IPv4 and IPv6.... */8633 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/dissectors/packet-tcp.c", 8633))
;8634 break;8635 }8636 /* See discussion in packet-udp.c of partial checksums used in8637 * checksum offloading in Linux and Windows (and possibly others.)8638 */8639 uint16_t partial_cksum;8640 SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, offset, reported_len)do { cksum_vec[3].len = (reported_len); cksum_vec[3].ptr = tvb_get_ptr
((tvb), (offset), cksum_vec[3].len); } while (0)
;8641 computed_cksum = in_cksum_ret_partial(cksum_vec, 4, &partial_cksum);8642 if (computed_cksum == 0 && th_sum == 0xffff) {8643 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,8644 offset + 16, 2, th_sum,8645 "0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);8646 8647 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);8648 item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_calculated, tvb,8649 offset + 16, 2, 0x0000);8650 proto_item_set_generated(item);8651 /* XXX - What should this special status be? */8652 item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_status, tvb,8653 offset + 16, 0, PROTO_CHECKSUM_E_BAD);8654 proto_item_set_generated(item);8655 expert_add_info(pinfo, item, &ei_tcp_checksum_ffff);8656 8657 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");8658 8659 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */8660 desegment_ok = TRUE(!(0));8661 } else {8662 proto_item* calc_item;8663 uint16_t shouldbe_cksum = in_cksum_shouldbe(th_sum, computed_cksum);8664 if (computed_cksum != 0 && th_sum == g_htons(partial_cksum)(((((guint16) ( (guint16) ((guint16) (partial_cksum) >>
8) | (guint16) ((guint16) (partial_cksum) << 8))))))
) {8665 /* Don't use PROTO_CHECKSUM_IN_CKSUM because we expect the value8666 * to match what we pass in. */8667 item = proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, g_htons(partial_cksum)(((((guint16) ( (guint16) ((guint16) (partial_cksum) >>
8) | (guint16) ((guint16) (partial_cksum) << 8))))))
,8668 ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_VERIFY0x01);8669 proto_item_append_text(item, " (matches partial checksum, not 0x%04x, likely caused by \"TCP checksum offload\")", shouldbe_cksum);8670 expert_add_info(pinfo, item, &ei_tcp_checksum_partial);8671 computed_cksum = 0;8672 /* XXX Add a new status, e.g. PROTO_CHECKSUM_E_PARTIAL? */8673 } else {8674 item = proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, computed_cksum,8675 ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_VERIFY0x01|PROTO_CHECKSUM_IN_CKSUM0x04);8676 }8677 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);8678 calc_item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_calculated, tvb,8679 offset + 16, 2, shouldbe_cksum);8680 proto_item_set_generated(calc_item);8681 8682 /* Checksum is valid, so we're willing to desegment it. */8683 if (computed_cksum == 0) {8684 desegment_ok = TRUE(!(0));8685 } else {8686 proto_item_append_text(item, "(maybe caused by \"TCP checksum offload\"?)");8687 8688 /* Checksum is invalid, so we're not willing to desegment it. */8689 desegment_ok = FALSE(0);8690 pinfo->noreassembly_reason = " [incorrect TCP checksum]";8691 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");8692 }8693 }8694 } else {8695 proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, 0,8696 ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00);8697 8698 /* We didn't check the checksum, and don't care if it's valid,8699 so we're willing to desegment it. */8700 desegment_ok = TRUE(!(0));8701 }8702 } else {8703 /* We don't have all the packet data, so we can't checksum it... */8704 proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, 0,8705 ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00);8706 8707 /* ...and aren't willing to desegment it. */8708 desegment_ok = FALSE(0);8709 }8710 8711 if (desegment_ok) {8712 /* We're willing to desegment this. Is desegmentation enabled? */8713 if (tcp_desegment) {8714 /* Yes - is this segment being returned in an error packet? */8715 if (!pinfo->flags.in_error_pkt) {8716 /* No - indicate that we will desegment.8717 We do NOT want to desegment segments returned in error8718 packets, as they're not part of a TCP connection. */8719 pinfo->can_desegment = 2;8720 }8721 }8722 }8723 8724 item = proto_tree_add_item_ret_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, ENC_BIG_ENDIAN0x00000000, &th_urp);8725 8726 if (IS_TH_URG(tcph->th_flags)(tcph->th_flags & 0x0020)) {8727 /* Export the urgent pointer, for the benefit of protocols such as8728 rlogin. */8729 tcpinfo.urgent_pointer = (guint16)th_urp;8730 tcp_info_append_uint(pinfo, "Urg", th_urp);8731 } else {8732 if (th_urp) {8733 /* Note if the urgent pointer field is non-zero */8734 expert_add_info(pinfo, item, &ei_tcp_urgent_pointer_non_zero);8735 }8736 }8737 8738 if (tcph->th_have_seglen)8739 tcp_info_append_uint(pinfo, "Len", tcph->th_seglen);8740 8741 /* If there's more than just the fixed-length header (20 bytes), create8742 a protocol tree item for the options. (We already know there's8743 not less than the fixed-length header - we checked that above.)8744 8745 We ensure that we don't throw an exception here, so that we can8746 do some analysis before we dissect the options and possibly8747 throw an exception. (Trying to avoid throwing an exception when8748 dissecting options is not something we should do.) */8749 optlen = tcph->th_hlen - TCPH_MIN_LEN20; /* length of options, in bytes */8750 options_item = NULL((void*)0);8751 options_tree = NULL((void*)0);8752 if (optlen != 0) {8753 guint bc = (guint)tvb_captured_length_remaining(tvb, offset + 20);8754 8755 if (tcp_tree != NULL((void*)0)) {8756 options_item = proto_tree_add_item(tcp_tree, hf_tcp_options, tvb, offset + 20,8757 bc < optlen ? bc : optlen, ENC_NA0x00000000);8758 proto_item_set_text(options_item, "Options: (%u bytes)", optlen);8759 options_tree = proto_item_add_subtree(options_item, ett_tcp_options);8760 }8761 }8762 8763 tcph->num_sack_ranges = 0;8764 8765 /* handle conversation timestamps */8766 if(tcp_calculate_ts) {8767 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);8768 }8769 8770 /* Now dissect the options. */8771 if (optlen) {8772 rvbd_option_data* option_data;8773 8774 tcp_dissect_options(tvb, offset + 20, optlen,8775 pinfo, options_tree,8776 options_item, tcph);8777 8778 /* Do some post evaluation of some Riverbed probe options in the list */8779 option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);8780 if (option_data != NULL((void*)0))8781 {8782 if (option_data->valid)8783 {8784 /* Distinguish S+ from S+* */8785 col_prepend_fstr(pinfo->cinfo, COL_INFO, "S%s, ",8786 option_data->type == PROBE_TRACE ? "#" :8787 (option_data->probe_flags & RVBD_FLAGS_PROBE_NCFE0x04) ? "+*" : "+");8788 }8789 }8790 8791 }8792 8793 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/8794 if(tcp_analyze_seq) {8795 guint32 use_seq = tcph->th_seq;8796 guint32 use_ack = tcph->th_ack;8797 /* May need to recover absolute values here... */8798 if (tcp_relative_seq) {8799 use_seq += tcpd->fwd->base_seq;8800 if (tcph->th_flags & TH_ACK0x0010) {8801 use_ack += tcpd->rev->base_seq;8802 }8803 }8804 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd, use_seq, use_ack);8805 }8806 8807 if(!pinfo->fd->visited) {8808 if((tcph->th_flags & TH_SYN0x0002)==TH_SYN0x0002) {8809 /* Check the validity of the window scale value8810 */8811 verify_tcp_window_scaling((tcph->th_flags&TH_ACK0x0010)==TH_ACK0x0010,tcpd);8812 }8813 8814 if((tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010))==(TH_SYN0x0002|TH_ACK0x0010)) {8815 /* If the SYN or the SYN+ACK offered SCPS capabilities,8816 * validate the flow's bidirectional scps capabilities.8817 * The or protects against broken implementations offering8818 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN8819 */8820 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {8821 verify_scps(pinfo, tf_syn, tcpd);8822 }8823 8824 }8825 }8826 8827 if (tcph->th_mptcp) {8828 8829 if (tcp_analyze_mptcp) {8830 mptcp_add_analysis_subtree(pinfo, tvb, tcp_tree, tcpd, tcpd->mptcp_analysis, tcph );8831 }8832 }8833 8834 /* Skip over header + options */8835 offset += tcph->th_hlen;8836 8837 /* Check the packet length to see if there's more data8838 (it could be an ACK-only packet) */8839 captured_length_remaining = tvb_captured_length_remaining(tvb, offset);8840 8841 if (tcph->th_have_seglen) {8842 if(have_tap_listener(tcp_follow_tap)) {8843 tcp_follow_tap_data_t* follow_data = wmem_new0(pinfo->pool, tcp_follow_tap_data_t)((tcp_follow_tap_data_t*)wmem_alloc0((pinfo->pool), sizeof
(tcp_follow_tap_data_t)))
;8844 8845 follow_data->tvb = tvb_new_subset_remaining(tvb, offset);8846 follow_data->tcph = tcph;8847 follow_data->tcpd = tcpd;8848 8849 tap_queue_packet(tcp_follow_tap, pinfo, follow_data);8850 }8851 }8852 8853 /* Nothing more to add to tcph, go ahead and send to the taps. */8854 CLEANUP_CALL_AND_POPexcept_pop(); if (1) except_cl.except_func(except_cl.except_context
); }
;8855 8856 /* if it is an MPTCP packet */8857 if(tcpd->mptcp_analysis) {8858 tap_queue_packet(mptcp_tap, pinfo, tcpd);8859 }8860 8861 /* If we're reassembling something whose length isn't known8862 * beforehand, and that runs all the way to the end of8863 * the data stream, a FIN indicates the end of the data8864 * stream and thus the completion of reassembly, so we8865 * need to explicitly check for that here.8866 */8867 if(tcph->th_have_seglen && tcpd && (tcph->th_flags & TH_FIN0x0001)8868 && pinfo->can_desegment8869 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001) ) {8870 struct tcp_multisegment_pdu *msp;8871 8872 /* Is this the FIN that ended the data stream or is it a8873 * retransmission of that FIN?8874 */8875 if (tcpd->fwd->fin == 0 || tcpd->fwd->fin == pinfo->num) {8876 /* Either we haven't seen a FIN for this flow or we8877 * have and it's this frame. Note that this is the FIN8878 * for this flow, terminate reassembly and dissect the8879 * results. */8880 tcpd->fwd->fin = pinfo->num;8881 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq);8882 if(msp) {8883 fragment_head *ipfd_head;8884 8885 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,8886 pinfo, msp->first_frame, msp,8887 tcph->th_seq - msp->seq,8888 tcph->th_seglen,8889 FALSE(0) );8890 if(ipfd_head && ipfd_head->reassembled_in == pinfo->num && ipfd_head->reas_in_layer_num == pinfo->curr_layer_num) {8891 tvbuff_t *next_tvb;8892 8893 /* create a new TVB structure for desegmented data8894 * datalen-1 to strip the dummy FIN byte off8895 */8896 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);8897 8898 /* add desegmented data to the data source list */8899 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");8900 8901 /* Show details of the reassembly */8902 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);8903 8904 /* call the payload dissector8905 * but make sure we don't offer desegmentation any more8906 */8907 pinfo->can_desegment = 0;8908 8909 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq,8910 nxtseq, FALSE(0), tcpd, &tcpinfo);8911 8912 return tvb_captured_length(tvb);8913 }8914 }8915 } else {8916 /* Yes. This is a retransmission of the final FIN (or it's8917 * the final FIN transmitted via a different path).8918 * XXX - we need to flag retransmissions a bit better.8919 */8920 proto_tree_add_uint(tcp_tree, hf_tcp_fin_retransmission, tvb, 0, 0, tcpd->fwd->fin);8921 }8922 }8923 8924 if (tcp_display_process_info && tcpd && ((tcpd->fwd && tcpd->fwd->process_info && tcpd->fwd->process_info->command) ||8925 (tcpd->rev && tcpd->rev->process_info && tcpd->rev->process_info->command))) {8926 field_tree = proto_tree_add_subtree(tcp_tree, tvb, offset, 0, ett_tcp_process_info, &ti, "Process Information");8927 proto_item_set_generated(ti);8928 if (tcpd->fwd && tcpd->fwd->process_info && tcpd->fwd->process_info->command) {8929 proto_tree_add_uint(field_tree, hf_tcp_proc_dst_uid, tvb, 0, 0, tcpd->fwd->process_info->process_uid);8930 proto_tree_add_uint(field_tree, hf_tcp_proc_dst_pid, tvb, 0, 0, tcpd->fwd->process_info->process_pid);8931 proto_tree_add_string(field_tree, hf_tcp_proc_dst_uname, tvb, 0, 0, tcpd->fwd->process_info->username);8932 proto_tree_add_string(field_tree, hf_tcp_proc_dst_cmd, tvb, 0, 0, tcpd->fwd->process_info->command);8933 }8934 if (tcpd->rev && tcpd->rev->process_info && tcpd->rev->process_info->command) {8935 proto_tree_add_uint(field_tree, hf_tcp_proc_src_uid, tvb, 0, 0, tcpd->rev->process_info->process_uid);8936 proto_tree_add_uint(field_tree, hf_tcp_proc_src_pid, tvb, 0, 0, tcpd->rev->process_info->process_pid);8937 proto_tree_add_string(field_tree, hf_tcp_proc_src_uname, tvb, 0, 0, tcpd->rev->process_info->username);8938 proto_tree_add_string(field_tree, hf_tcp_proc_src_cmd, tvb, 0, 0, tcpd->rev->process_info->command);8939 }8940 }8941 8942 /*8943 * XXX - what, if any, of this should we do if this is included in an8944 * error packet? It might be nice to see the details of the packet8945 * that caused the ICMP error, but it might not be nice to have the8946 * dissector update state based on it.8947 * Also, we probably don't want to run TCP taps on those packets.8948 */8949 if (captured_length_remaining != 0) {8950 if (tcph->th_flags & TH_RST0x0004) {8951 /*8952 * RFC1122 says:8953 *8954 * 4.2.2.12 RST Segment: RFC-793 Section 3.48955 *8956 * A TCP SHOULD allow a received RST segment to include data.8957 *8958 * DISCUSSION8959 * It has been suggested that a RST segment could contain8960 * ASCII text that encoded and explained the cause of the8961 * RST. No standard has yet been established for such8962 * data.8963 *8964 * so for segments with RST we just display the data as text.8965 */8966 proto_tree_add_item(tcp_tree, hf_tcp_reset_cause, tvb, offset, captured_length_remaining, ENC_NA0x00000000|ENC_ASCII0x00000000);8967 } else {8968 /* When we have a frame with TCP SYN bit set and segmented TCP payload we need8969 * to increment seq and nxtseq to detect the overlapping byte(s). This is to fix Bug 9882.8970 */8971 if(tcph->th_flags & TH_SYN0x0002) {8972 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq + 1, nxtseq + 1,8973 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo);8974 } else {8975 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,8976 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo);8977 }8978 }8979 }8980 return tvb_captured_length(tvb);8981}8982 8983static void8984tcp_init(void)8985{8986 tcp_stream_count = 0;8987 8988 /* MPTCP init */8989 mptcp_stream_count = 0;8990 mptcp_tokens = wmem_tree_new(wmem_file_scope());8991}8992 8993void8994proto_register_tcp(void)8995{8996 static hf_register_info hf[] = {8997 8998 { &hf_tcp_srcport,8999 { "Source Port", "tcp.srcport", FT_UINT16, BASE_PT_TCP, NULL((void*)0), 0x0,9000 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9001 9002 { &hf_tcp_dstport,9003 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_PT_TCP, NULL((void*)0), 0x0,9004 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9005 9006 { &hf_tcp_port,9007 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_PT_TCP, NULL((void*)0), 0x0,9008 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9009 9010 { &hf_tcp_stream,9011 { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9012 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9013 9014 { &hf_tcp_stream_pnum,9015 { "Stream Packet Number", "tcp.stream.pnum", FT_UINT32, BASE_DEC,9016 NULL((void*)0), 0x0,9017 "Relative packet number in this TCP stream", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9018 9019 { &hf_tcp_completeness,9020 { "Conversation completeness", "tcp.completeness", FT_UINT8,9021 BASE_CUSTOM, CF_FUNC(conversation_completeness_fill)((const void *) (gsize) (conversation_completeness_fill)), 0x0,9022 "The completeness of the conversation capture", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9023 9024 { &hf_tcp_completeness_syn,9025 { "SYN", "tcp.completeness.syn", FT_BOOLEAN, 8,9026 TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent
))))
, TCP_COMPLETENESS_SYNSENT0x01,9027 "Conversation has a SYN packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9028 9029 { &hf_tcp_completeness_syn_ack,9030 { "SYN-ACK", "tcp.completeness.syn-ack", FT_BOOLEAN, 8,9031 TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent
))))
, TCP_COMPLETENESS_SYNACK0x02,9032 "Conversation has a SYN-ACK packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9033 9034 { &hf_tcp_completeness_ack,9035 { "ACK", "tcp.completeness.ack", FT_BOOLEAN, 8,9036 TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent
))))
, TCP_COMPLETENESS_ACK0x04,9037 "Conversation has an ACK packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9038 9039 { &hf_tcp_completeness_data,9040 { "Data", "tcp.completeness.data", FT_BOOLEAN, 8,9041 TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent
))))
, TCP_COMPLETENESS_DATA0x08,9042 "Conversation has payload DATA", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9043 9044 { &hf_tcp_completeness_fin,9045 { "FIN", "tcp.completeness.fin", FT_BOOLEAN, 8,9046 TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent
))))
, TCP_COMPLETENESS_FIN0x10,9047 "Conversation has a FIN packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9048 9049 { &hf_tcp_completeness_rst,9050 { "RST", "tcp.completeness.rst", FT_BOOLEAN, 8,9051 TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent
))))
, TCP_COMPLETENESS_RST0x20,9052 "Conversation has a RST packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9053 9054 { &hf_tcp_completeness_str,9055 { "Completeness Flags", "tcp.completeness.str", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,9056 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9057 9058 { &hf_tcp_seq,9059 { "Sequence Number", "tcp.seq", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9060 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9061 9062 { &hf_tcp_seq_abs,9063 { "Sequence Number (raw)", "tcp.seq_raw", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9064 "This shows the raw value of the sequence number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9065 9066 { &hf_tcp_nxtseq,9067 { "Next Sequence Number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9068 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9069 9070 { &hf_tcp_ack,9071 { "Acknowledgment Number", "tcp.ack", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9072 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9073 9074 { &hf_tcp_ack_abs,9075 { "Acknowledgment number (raw)", "tcp.ack_raw", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9076 "This shows the raw value of the acknowledgment number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },9077 9078 // "Data Offset" in https://tools.ietf.org/html/rfc793#section-3.1 and9079 // "Data offset" in https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure9080 { &hf_tcp_hdr_len,9081 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,9082 "Data offset in 32-bit words", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9083 9084 { &hf_tcp_flags,9085 { "Flags", "tcp.flags", FT_UINT16, BASE_HEX, NULL((void*)0), TH_MASK0x0FFF,9086 "Flags (12 bits)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9087 9088 { &hf_tcp_flags_res,9089 { "Reserved", "tcp.flags.res", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_RES0x0E00,9090 "Three reserved bits (must be zero)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9091 9092 { &hf_tcp_flags_ae,9093 { "Accurate ECN", "tcp.flags.ae", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_AE0x0100,9094 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9095 9096 { &hf_tcp_flags_cwr,9097 { "Congestion Window Reduced", "tcp.flags.cwr", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_CWR0x0080,9098 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9099 9100 { &hf_tcp_flags_ece,9101 { "ECN-Echo", "tcp.flags.ece", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_ECE0x0040,9102 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9103 9104 { &hf_tcp_flags_ace,9105 { "ACE", "tcp.flags.ace", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,9106 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9107 9108 { &hf_tcp_flags_urg,9109 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_URG0x0020,9110 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9111 9112 { &hf_tcp_flags_ack,9113 { "Acknowledgment", "tcp.flags.ack", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_ACK0x0010,9114 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9115 9116 { &hf_tcp_flags_push,9117 { "Push", "tcp.flags.push", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_PUSH0x0008,9118 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9119 9120 { &hf_tcp_flags_reset,9121 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_RST0x0004,9122 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9123 9124 { &hf_tcp_flags_syn,9125 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_SYN0x0002,9126 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9127 9128 { &hf_tcp_flags_fin,9129 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, TH_FIN0x0001,9130 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9131 9132 { &hf_tcp_flags_str,9133 { "TCP Flags", "tcp.flags.str", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,9134 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9135 9136 { &hf_tcp_window_size_value,9137 { "Window", "tcp.window_size_value", FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,9138 "The window size value from the TCP header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9139 9140 /* 32 bits so we can present some values adjusted to window scaling */9141 { &hf_tcp_window_size,9142 { "Calculated window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9143 "The scaled window size (if scaling has been used)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9144 9145 { &hf_tcp_window_size_scalefactor,9146 { "Window size scaling factor", "tcp.window_size_scalefactor", FT_INT32, BASE_DEC, NULL((void*)0), 0x0,9147 "The window size scaling factor (-1 when unknown, -2 when no scaling is used)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9148 9149 { &hf_tcp_checksum,9150 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0,9151 "Details at: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9152 9153 { &hf_tcp_checksum_status,9154 { "Checksum Status", "tcp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals)((0 ? (const struct _value_string*)0 : ((proto_checksum_vals)
)))
, 0x0,9155 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9156 9157 { &hf_tcp_checksum_calculated,9158 { "Calculated Checksum", "tcp.checksum_calculated", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0,9159 "The expected TCP checksum field as calculated from the TCP segment", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9160 9161 { &hf_tcp_analysis,9162 { "SEQ/ACK analysis", "tcp.analysis", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,9163 "This frame has some of the TCP analysis shown", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9164 9165 { &hf_tcp_analysis_flags,9166 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,9167 "This frame has some of the TCP analysis flags set", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9168 9169 { &hf_tcp_analysis_duplicate_ack,9170 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,9171 "This is a duplicate ACK", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9172 9173 { &hf_tcp_analysis_duplicate_ack_num,9174 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9175 "This is duplicate ACK number #", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9176 9177 { &hf_tcp_analysis_duplicate_ack_frame,9178 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_DUP_ACK)((gpointer) (glong) (FT_FRAMENUM_DUP_ACK)), 0x0,9179 "This is a duplicate to the ACK in frame #", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9180 9181 { &hf_tcp_continuation_to,9182 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,9183 "This is a continuation to the PDU in frame #", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9184 9185 { &hf_tcp_len,9186 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9187 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9188 9189 { &hf_tcp_analysis_acks_frame,9190 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK)((gpointer) (glong) (FT_FRAMENUM_ACK)), 0x0,9191 "Which previous segment is this an ACK for", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9192 9193 { &hf_tcp_analysis_bytes_in_flight,9194 { "Bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9195 "How many bytes are now in flight for this connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9196 9197 { &hf_tcp_analysis_push_bytes_sent,9198 { "Bytes sent since last PSH flag", "tcp.analysis.push_bytes_sent", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9199 "How many bytes have been sent since the last PSH flag", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9200 9201 { &hf_tcp_analysis_ack_rtt,9202 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,9203 "How long time it took to ACK the segment (RTT)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9204 9205 { &hf_tcp_analysis_first_rtt,9206 { "iRTT", "tcp.analysis.initial_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,9207 "How long it took for the SYN to ACK handshake (iRTT)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9208 9209 { &hf_tcp_analysis_rto,9210 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,9211 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9212 9213 { &hf_tcp_analysis_rto_frame,9214 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,9215 "This is the frame we measure the RTO from", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9216 9217 { &hf_tcp_urgent_pointer,9218 { "Urgent Pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,9219 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9220 9221 { &hf_tcp_segment_overlap,9222 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,9223 "Segment overlaps with other segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9224 9225 { &hf_tcp_segment_overlap_conflict,9226 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,9227 "Overlapping segments contained conflicting data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9228 9229 { &hf_tcp_segment_multiple_tails,9230 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,9231 "Several tails were found when reassembling the pdu", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9232 9233 { &hf_tcp_segment_too_long_fragment,9234 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,9235 "Segment contained data past end of the pdu", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9236 9237 { &hf_tcp_segment_error,9238 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,9239 "Reassembling error due to illegal segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9240 9241 { &hf_tcp_segment_count,9242 { "Segment count", "tcp.segment.count", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9243 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9244 9245 { &hf_tcp_segment,9246 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,9247 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9248 9249 { &hf_tcp_segments,9250 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,9251 "TCP Segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9252 9253 { &hf_tcp_reassembled_in,9254 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,9255 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9256 9257 { &hf_tcp_reassembled_length,9258 { "Reassembled TCP length", "tcp.reassembled.length", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9259 "The total length of the reassembled payload", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9260 9261 { &hf_tcp_reassembled_data,9262 { "Reassembled TCP Data", "tcp.reassembled.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,9263 "The reassembled payload", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9264 9265 { &hf_tcp_option_kind,9266 { "Kind", "tcp.option_kind", FT_UINT8,9267 BASE_DEC|BASE_EXT_STRING0x00000200, &tcp_option_kind_vs_ext, 0x0, "This TCP option's kind", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9268 9269 { &hf_tcp_option_len,9270 { "Length", "tcp.option_len", FT_UINT8,9271 BASE_DEC, NULL((void*)0), 0x0, "Length of this TCP option in bytes (including kind and length fields)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9272 9273 { &hf_tcp_options,9274 { "TCP Options", "tcp.options", FT_BYTES,9275 BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9276 9277 { &hf_tcp_option_mss_val,9278 { "MSS Value", "tcp.options.mss_val", FT_UINT16,9279 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9280 9281 { &hf_tcp_option_wscale_shift,9282 { "Shift count", "tcp.options.wscale.shift", FT_UINT8,9283 BASE_DEC, NULL((void*)0), 0x0, "Logarithmically encoded power of 2 scale factor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9284 9285 { &hf_tcp_option_wscale_multiplier,9286 { "Multiplier", "tcp.options.wscale.multiplier", FT_UINT16,9287 BASE_DEC, NULL((void*)0), 0x0, "Multiply segment window size by this for scaled window size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9288 9289 { &hf_tcp_option_exp_data,9290 { "Data", "tcp.options.experimental.data", FT_BYTES,9291 BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9292 9293 { &hf_tcp_option_exp_exid,9294 { "Experiment Identifier", "tcp.options.experimental.exid", FT_UINT16,9295 BASE_HEX, &tcp_exid_vs, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9296 9297 { &hf_tcp_option_unknown_payload,9298 { "Payload", "tcp.options.unknown.payload", FT_BYTES,9299 BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9300 9301 { &hf_tcp_option_sack_sle,9302 {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32,9303 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9304 9305 { &hf_tcp_option_sack_sre,9306 {"TCP SACK Right Edge", "tcp.options.sack_re", FT_UINT32,9307 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9308 9309 { &hf_tcp_option_sack_range_count,9310 { "TCP SACK Count", "tcp.options.sack.count", FT_UINT8,9311 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9312 9313 { &hf_tcp_option_sack_dsack_le,9314 {"TCP D-SACK Left Edge", "tcp.options.sack.dsack_le", FT_UINT32,9315 BASE_DEC, NULL((void*)0), 0x0, "Duplicate SACK Left Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9316 9317 { &hf_tcp_option_sack_dsack_re,9318 {"TCP D-SACK Right Edge", "tcp.options.sack.dsack_re", FT_UINT32,9319 BASE_DEC, NULL((void*)0), 0x0, "Duplicate SACK Right Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9320 9321 { &hf_tcp_option_echo,9322 { "TCP Echo Option", "tcp.options.echo_value", FT_UINT32,9323 BASE_DEC, NULL((void*)0), 0x0, "TCP Sack Echo", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9324 9325 { &hf_tcp_option_timestamp_tsval,9326 { "Timestamp value", "tcp.options.timestamp.tsval", FT_UINT32,9327 BASE_DEC, NULL((void*)0), 0x0, "Value of sending machine's timestamp clock", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9328 9329 { &hf_tcp_option_timestamp_tsecr,9330 { "Timestamp echo reply", "tcp.options.timestamp.tsecr", FT_UINT32,9331 BASE_DEC, NULL((void*)0), 0x0, "Echoed timestamp from remote machine", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9332 9333 { &hf_tcp_option_mptcp_subtype,9334 { "Multipath TCP subtype", "tcp.options.mptcp.subtype", FT_UINT8,9335 BASE_DEC, VALS(mptcp_subtype_vs)((0 ? (const struct _value_string*)0 : ((mptcp_subtype_vs)))), 0xF0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9336 9337 { &hf_tcp_option_mptcp_version,9338 { "Multipath TCP version", "tcp.options.mptcp.version", FT_UINT8,9339 BASE_DEC, NULL((void*)0), 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9340 9341 { &hf_tcp_option_mptcp_reserved,9342 { "Reserved", "tcp.options.mptcp.reserved", FT_UINT16,9343 BASE_HEX, NULL((void*)0), 0x0FFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9344 9345 { &hf_tcp_option_mptcp_flags,9346 { "Multipath TCP flags", "tcp.options.mptcp.flags", FT_UINT8,9347 BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9348 9349 { &hf_tcp_option_mptcp_backup_flag,9350 { "Backup flag", "tcp.options.mptcp.backup.flag", FT_UINT8,9351 BASE_DEC, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9352 9353 { &hf_tcp_option_mptcp_checksum_flag,9354 { "Checksum required", "tcp.options.mptcp.checksumreq.flags", FT_UINT8,9355 BASE_DEC, NULL((void*)0), MPTCP_CHECKSUM_MASK0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9356 9357 { &hf_tcp_option_mptcp_B_flag,9358 { "Extensibility", "tcp.options.mptcp.extensibility.flag", FT_UINT8,9359 BASE_DEC, NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9360 9361 { &hf_tcp_option_mptcp_C_flag,9362 { "Do not attempt to establish new subflows to this address and port", "tcp.options.mptcp.nomoresubflows.flag", FT_UINT8,9363 BASE_DEC, NULL((void*)0), 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9364 9365 { &hf_tcp_option_mptcp_H_v0_flag,9366 { "Use HMAC-SHA1", "tcp.options.mptcp.sha1.flag", FT_UINT8,9367 BASE_DEC, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9368 9369 { &hf_tcp_option_mptcp_H_v1_flag,9370 { "Use HMAC-SHA256", "tcp.options.mptcp.sha256.flag", FT_UINT8,9371 BASE_DEC, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9372 9373 { &hf_tcp_option_mptcp_F_flag,9374 { "DATA_FIN", "tcp.options.mptcp.datafin.flag", FT_UINT8,9375 BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_DATA_FIN_PRESENT0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9376 9377 { &hf_tcp_option_mptcp_m_flag,9378 { "Data Sequence Number is 8 octets", "tcp.options.mptcp.dseqn8.flag", FT_UINT8,9379 BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_DSN_8BYTES0x08, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9380 9381 { &hf_tcp_option_mptcp_M_flag,9382 { "Data Sequence Number, Subflow Sequence Number, Data-level Length, Checksum present", "tcp.options.mptcp.dseqnpresent.flag", FT_UINT8,9383 BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_MAPPING_PRESENT0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9384 9385 { &hf_tcp_option_mptcp_a_flag,9386 { "Data ACK is 8 octets", "tcp.options.mptcp.dataack8.flag", FT_UINT8,9387 BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9388 9389 { &hf_tcp_option_mptcp_A_flag,9390 { "Data ACK is present", "tcp.options.mptcp.dataackpresent.flag", FT_UINT8,9391 BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_DATA_ACK_PRESENT0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9392 9393 { &hf_tcp_option_mptcp_reserved_v0_flag,9394 { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8,9395 BASE_HEX, NULL((void*)0), 0x3E, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9396 9397 { &hf_tcp_option_mptcp_reserved_v1_flag,9398 { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8,9399 BASE_HEX, NULL((void*)0), 0x1E, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9400 9401 { &hf_tcp_option_mptcp_U_flag,9402 { "Flag U", "tcp.options.mptcp.flag_U.flag", FT_BOOLEAN,9403 4, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, MPTCP_TCPRST_FLAG_U_PRESENT0x8, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9404 9405 { &hf_tcp_option_mptcp_V_flag,9406 { "Flag V", "tcp.options.mptcp.flag_V.flag", FT_BOOLEAN,9407 4, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, MPTCP_TCPRST_FLAG_V_PRESENT0x4, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9408 9409 { &hf_tcp_option_mptcp_W_flag,9410 { "Flag W", "tcp.options.mptcp.flag_W.flag", FT_BOOLEAN,9411 4, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, MPTCP_TCPRST_FLAG_W_PRESENT0x2, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9412 9413 { &hf_tcp_option_mptcp_T_flag,9414 { "Transient", "tcp.options.mptcp.flag_T.flag", FT_BOOLEAN,9415 4, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, MPTCP_TCPRST_FLAG_T_PRESENT0x1, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9416 9417 { &hf_tcp_option_mptcp_tcprst_reason,9418 { "TCPRST Reason", "tcp.options.mptcp.rst_reason", FT_UINT8,9419 BASE_HEX, VALS(mp_tcprst_reasons)((0 ? (const struct _value_string*)0 : ((mp_tcprst_reasons)))
)
, 0x0, "Multipath TCPRST Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9420 9421 { &hf_tcp_option_mptcp_address_id,9422 { "Address ID", "tcp.options.mptcp.addrid", FT_UINT8,9423 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9424 9425 { &hf_tcp_option_mptcp_sender_key,9426 { "Sender's Key", "tcp.options.mptcp.sendkey", FT_UINT64,9427 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9428 9429 { &hf_tcp_option_mptcp_recv_key,9430 { "Receiver's Key", "tcp.options.mptcp.recvkey", FT_UINT64,9431 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9432 9433 { &hf_tcp_option_mptcp_recv_token,9434 { "Receiver's Token", "tcp.options.mptcp.recvtok", FT_UINT32,9435 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9436 9437 { &hf_tcp_option_mptcp_sender_rand,9438 { "Sender's Random Number", "tcp.options.mptcp.sendrand", FT_UINT32,9439 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9440 9441 { &hf_tcp_option_mptcp_sender_trunc_hmac,9442 { "Sender's Truncated HMAC", "tcp.options.mptcp.sendtrunchmac", FT_UINT64,9443 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9444 9445 { &hf_tcp_option_mptcp_sender_hmac,9446 { "Sender's HMAC", "tcp.options.mptcp.sendhmac", FT_BYTES,9447 BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9448 9449 { &hf_tcp_option_mptcp_addaddr_trunc_hmac,9450 { "Truncated HMAC", "tcp.options.mptcp.addaddrtrunchmac", FT_UINT64,9451 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9452 9453 { &hf_tcp_option_mptcp_data_ack_raw,9454 { "Original MPTCP Data ACK", "tcp.options.mptcp.rawdataack", FT_UINT64,9455 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9456 9457 { &hf_tcp_option_mptcp_data_seq_no_raw,9458 { "Data Sequence Number", "tcp.options.mptcp.rawdataseqno", FT_UINT64,9459 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9460 9461 { &hf_tcp_option_mptcp_subflow_seq_no,9462 { "Subflow Sequence Number", "tcp.options.mptcp.subflowseqno", FT_UINT32,9463 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9464 9465 { &hf_tcp_option_mptcp_data_lvl_len,9466 { "Data-level Length", "tcp.options.mptcp.datalvllen", FT_UINT16,9467 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9468 9469 { &hf_tcp_option_mptcp_checksum,9470 { "Checksum", "tcp.options.mptcp.checksum", FT_UINT16,9471 BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9472 9473 { &hf_tcp_option_mptcp_ipver,9474 { "IP version", "tcp.options.mptcp.ipver", FT_UINT8,9475 BASE_DEC, NULL((void*)0), 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9476 9477 { &hf_tcp_option_mptcp_echo,9478 { "Echo", "tcp.options.mptcp.echo", FT_UINT8,9479 BASE_DEC, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9480 9481 { &hf_tcp_option_mptcp_ipv4,9482 { "Advertised IPv4 Address", "tcp.options.mptcp.ipv4", FT_IPv4,9483 BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9484 9485 { &hf_tcp_option_mptcp_ipv6,9486 { "Advertised IPv6 Address", "tcp.options.mptcp.ipv6", FT_IPv6,9487 BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9488 9489 { &hf_tcp_option_mptcp_port,9490 { "Advertised port", "tcp.options.mptcp.port", FT_UINT16,9491 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9492 9493 { &hf_tcp_option_cc,9494 { "TCP CC Option", "tcp.options.cc_value", FT_UINT32, BASE_DEC,9495 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9496 9497 { &hf_tcp_option_md5_digest,9498 { "MD5 digest", "tcp.options.md5.digest", FT_BYTES, BASE_NONE,9499 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9500 9501 { &hf_tcp_option_ao_keyid,9502 { "AO KeyID", "tcp.options.ao.keyid", FT_UINT8, BASE_DEC,9503 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9504 9505 { &hf_tcp_option_ao_rnextkeyid,9506 { "AO RNextKeyID", "tcp.options.ao.rnextkeyid", FT_UINT8, BASE_DEC,9507 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9508 9509 { &hf_tcp_option_ao_mac,9510 { "AO MAC", "tcp.options.ao.mac", FT_BYTES, BASE_NONE,9511 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9512 9513 { &hf_tcp_option_qs_rate,9514 { "QS Rate", "tcp.options.qs.rate", FT_UINT8, BASE_DEC|BASE_EXT_STRING0x00000200,9515 &qs_rate_vals_ext, 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9516 9517 { &hf_tcp_option_qs_ttl_diff,9518 { "QS Rate", "tcp.options.qs.ttl_diff", FT_UINT8, BASE_DEC,9519 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9520 9521 { &hf_tcp_option_tarr_rate,9522 { "TARR Rate", "tcp.options.tarr.rate", FT_UINT8, BASE_DEC,9523 NULL((void*)0), TCPOPT_TARR_RATE_MASK0xfe, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9524 9525 { &hf_tcp_option_tarr_reserved,9526 { "TARR Reserved", "tcp.options.tar.reserved", FT_UINT8, BASE_DEC,9527 NULL((void*)0), TCPOPT_TARR_RESERVED_MASK0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9528 9529 { &hf_tcp_option_acc_ecn_ee0b,9530 { "Accurate ECN Echo ECT(0) Byte Counter", "tcp.options.acc_ecn.ee0b",9531 FT_UINT24, BASE_DEC, NULL((void*)0), 0x0,9532 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9533 9534 { &hf_tcp_option_acc_ecn_eceb,9535 { "Accurate ECN Echo CE Byte Counter", "tcp.options.acc_ecn.eceb",9536 FT_UINT24, BASE_DEC, NULL((void*)0), 0x0,9537 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9538 9539 { &hf_tcp_option_acc_ecn_ee1b,9540 { "Accurate ECN Echo ECT(1) Byte Counter", "tcp.options.acc_ecn.ee1b",9541 FT_UINT24, BASE_DEC, NULL((void*)0), 0x0,9542 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9543 9544 { &hf_tcp_option_scps_vector,9545 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",9546 FT_UINT8, BASE_HEX, NULL((void*)0), 0x0,9547 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9548 9549 { &hf_tcp_option_scps_binding,9550 { "Binding Space (Community) ID",9551 "tcp.options.scps.binding.id",9552 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,9553 "TCP SCPS Extended Binding Space (Community) ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9554 9555 { &hf_tcp_option_scps_binding_len,9556 { "Extended Capability Length",9557 "tcp.options.scps.binding.len",9558 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,9559 "TCP SCPS Extended Capability Length in bytes", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9560 9561 { &hf_tcp_option_snack_offset,9562 { "TCP SNACK Offset", "tcp.options.snack.offset",9563 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,9564 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9565 9566 { &hf_tcp_option_snack_size,9567 { "TCP SNACK Size", "tcp.options.snack.size",9568 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,9569 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9570 9571 { &hf_tcp_option_snack_le,9572 { "TCP SNACK Left Edge", "tcp.options.snack.le",9573 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,9574 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9575 9576 { &hf_tcp_option_snack_re,9577 { "TCP SNACK Right Edge", "tcp.options.snack.re",9578 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,9579 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9580 9581 { &hf_tcp_scpsoption_flags_bets,9582 { "Partial Reliability Capable (BETS)",9583 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,9584 TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9585 9586 { &hf_tcp_scpsoption_flags_snack1,9587 { "Short Form SNACK Capable (SNACK1)",9588 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,9589 TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9590 9591 { &hf_tcp_scpsoption_flags_snack2,9592 { "Long Form SNACK Capable (SNACK2)",9593 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,9594 TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9595 9596 { &hf_tcp_scpsoption_flags_compress,9597 { "Lossless Header Compression (COMP)",9598 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,9599 TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, 0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9600 9601 { &hf_tcp_scpsoption_flags_nlts,9602 { "Network Layer Timestamp (NLTS)",9603 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,9604 TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, 0x8, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9605 9606 { &hf_tcp_scpsoption_flags_reserved,9607 { "Reserved",9608 "tcp.options.scpsflags.reserved", FT_UINT8, BASE_DEC,9609 NULL((void*)0), 0x7, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9610 9611 { &hf_tcp_scpsoption_connection_id,9612 { "Connection ID",9613 "tcp.options.scps.binding",9614 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,9615 "TCP SCPS Connection ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9616 9617 { &hf_tcp_option_user_to_granularity,9618 { "Granularity", "tcp.options.user_to_granularity", FT_BOOLEAN,9619 16, TFS(&tcp_option_user_to_granularity)((0 ? (const struct true_false_string*)0 : ((&tcp_option_user_to_granularity
))))
, 0x8000, "TCP User Timeout Granularity", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9620 9621 { &hf_tcp_option_user_to_val,9622 { "User Timeout", "tcp.options.user_to_val", FT_UINT16,9623 BASE_DEC, NULL((void*)0), 0x7FFF, "TCP User Timeout Value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9624 9625 { &hf_tcp_option_rvbd_probe_type1,9626 { "Type", "tcp.options.rvbd.probe.type1",9627 FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9628 9629 { &hf_tcp_option_rvbd_probe_type2,9630 { "Type", "tcp.options.rvbd.probe.type2",9631 FT_UINT8, BASE_DEC, NULL((void*)0), 0xFE, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9632 9633 { &hf_tcp_option_rvbd_probe_version1,9634 { "Version", "tcp.options.rvbd.probe.version",9635 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9636 9637 { &hf_tcp_option_rvbd_probe_version2,9638 { "Version", "tcp.options.rvbd.probe.version_raw",9639 FT_UINT8, BASE_DEC, NULL((void*)0), 0x01, "Version 2 Raw Value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9640 9641 { &hf_tcp_option_rvbd_probe_prober,9642 { "CSH IP", "tcp.options.rvbd.probe.prober",9643 FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9644 9645 { &hf_tcp_option_rvbd_probe_proxy,9646 { "SSH IP", "tcp.options.rvbd.probe.proxy.ip",9647 FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9648 9649 { &hf_tcp_option_rvbd_probe_proxy_port,9650 { "SSH Port", "tcp.options.rvbd.probe.proxy.port",9651 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9652 9653 { &hf_tcp_option_rvbd_probe_appli_ver,9654 { "Application Version", "tcp.options.rvbd.probe.appli_ver",9655 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9656 9657 { &hf_tcp_option_rvbd_probe_client,9658 { "Client IP", "tcp.options.rvbd.probe.client.ip",9659 FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9660 9661 { &hf_tcp_option_rvbd_probe_storeid,9662 { "CFE Store ID", "tcp.options.rvbd.probe.storeid",9663 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9664 9665 { &hf_tcp_option_rvbd_probe_flags,9666 { "Probe Flags", "tcp.options.rvbd.probe.flags",9667 FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9668 9669 { &hf_tcp_option_rvbd_probe_flag_not_cfe,9670 { "Not CFE", "tcp.options.rvbd.probe.flags.notcfe",9671 FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, RVBD_FLAGS_PROBE_NCFE0x04,9672 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9673 9674 { &hf_tcp_option_rvbd_probe_flag_last_notify,9675 { "Last Notify", "tcp.options.rvbd.probe.flags.last",9676 FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, RVBD_FLAGS_PROBE_LAST0x01,9677 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9678 9679 { &hf_tcp_option_rvbd_probe_flag_probe_cache,9680 { "Disable Probe Cache on CSH", "tcp.options.rvbd.probe.flags.probe",9681 FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, RVBD_FLAGS_PROBE0x10,9682 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9683 9684 { &hf_tcp_option_rvbd_probe_flag_sslcert,9685 { "SSL Enabled", "tcp.options.rvbd.probe.flags.ssl",9686 FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, RVBD_FLAGS_PROBE_SSLCERT0x02,9687 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9688 9689 { &hf_tcp_option_rvbd_probe_flag_server_connected,9690 { "SSH outer to server established", "tcp.options.rvbd.probe.flags.server",9691 FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, RVBD_FLAGS_PROBE_SERVER0x01,9692 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9693 9694 { &hf_tcp_option_rvbd_trpy_flags,9695 { "Transparency Options", "tcp.options.rvbd.trpy.flags",9696 FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9697 9698 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,9699 { "Enable FW traversal feature", "tcp.options.rvbd.trpy.flags.fw_rst_probe",9700 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
,9701 RVBD_FLAGS_TRPY_FW_RST_PROBE0x0400,9702 "Reset state created by probe on the nexthop firewall",9703 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9704 9705 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,9706 { "Enable Inner FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst_inner",9707 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
,9708 RVBD_FLAGS_TRPY_FW_RST_INNER0x0200,9709 "Reset state created by transparent inner on all firewalls"9710 " before passing connection through",9711 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9712 9713 { &hf_tcp_option_rvbd_trpy_flag_fw_rst,9714 { "Enable Transparency FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst",9715 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
,9716 RVBD_FLAGS_TRPY_FW_RST0x0100,9717 "Reset state created by probe on all firewalls before "9718 "establishing transparent inner connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9719 9720 { &hf_tcp_option_rvbd_trpy_flag_chksum,9721 { "Reserved", "tcp.options.rvbd.trpy.flags.chksum",9722 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
,9723 RVBD_FLAGS_TRPY_CHKSUM0x0004, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9724 9725 { &hf_tcp_option_rvbd_trpy_flag_oob,9726 { "Out of band connection", "tcp.options.rvbd.trpy.flags.oob",9727 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
,9728 RVBD_FLAGS_TRPY_OOB0x0002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9729 9730 { &hf_tcp_option_rvbd_trpy_flag_mode,9731 { "Transparency Mode", "tcp.options.rvbd.trpy.flags.mode",9732 FT_BOOLEAN, 16, TFS(&trpy_mode_str)((0 ? (const struct true_false_string*)0 : ((&trpy_mode_str
))))
,9733 RVBD_FLAGS_TRPY_MODE0x0001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9734 9735 { &hf_tcp_option_rvbd_trpy_src,9736 { "Src SH IP Addr", "tcp.options.rvbd.trpy.src.ip",9737 FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9738 9739 { &hf_tcp_option_rvbd_trpy_dst,9740 { "Dst SH IP Addr", "tcp.options.rvbd.trpy.dst.ip",9741 FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9742 9743 { &hf_tcp_option_rvbd_trpy_src_port,9744 { "Src SH Inner Port", "tcp.options.rvbd.trpy.src.port",9745 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9746 9747 { &hf_tcp_option_rvbd_trpy_dst_port,9748 { "Dst SH Inner Port", "tcp.options.rvbd.trpy.dst.port",9749 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9750 9751 { &hf_tcp_option_rvbd_trpy_client_port,9752 { "Out of band connection Client Port", "tcp.options.rvbd.trpy.client.port",9753 FT_UINT16, BASE_DEC, NULL((void*)0) , 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9754 9755 { &hf_tcp_option_fast_open_cookie_request,9756 { "Fast Open Cookie Request", "tcp.options.tfo.request", FT_NONE,9757 BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9758 9759 { &hf_tcp_option_fast_open_cookie,9760 { "Fast Open Cookie", "tcp.options.tfo.cookie", FT_BYTES,9761 BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9762 9763 { &hf_tcp_pdu_time,9764 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,9765 "How long time has passed until the last frame of this PDU", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9766 9767 { &hf_tcp_pdu_size,9768 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9769 "The size of this PDU", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9770 9771 { &hf_tcp_pdu_last_frame,9772 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,9773 "This is the last frame of the PDU starting in this segment", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9774 9775 { &hf_tcp_ts_relative,9776 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,9777 "Time relative to first frame in this TCP stream", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9778 9779 { &hf_tcp_ts_delta,9780 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,9781 "Time delta from previous frame in this TCP stream", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9782 9783 { &hf_tcp_proc_src_uid,9784 { "Source process user ID", "tcp.proc.srcuid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9785 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9786 9787 { &hf_tcp_proc_src_pid,9788 { "Source process ID", "tcp.proc.srcpid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9789 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9790 9791 { &hf_tcp_proc_src_uname,9792 { "Source process user name", "tcp.proc.srcuname", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,9793 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9794 9795 { &hf_tcp_proc_src_cmd,9796 { "Source process name", "tcp.proc.srccmd", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,9797 "Source process command name", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9798 9799 { &hf_tcp_proc_dst_uid,9800 { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9801 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9802 9803 { &hf_tcp_proc_dst_pid,9804 { "Destination process ID", "tcp.proc.dstpid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9805 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9806 9807 { &hf_tcp_proc_dst_uname,9808 { "Destination process user name", "tcp.proc.dstuname", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,9809 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9810 9811 { &hf_tcp_proc_dst_cmd,9812 { "Destination process name", "tcp.proc.dstcmd", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,9813 "Destination process command name", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9814 9815 { &hf_tcp_segment_data,9816 { "TCP segment data", "tcp.segment_data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,9817 "A data segment used in reassembly of an upper-layer protocol (ULP)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9818 9819 { &hf_tcp_payload,9820 { "TCP payload", "tcp.payload", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,9821 "The TCP payload of this packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},9822 9823 { &hf_tcp_option_scps_binding_data,9824 { "Binding Space Data", "tcp.options.scps.binding.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,9825 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9826 9827 { &hf_tcp_option_rvbd_probe_reserved,9828 { "Reserved", "tcp.options.rvbd.probe.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0,9829 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9830 9831 { &hf_tcp_fin_retransmission,9832 { "Retransmission of FIN from frame", "tcp.fin_retransmission", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,9833 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9834 9835 { &hf_tcp_reset_cause,9836 { "Reset cause", "tcp.reset_cause", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,9837 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9838 9839 { &hf_tcp_syncookie_time,9840 { "SYN Cookie Time", "tcp.syncookie.time", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,9841 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9842 9843 { &hf_tcp_syncookie_mss,9844 { "SYN Cookie Maximum Segment Size", "tcp.syncookie.mss", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,9845 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9846 9847 { &hf_tcp_syncookie_hash,9848 { "SYN Cookie hash", "tcp.syncookie.hash", FT_UINT24, BASE_HEX, NULL((void*)0), 0x0,9849 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9850 9851 { &hf_tcp_syncookie_option_timestamp,9852 { "SYN Cookie Timestamp", "tcp.options.timestamp.tsval.syncookie.timestamp", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,9853 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9854 9855 { &hf_tcp_syncookie_option_ecn,9856 { "SYN Cookie ECN", "tcp.options.timestamp.tsval.syncookie.ecn", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,9857 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9858 9859 { &hf_tcp_syncookie_option_sack,9860 { "SYN Cookie SACK", "tcp.options.timestamp.tsval.syncookie.sack", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,9861 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9862 9863 { &hf_tcp_syncookie_option_wscale,9864 { "SYN Cookie WScale", "tcp.options.timestamp.tsval.syncookie.wscale", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,9865 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},9866 };9867 9868 static gint *ett[] = {9869 &ett_tcp,9870 &ett_tcp_completeness,9871 &ett_tcp_flags,9872 &ett_tcp_options,9873 &ett_tcp_option_timestamp,9874 &ett_tcp_option_mptcp,9875 &ett_tcp_option_wscale,9876 &ett_tcp_option_sack,9877 &ett_tcp_option_snack,9878 &ett_tcp_option_scps,9879 &ett_tcp_scpsoption_flags,9880 &ett_tcp_option_scps_extended,9881 &ett_tcp_option_user_to,9882 &ett_tcp_option_exp,9883 &ett_tcp_option_acc_ecn,9884 &ett_tcp_option_sack_perm,9885 &ett_tcp_option_mss,9886 &ett_tcp_opt_rvbd_probe,9887 &ett_tcp_opt_rvbd_probe_flags,9888 &ett_tcp_opt_rvbd_trpy,9889 &ett_tcp_opt_rvbd_trpy_flags,9890 &ett_tcp_opt_echo,9891 &ett_tcp_opt_cc,9892 &ett_tcp_opt_md5,9893 &ett_tcp_opt_ao,9894 &ett_tcp_opt_qs,9895 &ett_tcp_analysis_faults,9896 &ett_tcp_analysis,9897 &ett_tcp_timestamps,9898 &ett_tcp_segments,9899 &ett_tcp_segment,9900 &ett_tcp_checksum,9901 &ett_tcp_process_info,9902 &ett_tcp_unknown_opt,9903 &ett_tcp_opt_recbound,9904 &ett_tcp_opt_scpscor,9905 &ett_tcp_option_other,9906 &ett_tcp_syncookie,9907 &ett_tcp_syncookie_option9908 };9909 9910 static gint *mptcp_ett[] = {9911 &ett_mptcp_analysis,9912 &ett_mptcp_analysis_subflows9913 };9914 9915 static const enum_val_t window_scaling_vals[] = {9916 {"not-known", "Not known", WindowScaling_NotKnown},9917 {"0", "0 (no scaling)", WindowScaling_0},9918 {"1", "1 (multiply by 2)", WindowScaling_1},9919 {"2", "2 (multiply by 4)", WindowScaling_2},9920 {"3", "3 (multiply by 8)", WindowScaling_3},9921 {"4", "4 (multiply by 16)", WindowScaling_4},9922 {"5", "5 (multiply by 32)", WindowScaling_5},9923 {"6", "6 (multiply by 64)", WindowScaling_6},9924 {"7", "7 (multiply by 128)", WindowScaling_7},9925 {"8", "8 (multiply by 256)", WindowScaling_8},9926 {"9", "9 (multiply by 512)", WindowScaling_9},9927 {"10", "10 (multiply by 1024)", WindowScaling_10},9928 {"11", "11 (multiply by 2048)", WindowScaling_11},9929 {"12", "12 (multiply by 4096)", WindowScaling_12},9930 {"13", "13 (multiply by 8192)", WindowScaling_13},9931 {"14", "14 (multiply by 16384)", WindowScaling_14},9932 {NULL((void*)0), NULL((void*)0), -1}9933 };9934 9935 static const enum_val_t override_analysis_vals[] = {9936 {"0", "0 (none)", OverrideAnalysis_0},9937 {"1", "1 (Out-of-Order)", OverrideAnalysis_1},9938 {"2", "2 (Retransmission)", OverrideAnalysis_2},9939 {"3", "3 (Fast Retransmission)", OverrideAnalysis_3},9940 {"4", "4 (Spurious Retransmission)",OverrideAnalysis_4},9941 {NULL((void*)0), NULL((void*)0), -1}9942 };9943 9944 static ei_register_info ei[] = {9945 { &ei_tcp_opt_len_invalid, { "tcp.option.len.invalid", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "Invalid length for option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9946 { &ei_tcp_analysis_retransmission, { "tcp.analysis.retransmission", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame is a (suspected) retransmission", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9947 { &ei_tcp_analysis_fast_retransmission, { "tcp.analysis.fast_retransmission", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame is a (suspected) fast retransmission", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9948 { &ei_tcp_analysis_spurious_retransmission, { "tcp.analysis.spurious_retransmission", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame is a (suspected) spurious retransmission", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9949 { &ei_tcp_analysis_out_of_order, { "tcp.analysis.out_of_order", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "This frame is a (suspected) out-of-order segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9950 { &ei_tcp_analysis_reused_ports, { "tcp.analysis.reused_ports", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "A new tcp session is started with the same ports as an earlier session in this trace", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9951 { &ei_tcp_analysis_lost_packet, { "tcp.analysis.lost_segment", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "Previous segment(s) not captured (common at capture start)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9952 { &ei_tcp_analysis_ack_lost_packet, { "tcp.analysis.ack_lost_segment", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "ACKed segment that wasn't captured (common at capture start)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9953 { &ei_tcp_analysis_window_update, { "tcp.analysis.window_update", PI_SEQUENCE0x02000000, PI_CHAT0x00200000, "TCP window update", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9954 { &ei_tcp_analysis_window_full, { "tcp.analysis.window_full", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "TCP window specified by the receiver is now completely full", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9955 { &ei_tcp_analysis_keep_alive, { "tcp.analysis.keep_alive", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP keep-alive segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9956 { &ei_tcp_analysis_keep_alive_ack, { "tcp.analysis.keep_alive_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "ACK to a TCP keep-alive segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9957 { &ei_tcp_analysis_duplicate_ack, { "tcp.analysis.duplicate_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "Duplicate ACK", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9958 { &ei_tcp_analysis_zero_window_probe, { "tcp.analysis.zero_window_probe", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP Zero Window Probe", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9959 { &ei_tcp_analysis_zero_window, { "tcp.analysis.zero_window", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "TCP Zero Window segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9960 { &ei_tcp_analysis_zero_window_probe_ack, { "tcp.analysis.zero_window_probe_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "ACK to a TCP Zero Window Probe", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9961 { &ei_tcp_analysis_tfo_syn, { "tcp.analysis.tfo_syn", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP SYN with TFO Cookie", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9962 { &ei_tcp_analysis_tfo_ack, { "tcp.analysis.tfo_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP SYN-ACK accepting TFO data", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9963 { &ei_tcp_analysis_tfo_ignored, { "tcp.analysis.tfo_ignored", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP SYN-ACK ignoring TFO data", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9964 { &ei_tcp_analysis_partial_ack, { "tcp.analysis.partial_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "Partial Acknowledgement of a segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9965 { &ei_tcp_connection_fin_active, { "tcp.connection.fin_active", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame initiates the connection closing", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9966 { &ei_tcp_connection_fin_passive, { "tcp.connection.fin_passive", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame undergoes the connection closing", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9967 { &ei_tcp_scps_capable, { "tcp.analysis.zero_window_probe_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9968 { &ei_tcp_option_sack_dsack, { "tcp.options.sack.dsack", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "D-SACK Sequence", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9969 { &ei_tcp_option_snack_sequence, { "tcp.options.snack.sequence", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "SNACK Sequence", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9970 { &ei_tcp_option_wscale_shift_invalid, { "tcp.options.wscale.shift.invalid", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Window scale shift exceeds 14", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9971 { &ei_tcp_option_mss_absent, { "tcp.options.mss.absent", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "The SYN packet does not contain a MSS option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9972 { &ei_tcp_option_mss_present, { "tcp.options.mss.present", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "The non-SYN packet does contain a MSS option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9973 { &ei_tcp_option_sack_perm_absent, { "tcp.options.sack_perm.absent", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "The SYN packet does not contain a SACK PERM option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9974 { &ei_tcp_option_sack_perm_present, { "tcp.options.sack_perm.present", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "The non-SYN packet does contain a SACK PERM option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9975 { &ei_tcp_short_segment, { "tcp.short_segment", PI_MALFORMED0x07000000, PI_WARN0x00600000, "Short segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9976 { &ei_tcp_ack_nonzero, { "tcp.ack.nonzero", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "The acknowledgment number field is nonzero while the ACK flag is not set", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9977 { &ei_tcp_connection_synack, { "tcp.connection.synack", PI_SEQUENCE0x02000000, PI_CHAT0x00200000, "Connection establish acknowledge (SYN+ACK)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9978 { &ei_tcp_connection_syn, { "tcp.connection.syn", PI_SEQUENCE0x02000000, PI_CHAT0x00200000, "Connection establish request (SYN)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9979 { &ei_tcp_connection_fin, { "tcp.connection.fin", PI_SEQUENCE0x02000000, PI_CHAT0x00200000, "Connection finish (FIN)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9980 /* According to RFCs, RST is an indication of an error. Some applications use it9981 * to terminate a connection as well, which is a misbehavior (see e.g. rfc3360)9982 */9983 { &ei_tcp_connection_rst, { "tcp.connection.rst", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "Connection reset (RST)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9984 { &ei_tcp_checksum_ffff, { "tcp.checksum.ffff", PI_CHECKSUM0x01000000, PI_WARN0x00600000, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9985 { &ei_tcp_checksum_partial, { "tcp.checksum.partial", PI_CHECKSUM0x01000000, PI_NOTE0x00400000, "Partial (pseudo header) checksum (likely caused by \"TCP checksum offload\")", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9986 { &ei_tcp_checksum_bad, { "tcp.checksum_bad.expert", PI_CHECKSUM0x01000000, PI_ERROR0x00800000, "Bad checksum", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9987 { &ei_tcp_urgent_pointer_non_zero, { "tcp.urgent_pointer.non_zero", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "The urgent pointer field is nonzero while the URG flag is not set", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9988 { &ei_tcp_suboption_malformed, { "tcp.suboption_malformed", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "suboption would go past end of option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9989 { &ei_tcp_nop, { "tcp.nop", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "4 NOP in a row - a router may have removed some options", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9990 { &ei_tcp_non_zero_bytes_after_eol, { "tcp.non_zero_bytes_after_eol", PI_PROTOCOL0x09000000, PI_ERROR0x00800000, "Non zero bytes in option space after EOL option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9991 { &ei_tcp_bogus_header_length, { "tcp.bogus_header_length", PI_PROTOCOL0x09000000, PI_ERROR0x00800000, "Bogus TCP Header length", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9992 };9993 9994 static ei_register_info mptcp_ei[] = {9995#if 09996 { &ei_mptcp_analysis_unexpected_idsn, { "mptcp.connection.unexpected_idsn", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "Unexpected initial sequence number", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9997#endif9998 { &ei_mptcp_analysis_echoed_key_mismatch, { "mptcp.connection.echoed_key_mismatch", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "The echoed key in the ACK of the MPTCP handshake does not match the key of the SYN/ACK", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},9999 { &ei_mptcp_analysis_missing_algorithm, { "mptcp.connection.missing_algorithm", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "No crypto algorithm specified", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},10000 { &ei_mptcp_analysis_unsupported_algorithm, { "mptcp.connection.unsupported_algorithm", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Unsupported algorithm", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},10001 { &ei_mptcp_infinite_mapping, { "mptcp.dss.infinite_mapping", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Fallback to infinite mapping", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},10002 { &ei_mptcp_mapping_missing, { "mptcp.dss.missing_mapping", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "No mapping available", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},10003#if 010004 { &ei_mptcp_stream_incomplete, { "mptcp.incomplete", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Everything was not captured", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},10005 { &ei_mptcp_analysis_dsn_out_of_order, { "mptcp.analysis.dsn.out_of_order", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Out of order dsn", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},10006#endif10007 };10008 10009 static hf_register_info mptcp_hf[] = {10010 { &hf_mptcp_ack,10011 { "Multipath TCP Data ACK", "mptcp.ack", FT_UINT64,10012 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},10013 10014 { &hf_mptcp_dsn,10015 { "Data Sequence Number", "mptcp.dsn", FT_UINT64, BASE_DEC, NULL((void*)0), 0x0,10016 "Data Sequence Number mapped to this TCP sequence number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},10017 10018 { &hf_mptcp_rawdsn64,10019 { "Raw Data Sequence Number", "mptcp.rawdsn64", FT_UINT64, BASE_DEC, NULL((void*)0), 0x0,10020 "Data Sequence Number mapped to this TCP sequence number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},10021 10022 { &hf_mptcp_dss_dsn,10023 { "DSS Data Sequence Number", "mptcp.dss.dsn", FT_UINT64,10024 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},10025 10026 { &hf_mptcp_expected_idsn,10027 { "Subflow expected IDSN", "mptcp.expected_idsn", FT_UINT64,10028 BASE_DEC|BASE_UNIT_STRING0x00001000, &units_64bit_version, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},10029 10030 { &hf_mptcp_analysis,10031 { "MPTCP analysis", "mptcp.analysis", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,10032 "This frame has some of the MPTCP analysis shown", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},10033 10034 { &hf_mptcp_related_mapping,10035 { "Related mapping", "mptcp.related_mapping", FT_FRAMENUM , BASE_NONE, NULL((void*)0), 0x0,10036 "Packet in which current packet DSS mapping was sent", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},10037 10038 { &hf_mptcp_reinjection_of,10039 { "Reinjection of", "mptcp.reinjection_of", FT_FRAMENUM , BASE_NONE, NULL((void*)0), 0x0,10040 "This is a retransmission of data sent on another subflow", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},10041 10042 { &hf_mptcp_reinjected_in,10043 { "Data reinjected in", "mptcp.reinjected_in", FT_FRAMENUM , BASE_NONE, NULL((void*)0), 0x0,10044 "This was retransmitted on another subflow", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},10045 10046 { &hf_mptcp_analysis_subflows,10047 { "TCP subflow stream id(s)", "mptcp.analysis.subflows", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,10048 "List all TCP connections mapped to this MPTCP connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},10049 10050 { &hf_mptcp_stream,10051 { "Stream index", "mptcp.stream", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,10052 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},10053 10054 { &hf_mptcp_number_of_removed_addresses,10055 { "Number of removed addresses", "mptcp.rm_addr.count", FT_UINT8,10056 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},10057 10058 { &hf_mptcp_expected_token,10059 { "Subflow token generated from key", "mptcp.expected_token", FT_UINT32,10060 BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},10061 10062 { &hf_mptcp_analysis_master,10063 { "Master flow", "mptcp.master", FT_BOOLEAN, BASE_NONE,10064 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}10065 10066 };10067 10068 static build_valid_func tcp_da_src_values[1] = {tcp_src_value};10069 static build_valid_func tcp_da_dst_values[1] = {tcp_dst_value};10070 static build_valid_func tcp_da_both_values[2] = {tcp_src_value, tcp_dst_value};10071 static decode_as_value_t tcp_da_values[3] = {{tcp_src_prompt, 1, tcp_da_src_values}, {tcp_dst_prompt, 1, tcp_da_dst_values}, {tcp_both_prompt, 2, tcp_da_both_values}};10072 static decode_as_t tcp_da = {"tcp", "tcp.port", 3, 2, tcp_da_values, "TCP", "port(s) as",10073 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL((void*)0)};10074 10075 module_t *tcp_module;10076 module_t *mptcp_module;10077 expert_module_t* expert_tcp;10078 expert_module_t* expert_mptcp;10079 10080 proto_tcp = proto_register_protocol("Transmission Control Protocol", "TCP", "tcp");10081 tcp_handle = register_dissector("tcp", dissect_tcp, proto_tcp);10082 tcp_cap_handle = register_capture_dissector("tcp", capture_tcp, proto_tcp);10083 proto_register_field_array(proto_tcp, hf, array_length(hf)(sizeof hf / sizeof hf[0]));10084 proto_register_subtree_array(ett, array_length(ett)(sizeof ett / sizeof ett[0]));10085 expert_tcp = expert_register_protocol(proto_tcp);10086 expert_register_field_array(expert_tcp, ei, array_length(ei)(sizeof ei / sizeof ei[0]));10087 10088 /* subdissector code */10089 subdissector_table = register_dissector_table("tcp.port",10090 "TCP port", proto_tcp, FT_UINT16, BASE_DEC);10091 heur_subdissector_list = register_heur_dissector_list_with_description("tcp", "TCP heuristic", proto_tcp);10092 tcp_option_table = register_dissector_table("tcp.option",10093 "TCP Options", proto_tcp, FT_UINT8, BASE_DEC);10094 10095 /* Register TCP options as their own protocols so we can get the name of the option */10096 proto_tcp_option_nop = proto_register_protocol_in_name_only("TCP Option - No-Operation (NOP)", "No-Operation (NOP)", "tcp.options.nop", proto_tcp, FT_BYTES);10097 proto_tcp_option_eol = proto_register_protocol_in_name_only("TCP Option - End of Option List (EOL)", "End of Option List (EOL)", "tcp.options.eol", proto_tcp, FT_BYTES);10098 proto_tcp_option_timestamp = proto_register_protocol_in_name_only("TCP Option - Timestamps", "Timestamps", "tcp.options.timestamp", proto_tcp, FT_BYTES);10099 proto_tcp_option_mss = proto_register_protocol_in_name_only("TCP Option - Maximum segment size", "Maximum segment size", "tcp.options.mss", proto_tcp, FT_BYTES);10100 proto_tcp_option_wscale = proto_register_protocol_in_name_only("TCP Option - Window scale", "Window scale", "tcp.options.wscale", proto_tcp, FT_BYTES);10101 proto_tcp_option_sack_perm = proto_register_protocol_in_name_only("TCP Option - SACK permitted", "SACK permitted", "tcp.options.sack_perm", proto_tcp, FT_BYTES);10102 proto_tcp_option_sack = proto_register_protocol_in_name_only("TCP Option - SACK", "SACK", "tcp.options.sack", proto_tcp, FT_BYTES);10103 proto_tcp_option_echo = proto_register_protocol_in_name_only("TCP Option - Echo", "Echo", "tcp.options.echo", proto_tcp, FT_BYTES);10104 proto_tcp_option_echoreply = proto_register_protocol_in_name_only("TCP Option - Echo reply", "Echo reply", "tcp.options.echoreply", proto_tcp, FT_BYTES);10105 proto_tcp_option_cc = proto_register_protocol_in_name_only("TCP Option - CC", "CC", "tcp.options.cc", proto_tcp, FT_BYTES);10106 proto_tcp_option_cc_new = proto_register_protocol_in_name_only("TCP Option - CC.NEW", "CC.NEW", "tcp.options.ccnew", proto_tcp, FT_BYTES);10107 proto_tcp_option_cc_echo = proto_register_protocol_in_name_only("TCP Option - CC.ECHO", "CC.ECHO", "tcp.options.ccecho", proto_tcp, FT_BYTES);10108 proto_tcp_option_ao = proto_register_protocol_in_name_only("TCP Option - TCP AO", "TCP AO", "tcp.options.ao", proto_tcp, FT_BYTES);10109 proto_tcp_option_md5 = proto_register_protocol_in_name_only("TCP Option - TCP MD5 signature", "TCP MD5 signature", "tcp.options.md5", proto_tcp, FT_BYTES);10110 proto_tcp_option_scps = proto_register_protocol_in_name_only("TCP Option - SCPS capabilities", "SCPS capabilities", "tcp.options.scps", proto_tcp, FT_BYTES);10111 proto_tcp_option_snack = proto_register_protocol_in_name_only("TCP Option - Selective Negative Acknowledgment", "Selective Negative Acknowledgment", "tcp.options.snack", proto_tcp, FT_BYTES);10112 proto_tcp_option_scpsrec = proto_register_protocol_in_name_only("TCP Option - SCPS record boundary", "SCPS record boundary", "tcp.options.scpsrec", proto_tcp, FT_BYTES);10113 proto_tcp_option_scpscor = proto_register_protocol_in_name_only("TCP Option - SCPS corruption experienced", "SCPS corruption experienced", "tcp.options.scpscor", proto_tcp, FT_BYTES);10114 proto_tcp_option_qs = proto_register_protocol_in_name_only("TCP Option - Quick-Start", "Quick-Start", "tcp.options.qs", proto_tcp, FT_BYTES);10115 proto_tcp_option_user_to = proto_register_protocol_in_name_only("TCP Option - User Timeout", "User Timeout", "tcp.options.user_to", proto_tcp, FT_BYTES);10116 proto_tcp_option_tfo = proto_register_protocol_in_name_only("TCP Option - TCP Fast Open", "TCP Fast Open", "tcp.options.tfo", proto_tcp, FT_BYTES);10117 proto_tcp_option_acc_ecn = proto_register_protocol_in_name_only("TCP Option - Accurate ECN", "Accurate ECN", "tcp.options.acc_ecn", proto_tcp, FT_BYTES);10118 proto_tcp_option_rvbd_probe = proto_register_protocol_in_name_only("TCP Option - Riverbed Probe", "Riverbed Probe", "tcp.options.rvbd.probe", proto_tcp, FT_BYTES);10119 proto_tcp_option_rvbd_trpy = proto_register_protocol_in_name_only("TCP Option - Riverbed Transparency", "Riverbed Transparency", "tcp.options.rvbd.trpy", proto_tcp, FT_BYTES);10120 proto_tcp_option_exp = proto_register_protocol_in_name_only("TCP Option - Experimental", "Experimental", "tcp.options.experimental", proto_tcp, FT_BYTES);10121 proto_tcp_option_unknown = proto_register_protocol_in_name_only("TCP Option - Unknown", "Unknown", "tcp.options.unknown", proto_tcp, FT_BYTES);10122 10123 register_capture_dissector_table("tcp.port", "TCP");10124 10125 /* Register configuration preferences */10126 tcp_module = prefs_register_protocol(proto_tcp, NULL((void*)0));10127 prefs_register_bool_preference(tcp_module, "summary_in_tree",10128 "Show TCP summary in protocol tree",10129 "Whether the TCP summary line should be shown in the protocol tree",10130 &tcp_summary_in_tree);10131 prefs_register_bool_preference(tcp_module, "check_checksum",10132 "Validate the TCP checksum if possible",10133 "Whether to validate the TCP checksum or not. "10134 "(Invalid checksums will cause reassembly, if enabled, to fail.)",10135 &tcp_check_checksum);10136 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",10137 "Allow subdissector to reassemble TCP streams",10138 "Whether subdissector can request TCP streams to be reassembled",10139 &tcp_desegment);10140 prefs_register_bool_preference(tcp_module, "reassemble_out_of_order",10141 "Reassemble out-of-order segments",10142 "Whether out-of-order segments should be buffered and reordered before passing it to a subdissector. "10143 "To use this option you must also enable \"Allow subdissector to reassemble TCP streams\".",10144 &tcp_reassemble_out_of_order);10145 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",10146 "Analyze TCP sequence numbers",10147 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",10148 &tcp_analyze_seq);10149 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",10150 "Relative sequence numbers (Requires \"Analyze TCP sequence numbers\")",10151 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "10152 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",10153 &tcp_relative_seq);10154 10155 prefs_register_custom_preference_TCP_Analysis(tcp_module, "default_override_analysis",10156 "Force interpretation to selected packet(s)",10157 "Override the default analysis with this value for the selected packet",10158 &tcp_default_override_analysis, override_analysis_vals, FALSE(0));10159 10160 prefs_register_enum_preference(tcp_module, "default_window_scaling",10161 "Scaling factor to use when not available from capture",10162 "Make the TCP dissector use this scaling factor for streams where the signalled scaling factor "10163 "is not visible in the capture",10164 &tcp_default_window_scaling, window_scaling_vals, FALSE(0));10165 10166 /* Presumably a retired, unconditional version of what has been added back with the preference above... */10167 prefs_register_obsolete_preference(tcp_module, "window_scaling");10168 10169 prefs_register_bool_preference(tcp_module, "track_bytes_in_flight",10170 "Track number of bytes in flight",10171 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "10172 "To use this option you must also enable \"Analyze TCP sequence numbers\". "10173 "This takes a lot of memory but allows you to track how much data are in flight at a time and graphing it in io-graphs",10174 &tcp_track_bytes_in_flight);10175 prefs_register_bool_preference(tcp_module, "bif_seq_based",10176 "Evaluate bytes in flight based on sequence numbers",10177 "Evaluate BiF on actual sequence numbers or use the historical method based on payloads (default). "10178 "This option has no effect if not used with \"Track number of bytes in flight\". ",10179 &tcp_bif_seq_based);10180 prefs_register_bool_preference(tcp_module, "calculate_timestamps",10181 "Calculate stream packet number and timestamps",10182 "Calculate relative packet number and timestamps relative to the first frame and the previous frame in the tcp conversation",10183 &tcp_calculate_ts);10184 prefs_register_bool_preference(tcp_module, "try_heuristic_first",10185 "Try heuristic sub-dissectors first",10186 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",10187 &try_heuristic_first);10188 prefs_register_bool_preference(tcp_module, "ignore_tcp_timestamps",10189 "Ignore TCP Timestamps in summary",10190 "Do not place the TCP Timestamps in the summary line",10191 &tcp_ignore_timestamps);10192 prefs_register_bool_preference(tcp_module, "fastrt_supersedes_ooo",10193 "Fast Retransmission supersedes Out-of-Order interpretation",10194 "When interpreting ambiguous packets, give precedence to Fast Retransmission or OOO ",10195 &tcp_fastrt_precedence);10196 10197 prefs_register_bool_preference(tcp_module, "no_subdissector_on_error",10198 "Do not call subdissectors for error packets",10199 "Do not call any subdissectors for Retransmitted or OutOfOrder segments",10200 &tcp_no_subdissector_on_error);10201 10202 prefs_register_bool_preference(tcp_module, "dissect_experimental_options_rfc6994",10203 "TCP Experimental Options using the format of RFC 6994",10204 "Assume TCP Experimental Options (253, 254) have an Experiment Identifier and use it for dissection",10205 &tcp_exp_options_rfc6994);10206 10207 prefs_register_bool_preference(tcp_module, "display_process_info_from_ipfix",10208 "Display process information via IPFIX",10209 "Collect and store process information retrieved from IPFIX dissector",10210 &tcp_display_process_info);10211 10212 prefs_register_bool_preference(tcp_module, "read_seq_as_syn_cookie",10213 "Read the seq no. as syn cookie",10214 "Read the sequence number as it was a syn cookie",10215 &read_seq_as_syn_cookie);10216 10217 register_init_routine(tcp_init);10218 reassembly_table_register(&tcp_reassembly_table,10219 &tcp_reassembly_table_functions);10220 10221 register_decode_as(&tcp_da);10222 10223 register_conversation_table(proto_tcp, FALSE(0), tcpip_conversation_packet, tcpip_endpoint_packet);10224 register_conversation_filter("tcp", "TCP", tcp_filter_valid, tcp_build_filter_by_id, NULL((void*)0));10225 10226 register_seq_analysis("tcp", "TCP Flows", proto_tcp, NULL((void*)0), TL_REQUIRES_NOTHING0x00000000, tcp_seq_analysis_packet);10227 10228 /* considers MPTCP as a distinct protocol (even if it's a TCP option) */10229 proto_mptcp = proto_register_protocol("Multipath Transmission Control Protocol", "MPTCP", "mptcp");10230 10231 proto_register_field_array(proto_mptcp, mptcp_hf, array_length(mptcp_hf)(sizeof mptcp_hf / sizeof mptcp_hf[0]));10232 proto_register_subtree_array(mptcp_ett, array_length(mptcp_ett)(sizeof mptcp_ett / sizeof mptcp_ett[0]));10233 10234 /* Register configuration preferences */10235 mptcp_module = prefs_register_protocol(proto_mptcp, NULL((void*)0));10236 expert_mptcp = expert_register_protocol(proto_tcp);10237 expert_register_field_array(expert_mptcp, mptcp_ei, array_length(mptcp_ei)(sizeof mptcp_ei / sizeof mptcp_ei[0]));10238 10239 prefs_register_bool_preference(mptcp_module, "analyze_mptcp",10240 "Map TCP subflows to their respective MPTCP connections",10241 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",10242 &tcp_analyze_mptcp);10243 10244 prefs_register_bool_preference(mptcp_module, "relative_sequence_numbers",10245 "Display relative MPTCP sequence numbers.",10246 "In case you don't capture the key, it will use the first DSN seen",10247 &mptcp_relative_seq);10248 10249 prefs_register_bool_preference(mptcp_module, "analyze_mappings",10250 "Deeper analysis of Data Sequence Signal (DSS)",10251 "Scales logarithmically with the number of packets"10252 "You need to capture the handshake for this to work."10253 "\"Map TCP subflows to their respective MPTCP connections\"",10254 &mptcp_analyze_mappings);10255 10256 prefs_register_bool_preference(mptcp_module, "intersubflows_retransmission",10257 "Check for data duplication across subflows",10258 "(Greedy algorithm: Scales linearly with number of subflows and"10259 " logarithmic scaling with number of packets)"10260 "You need to enable DSS mapping analysis for this option to work",10261 &mptcp_intersubflows_retransmission);10262 10263 register_conversation_table(proto_mptcp, FALSE(0), mptcpip_conversation_packet, tcpip_endpoint_packet);10264 register_follow_stream(proto_tcp, "tcp_follow", tcp_follow_conv_filter, tcp_follow_index_filter, tcp_follow_address_filter,10265 tcp_port_to_display, follow_tcp_tap_listener, get_tcp_stream_count, NULL((void*)0));10266}10267 10268void10269proto_reg_handoff_tcp(void)10270{10271 dissector_add_uint("ip.proto", IP_PROTO_TCP6, tcp_handle);10272 dissector_add_for_decode_as_with_preference("udp.port", tcp_handle);10273 data_handle = find_dissector("data");10274 sport_handle = find_dissector("sport");10275 tcp_tap = register_tap("tcp");10276 tcp_follow_tap = register_tap("tcp_follow");10277 10278 capture_dissector_add_uint("ip.proto", IP_PROTO_TCP6, tcp_cap_handle);10279 10280 /* Create dissection function handles for all TCP options */10281 dissector_add_uint("tcp.option", TCPOPT_TIMESTAMP8, create_dissector_handle( dissect_tcpopt_timestamp, proto_tcp_option_timestamp ));10282 dissector_add_uint("tcp.option", TCPOPT_MSS2, create_dissector_handle( dissect_tcpopt_mss, proto_tcp_option_mss ));10283 dissector_add_uint("tcp.option", TCPOPT_WINDOW3, create_dissector_handle( dissect_tcpopt_wscale, proto_tcp_option_wscale ));10284 dissector_add_uint("tcp.option", TCPOPT_SACK_PERM4, create_dissector_handle( dissect_tcpopt_sack_perm, proto_tcp_option_sack_perm ));10285 dissector_add_uint("tcp.option", TCPOPT_SACK5, create_dissector_handle( dissect_tcpopt_sack, proto_tcp_option_sack ));10286 dissector_add_uint("tcp.option", TCPOPT_ECHO6, create_dissector_handle( dissect_tcpopt_echo, proto_tcp_option_echo ));10287 dissector_add_uint("tcp.option", TCPOPT_ECHOREPLY7, create_dissector_handle( dissect_tcpopt_echo, proto_tcp_option_echoreply ));10288 dissector_add_uint("tcp.option", TCPOPT_CC11, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc ));10289 dissector_add_uint("tcp.option", TCPOPT_CCNEW12, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc_new ));10290 dissector_add_uint("tcp.option", TCPOPT_CCECHO13, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc_echo ));10291 dissector_add_uint("tcp.option", TCPOPT_MD519, create_dissector_handle( dissect_tcpopt_md5, proto_tcp_option_md5 ));10292 dissector_add_uint("tcp.option", TCPOPT_AO29, create_dissector_handle( dissect_tcpopt_ao, proto_tcp_option_ao ));10293 dissector_add_uint("tcp.option", TCPOPT_SCPS20, create_dissector_handle( dissect_tcpopt_scps, proto_tcp_option_scps ));10294 dissector_add_uint("tcp.option", TCPOPT_SNACK21, create_dissector_handle( dissect_tcpopt_snack, proto_tcp_option_snack ));10295 dissector_add_uint("tcp.option", TCPOPT_RECBOUND22, create_dissector_handle( dissect_tcpopt_recbound, proto_tcp_option_scpsrec ));10296 dissector_add_uint("tcp.option", TCPOPT_CORREXP23, create_dissector_handle( dissect_tcpopt_correxp, proto_tcp_option_scpscor ));10297 dissector_add_uint("tcp.option", TCPOPT_QS27, create_dissector_handle( dissect_tcpopt_qs, proto_tcp_option_qs ));10298 dissector_add_uint("tcp.option", TCPOPT_USER_TO28, create_dissector_handle( dissect_tcpopt_user_to, proto_tcp_option_user_to ));10299 dissector_add_uint("tcp.option", TCPOPT_TFO34, create_dissector_handle( dissect_tcpopt_tfo, proto_tcp_option_tfo ));10300 dissector_add_uint("tcp.option", TCPOPT_RVBD_PROBE76, create_dissector_handle( dissect_tcpopt_rvbd_probe, proto_tcp_option_rvbd_probe ));10301 dissector_add_uint("tcp.option", TCPOPT_RVBD_TRPY78, create_dissector_handle( dissect_tcpopt_rvbd_trpy, proto_tcp_option_rvbd_trpy ));10302 dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_00xac, create_dissector_handle( dissect_tcpopt_acc_ecn, proto_tcp_option_acc_ecn ));10303 dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_10xae, create_dissector_handle( dissect_tcpopt_acc_ecn, proto_tcp_option_acc_ecn ));10304 dissector_add_uint("tcp.option", TCPOPT_EXP_FD0xfd, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp ));10305 dissector_add_uint("tcp.option", TCPOPT_EXP_FE0xfe, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp ));10306 dissector_add_uint("tcp.option", TCPOPT_MPTCP30, create_dissector_handle( dissect_tcpopt_mptcp, proto_mptcp ));10307 /* Common handle for all the unknown/unsupported TCP options */10308 tcp_opt_unknown_handle = create_dissector_handle( dissect_tcpopt_unknown, proto_tcp_option_unknown );10309 10310 mptcp_tap = register_tap("mptcp");10311 exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4"OSI layer 4");10312 10313 proto_ip = proto_get_id_by_filter_name("ip");10314 proto_icmp = proto_get_id_by_filter_name("icmp");10315}10316 10317/*10318 * Editor modelines10319 *10320 * Local Variables:10321 * c-basic-offset: 410322 * tab-width: 810323 * indent-tabs-mode: nil10324 * End:10325 *10326 * ex: set shiftwidth=4 tabstop=8 expandtab:10327 * :indentSize=4:tabSize=8:noTabs=true:10328 */
/builds/wireshark/wireshark/epan/dissectors/packet-tcp.c (2024)
Top Articles
Latest Posts
Article information

Author: Dr. Pierre Goyette

Last Updated:

Views: 6430

Rating: 5 / 5 (50 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Dr. Pierre Goyette

Birthday: 1998-01-29

Address: Apt. 611 3357 Yong Plain, West Audra, IL 70053

Phone: +5819954278378

Job: Construction Director

Hobby: Embroidery, Creative writing, Shopping, Driving, Stand-up comedy, Coffee roasting, Scrapbooking

Introduction: My name is Dr. Pierre Goyette, I am a enchanting, powerful, jolly, rich, graceful, colorful, zany person who loves writing and wants to share my knowledge and understanding with you.