From e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 22:34:10 +0200 Subject: Adding upstream version 4.2.2. Signed-off-by: Daniel Baumann --- epan/dissectors/packet-tcp.h | 572 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 572 insertions(+) create mode 100644 epan/dissectors/packet-tcp.h (limited to 'epan/dissectors/packet-tcp.h') diff --git a/epan/dissectors/packet-tcp.h b/epan/dissectors/packet-tcp.h new file mode 100644 index 00000000..52205051 --- /dev/null +++ b/epan/dissectors/packet-tcp.h @@ -0,0 +1,572 @@ +/* packet-tcp.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __PACKET_TCP_H__ +#define __PACKET_TCP_H__ + +#include "ws_symbol_export.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* TCP flags */ +#define TH_FIN 0x0001 +#define TH_SYN 0x0002 +#define TH_RST 0x0004 +#define TH_PUSH 0x0008 +#define TH_ACK 0x0010 +#define TH_URG 0x0020 +#define TH_ECE 0x0040 +#define TH_CWR 0x0080 +#define TH_AE 0x0100 +#define TH_RES 0x0E00 /* 3 reserved bits */ +#define TH_MASK 0x0FFF + +#define IS_TH_FIN(x) (x & TH_FIN) +#define IS_TH_URG(x) (x & TH_URG) + +/* Idea for gt: either x > y, or y is much bigger (assume wrap) */ +#define GT_SEQ(x, y) ((gint32)((y) - (x)) < 0) +#define LT_SEQ(x, y) ((gint32)((x) - (y)) < 0) +#define GE_SEQ(x, y) ((gint32)((y) - (x)) <= 0) +#define LE_SEQ(x, y) ((gint32)((x) - (y)) <= 0) +#define EQ_SEQ(x, y) (x) == (y) + +/* mh as in mptcp header */ +struct mptcpheader { + + gboolean mh_mpc; /* true if seen an mp_capable option */ + gboolean mh_join; /* true if seen an mp_join option */ + gboolean mh_dss; /* true if seen a dss */ + gboolean mh_add; /* true if seen an MP_ADD */ + gboolean mh_remove; /* true if seen an MP_REMOVE */ + gboolean mh_prio; /* true if seen an MP_PRIO */ + gboolean mh_fail; /* true if seen an MP_FAIL */ + gboolean mh_fastclose; /* true if seen a fastclose */ + gboolean mh_tcprst; /* true if seen a MP_TCPRST */ + + guint8 mh_capable_flags; /* to get hmac version for instance */ + guint8 mh_dss_flags; /* data sequence signal flag */ + guint32 mh_dss_ssn; /* DSS Subflow Sequence Number */ + guint64 mh_dss_rawdsn; /* DSS Data Sequence Number */ + guint64 mh_dss_rawack; /* DSS raw data ack */ + guint16 mh_dss_length; /* mapping/DSS length */ + + guint64 mh_key; /* Sender key in MP_CAPABLE */ + guint32 mh_token; /* seen in MP_JOIN. Should be a hash of the initial key */ + + guint32 mh_stream; /* this stream index field is included to help differentiate when address/port pairs are reused */ + + /* Data Sequence Number of the current segment. It needs to be computed from previous mappings + * and as such is not necessarily set + */ + guint64 mh_rawdsn64; + /* DSN formatted according to the wireshark MPTCP options */ + guint64 mh_dsn; +}; + +/* the tcp header structure, passed to tap listeners */ +typedef struct tcpheader { + guint32 th_rawseq; /* raw value */ + guint32 th_seq; /* raw or relative value depending on tcp_relative_seq */ + + guint32 th_rawack; /* raw value */ + guint32 th_ack; /* raw or relative value depending on tcp_relative_seq */ + gboolean th_have_seglen; /* TRUE if th_seglen is valid */ + guint32 th_seglen; /* in bytes */ + guint32 th_win; /* make it 32 bits so we can handle some scaling */ + guint16 th_sport; + guint16 th_dport; + guint8 th_hlen; + gboolean th_use_ace; + guint16 th_flags; + guint32 th_stream; /* this stream index field is included to help differentiate when address/port pairs are reused */ + address ip_src; + address ip_dst; + + /* This is the absolute maximum we could find in TCP options (RFC2018, section 3) */ + #define MAX_TCP_SACK_RANGES 4 + guint8 num_sack_ranges; + guint32 sack_left_edge[MAX_TCP_SACK_RANGES]; + guint32 sack_right_edge[MAX_TCP_SACK_RANGES]; + + /* header for TCP option Multipath Operation */ + struct mptcpheader *th_mptcp; +} tcp_info_t; + +/* + * Private data passed from the TCP dissector to subdissectors. + * NOTE: This structure is used by Export PDU functionality so + * make sure that handling is also updated if this structure + * changes! + */ +struct tcpinfo { + guint32 seq; /* Sequence number of first byte in the data */ + guint32 nxtseq; /* Sequence number of first byte after data */ + guint32 lastackseq; /* Sequence number of last ack */ + gboolean is_reassembled; /* This is reassembled data. */ + guint16 flags; /* TCP flags */ + guint16 urgent_pointer; /* Urgent pointer value for the current packet. */ +}; + +/* + * Loop for dissecting PDUs within a TCP stream; assumes that a PDU + * consists of a fixed-length chunk of data that contains enough information + * to determine the length of the PDU, followed by rest of the PDU. + * + * The first three arguments are the arguments passed to the dissector + * that calls this routine. + * + * "proto_desegment" is the dissector's flag controlling whether it should + * desegment PDUs that cross TCP segment boundaries. + * + * "fixed_len" is the length of the fixed-length part of the PDU. + * + * "get_pdu_len()" is a routine called to get the length of the PDU from + * the fixed-length part of the PDU; it's passed "pinfo", "tvb", "offset" and + * "dissector_data". + * + * "dissect_pdu()" is the routine to dissect a PDU. + */ +WS_DLL_PUBLIC void +tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + gboolean proto_desegment, guint fixed_len, + guint (*get_pdu_len)(packet_info *, tvbuff_t *, int, void*), + dissector_t dissect_pdu, void* dissector_data); + +extern const reassembly_table_functions +tcp_reassembly_table_functions; + +extern struct tcp_multisegment_pdu * +pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, wmem_tree_t *multisegment_pdus); + +typedef struct _tcp_unacked_t { + struct _tcp_unacked_t *next; + guint32 frame; + guint32 seq; + guint32 nextseq; + nstime_t ts; +} tcp_unacked_t; + +struct tcp_acked { + guint32 frame_acked; + nstime_t ts; + + guint32 rto_frame; + nstime_t rto_ts; /* Time since previous packet for + retransmissions. */ + guint16 flags; /* see TCP_A_* in packet-tcp.c */ + guint32 dupack_num; /* dup ack number */ + guint32 dupack_frame; /* dup ack to frame # */ + guint32 bytes_in_flight; /* number of bytes in flight */ + guint32 push_bytes_sent; /* bytes since the last PSH flag */ + + guint32 new_data_seq; /* For segments with old data, + where new data starts */ +}; + +/* One instance of this structure is created for each pdu that spans across + * multiple tcp segments. + */ +struct tcp_multisegment_pdu { + guint32 seq; + guint32 nxtpdu; + guint32 first_frame; /* The frame where this MSP was created (used as key in reassembly tables). */ + guint32 last_frame; + nstime_t last_frame_time; + guint32 first_frame_with_seq; /* The frame that contains the first frame that matches 'seq' + (same as 'first_frame', larger than 'first_frame' for OoO segments) */ + guint32 flags; +#define MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT 0x00000001 +/* Whether this MSP is finished and no more segments can be added. */ +#define MSP_FLAGS_GOT_ALL_SEGMENTS 0x00000002 +/* Whether the first segment of this MSP was not yet seen. */ +#define MSP_FLAGS_MISSING_FIRST_SEGMENT 0x00000004 +}; + + +/* Represents the MPTCP DSS option mapping part + It allows to map relative subflow sequence number (ssn) to global MPTCP sequence numbers + under their 64 bits form +*/ +typedef struct _mptcp_dss_mapping_t { + +/* In DSS, SSN are enumeratad with relative seq_nb, i.e. starting from 0 */ + + guint32 ssn_low; + guint32 ssn_high; + +/* Ideally the dsn should always be registered with the extended version + * but it may not be possible if we don't know the 32 MSB of the base_dsn + */ + gboolean extended_dsn; /* TRUE if MPTCP_DSS_FLAG_DATA_8BYTES */ + + guint64 rawdsn; /* matches the low member of range + should be converted to the 64 bits version before being registered + */ +/* to check if mapping was sent before or after packet */ +guint32 frame; +} mptcp_dss_mapping_t; + + +/* Structure used in mptcp meta member 'dsn_map' + */ +typedef struct _mptcp_dsn2packet_mapping_t { + guint32 frame; /* packet to look into PINFO_FD_NUM */ + struct tcp_analysis* subflow; /* in order to get statistics */ +} mptcp_dsn2packet_mapping_t; + + +/* Should basically look like a_tcp_flow_t but for mptcp with 64bit sequence number. +The meta is specific to a direction of the communication and aggregates information of +all the subflows +*/ +typedef struct _mptcp_meta_flow_t { + + guint8 static_flags; /* remember which fields are set */ + + /* flags exchanged between hosts during 3WHS. Gives checksum/extensiblity/hmac information */ + guint8 flags; + guint64 base_dsn; /* first data seq number (used by relative sequence numbers) seen. */ + guint64 nextseq; /* highest seen nextseq */ + guint64 dfin; /* data fin */ + + guint8 version; /* negociated mptcp version */ + + guint64 key; /* if it was set */ + + /* expected token sha1 digest of keys, truncated to 32 most significant bits + derived from key. Stored to speed up subflow/MPTCP connection mapping */ + guint32 token; + + guint32 nextseqframe; /* frame number for segment with highest sequence number */ + + /* highest seen continuous seq number (without hole in the stream) */ + guint64 maxseqtobeacked; + + guint64 fin; /* frame number of the final dataFIN */ + + /* first addresses registered */ + address ip_src; + address ip_dst; + guint32 sport; + guint32 dport; +} mptcp_meta_flow_t; + +/* MPTCP data specific to this subflow direction */ +struct mptcp_subflow { + guint8 static_flags; /* flags stating which of the flow */ + guint32 nonce; /* used only for MP_JOIN */ + guint8 address_id; /* sent during an MP_JOIN */ + + + /* map DSN to packets + * Used when looking for reinjections across subflows + */ + wmem_itree_t *dsn2packet_map; + + /* Map SSN to a DSS mappings + * a DSS can map DSN to SSNs possibily over several packets, + * hence some packets may have been mapped by previous DSS, + * whence the necessity to be able to look for SSN -> DSN */ + wmem_itree_t *ssn2dsn_mappings; + /* meta flow to which it is attached. Helps setting forward and backward meta flow */ + mptcp_meta_flow_t *meta; +}; + + +typedef enum { + MPTCP_HMAC_NOT_SET = 0, + /* this is either SHA1 for MPTCP v0 or sha256 for MPTCP v1 */ + MPTCP_HMAC_SHA = 1, + MPTCP_HMAC_LAST +} mptcp_hmac_algorithm_t; + + +#define MPTCP_CAPABLE_CRYPTO_MASK 0x3F + +#define MPTCP_CHECKSUM_MASK 0x80 + +/* Information in a flow that is only used when tcp_analyze_seq preference + * is enabled, so save the memory when it isn't + */ +typedef struct tcp_analyze_seq_flow_info_t { + tcp_unacked_t *segments;/* List of segments for which we haven't seen an ACK */ + guint16 segment_count; /* How many unacked segments we're currently storing */ + guint32 lastack; /* Last seen ack for the reverse flow */ + nstime_t lastacktime; /* Time of the last ack packet */ + guint32 lastnondupack; /* frame number of last seen non dupack */ + guint32 dupacknum; /* dupack number */ + guint32 nextseq; /* highest seen nextseq */ + guint32 maxseqtobeacked;/* highest seen continuous seq number (without hole in the stream) from the fwd party, + * this is the maximum seq number that can be acked by the rev party in normal case. + * If the rev party sends an ACK beyond this seq number it indicates TCP_A_ACK_LOST_PACKET condition */ + guint32 nextseqframe; /* frame number for segment with highest + * sequence number + */ + nstime_t nextseqtime; /* Time of the nextseq packet so we can + * distinguish between retransmission, + * fast retransmissions and outoforder + */ + + guint8 lastacklen; /* length of the last fwd ACK packet - 0 means pure ACK */ + + /* + * Handling of SACK blocks + * Copied from tcpheader + */ + guint8 num_sack_ranges; + guint32 sack_left_edge[MAX_TCP_SACK_RANGES]; + guint32 sack_right_edge[MAX_TCP_SACK_RANGES]; + +} tcp_analyze_seq_flow_info_t; + + /* Process info, currently discovered via IPFIX */ +typedef struct tcp_process_info_t { + guint32 process_uid; /* UID of local process */ + guint32 process_pid; /* PID of local process */ + gchar *username; /* Username of the local process */ + gchar *command; /* Local process name + path + args */ + +} tcp_process_info_t; + +typedef struct _tcp_flow_t { + guint8 static_flags; /* true if base seq set */ + guint32 base_seq; /* base seq number (used by relative sequence numbers)*/ +#define TCP_MAX_UNACKED_SEGMENTS 10000 /* The most unacked segments we'll store */ + guint32 fin; /* frame number of the final FIN */ + guint32 window; /* last seen window */ + gint16 win_scale; /* -1 is we don't know, -2 is window scaling is not used */ + gint16 scps_capable; /* flow advertised scps capabilities */ + guint16 maxsizeacked; /* 0 if not yet known */ + gboolean valid_bif; /* if lost pkts, disable BiF until ACK is recvd */ + guint32 push_bytes_sent; /* bytes since the last PSH flag */ + gboolean push_set_last; /* tracking last time PSH flag was set */ + guint8 mp_operations; /* tracking of the MPTCP operations */ + gboolean is_first_ack; /* indicates if this is the first ACK */ + gboolean closing_initiator; /* tracking who is responsible of the connection end */ + + tcp_analyze_seq_flow_info_t* tcp_analyze_seq_info; + +/* This tcp flow/session contains only one single PDU and should + * be reassembled until the final FIN segment. + */ +#define TCP_FLOW_REASSEMBLE_UNTIL_FIN 0x0001 + guint16 flags; + + /* see TCP_A_* in packet-tcp.c */ + guint32 lastsegmentflags; + + /* The next (largest) sequence number after all segments seen so far. + * Valid only on the first pass and used to handle out-of-order segments + * during reassembly. */ + guint32 maxnextseq; + + /* This tree is indexed by sequence number and keeps track of all + * all pdus spanning multiple segments for this flow. + */ + wmem_tree_t *multisegment_pdus; + + /* A sorted list of pending out-of-order segments. */ + wmem_list_t *ooo_segments; + + /* Process info, currently discovered via IPFIX */ + tcp_process_info_t* process_info; + + /* MPTCP subflow intel */ + struct mptcp_subflow *mptcp_subflow; +} tcp_flow_t; + +/* Stores common information between both hosts of the MPTCP connection*/ +struct mptcp_analysis { + + guint16 mp_flags; /* MPTCP meta analysis related, see MPTCP_META_* in packet-tcp.c */ + + /* + * For other subflows, they link the meta via mptcp_subflow_t::meta_flow + * according to the validity of the token. + */ + mptcp_meta_flow_t meta_flow[2]; + + guint32 stream; /* Keep track of unique mptcp stream (per MP_CAPABLE handshake) */ + guint8 hmac_algo; /* hmac decided after negociation */ + wmem_list_t* subflows; /* List of subflows (tcp_analysis) */ + + /* identifier of the tcp stream that saw the initial 3WHS with MP_CAPABLE option */ + struct tcp_analysis *master; + + /* Keep track of the last TCP operations seen in order to avoid false DUP ACKs */ + guint8 mp_operations; +}; + +struct tcp_analysis { + /* These two structs are managed based on comparing the source + * and destination addresses and, if they're equal, comparing + * the source and destination ports. + * + * If the source is greater than the destination, then stuff + * sent from src is in ual1. + * + * If the source is less than the destination, then stuff + * sent from src is in ual2. + * + * XXX - if the addresses and ports are equal, we don't guarantee + * the behavior. + */ + tcp_flow_t flow1; + tcp_flow_t flow2; + + /* These pointers are set by get_tcp_conversation_data() + * fwd point in the same direction as the current packet + * and rev in the reverse direction + */ + tcp_flow_t *fwd; + tcp_flow_t *rev; + + /* This pointer is NULL or points to a tcp_acked struct if this + * packet has "interesting" properties such as being a KeepAlive or + * similar + */ + struct tcp_acked *ta; + /* This structure contains a tree containing all the various ta's + * keyed by frame number. + */ + wmem_tree_t *acked_table; + + /* Remember the timestamp of the first frame seen in this tcp + * conversation to be able to calculate a relative time compared + * to the start of this conversation + */ + nstime_t ts_first; + + /* Remember the timestamp of the most recent SYN in this conversation in + * order to calculate the first_rtt below. Not necessarily ts_first, if + * the SYN is retransmitted. */ + nstime_t ts_mru_syn; + + /* If we have the handshake, remember the RTT between the initial SYN + * and ACK for use detecting out-of-order segments. */ + nstime_t ts_first_rtt; + + /* Remember the timestamp of the frame that was last seen in this + * tcp conversation to be able to calculate a delta time compared + * to previous frame in this conversation + */ + nstime_t ts_prev; + + /* Keep track of tcp stream numbers instead of using the conversation + * index (as how it was done before). This prevents gaps in the + * stream index numbering + */ + guint32 stream; + + /* Remembers the server port on the SYN (or SYN|ACK) packet to + * help determine which dissector to call + */ + guint16 server_port; + + /* Set when the client sends a SYN with data and the cookie in the Fast Open + * option. + */ + guint8 tfo_syn_data : 1; + + /* allocated only when mptcp enabled + * several tcp_analysis may refer to the same mptcp_analysis + * can exist without any meta + */ + struct mptcp_analysis* mptcp_analysis; + + /* Track the TCP conversation completeness, as the capture might + * contain all parts of a TCP flow (establishment, data, clearing) or + * just some parts if we jumped on the bandwagon of an already established + * connection or left before it was terminated explicitly + */ + guint8 conversation_completeness; + + /* Stores the value as a String to be displayed in the appropriate field */ + gchar *conversation_completeness_str; + + /* Track AccECN support */ + gboolean had_acc_ecn_setup_syn; + gboolean had_acc_ecn_setup_syn_ack; + gboolean had_acc_ecn_option; +}; + +/* Structure that keeps per packet data. First used to be able + * to calculate the time_delta from the last seen frame in this + * TCP conversation. Can be extended for future use. + */ +struct tcp_per_packet_data_t { + nstime_t ts_del; + guint8 tcp_snd_manual_analysis; +}; + +/* Structure that keeps per packet data. Some operations are cpu-intensive and are + * best cached into this structure + */ +typedef struct mptcp_per_packet_data_t_ { + + /* Mapping that covers this packet content */ + mptcp_dss_mapping_t *mapping; + +} mptcp_per_packet_data_t; + + +WS_DLL_PUBLIC void dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, + guint32 seq, guint32 nxtseq, guint32 sport, + guint32 dport, proto_tree *tree, + proto_tree *tcp_tree, + struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo); + +WS_DLL_PUBLIC struct tcp_analysis *get_tcp_conversation_data(conversation_t *conv, + packet_info *pinfo); + +WS_DLL_PUBLIC gboolean decode_tcp_ports(tvbuff_t *, int, packet_info *, proto_tree *, int, int, struct tcp_analysis *, struct tcpinfo *); + +/** Associate process information with a given flow + * + * @param frame_num The frame number + * @param local_addr The local IPv4 or IPv6 address of the process + * @param remote_addr The remote IPv4 or IPv6 address of the process + * @param local_port The local TCP port of the process + * @param remote_port The remote TCP port of the process + * @param uid The numeric user ID of the process + * @param pid The numeric PID of the process + * @param username Ephemeral string containing the full or partial process name + * @param command Ephemeral string containing the full or partial process name + */ +extern void add_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); + +/** Get the current number of TCP streams + * + * @return The number of TCP streams + */ +WS_DLL_PUBLIC guint32 get_tcp_stream_count(void); + +/** Get the current number of MPTCP streams + * + * @return The number of MPTCP streams + */ +WS_DLL_PUBLIC guint32 get_mptcp_stream_count(void); + +/* Follow Stream functionality shared with HTTP (and SSL?) */ +extern gchar *tcp_follow_conv_filter(epan_dissect_t *edt, packet_info *pinfo, guint *stream, guint *sub_stream); +extern gchar *tcp_follow_index_filter(guint stream, guint sub_stream); +extern gchar *tcp_follow_address_filter(address *src_addr, address *dst_addr, int src_port, int dst_port); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif -- cgit v1.2.3