aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-iperf.c
blob: 40f39adca47650fad430b68bba4b63604f312bf8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/* packet-iperf.c
 * Routines for iPerf dissection
 * By Anish Bhatt <anish@gatech.edu>
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "config.h"
#include <epan/packet.h>

#define IPERF2_HDR_SIZE 24
#define IPERF2_UDP_HDR_SIZE 12

void proto_register_iperf2(void);
void proto_reg_handoff_iperf2(void);

static int proto_iperf2 = -1;

static int hf_iperf2_sequence = -1;
static int hf_iperf2_sec = -1;
static int hf_iperf2_usec = -1;
static int hf_iperf2_flags = -1;
static int hf_iperf2_num_threads = -1;
static int hf_iperf2_mport = -1;
static int hf_iperf2_bufferlen = -1;
static int hf_iperf2_mwinband = -1;
static int hf_iperf2_mamount = -1;

static gint ett_iperf2 = -1;
static gint ett_udphdr = -1;
static gint ett_client_hdr = -1;

static dissector_handle_t iperf2_handle_tcp = NULL;
static dissector_handle_t iperf2_handle_udp = NULL;


static int
dissect_iperf2(tvbuff_t *tvb, proto_tree *iperf2_tree, guint32 offset)
{
    proto_tree *client_tree;

    client_tree = proto_tree_add_subtree(iperf2_tree, tvb, offset, IPERF2_HDR_SIZE, ett_client_hdr, NULL, "iPerf2 Client Header");
    proto_tree_add_item(client_tree, hf_iperf2_flags, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    proto_tree_add_item(client_tree, hf_iperf2_num_threads, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    proto_tree_add_item(client_tree, hf_iperf2_mport, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    proto_tree_add_item(client_tree, hf_iperf2_bufferlen, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    proto_tree_add_item(client_tree, hf_iperf2_mwinband, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    proto_tree_add_item(client_tree, hf_iperf2_mamount, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;

    return offset;
}

static int
dissect_iperf2_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
{
    proto_item *ti;
    proto_tree *iperf2_tree;

    /*There is probably a better way to do this, for now ignore any TCP packet with payload
     > 24 bytes as only the first packet with a 24 byte payload has iperf headers. One way might
     be to check header flags, as there are only two possible values */
    if (tvb_reported_length(tvb) > IPERF2_HDR_SIZE)
        return 0;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "iPerf2");
    /* Clear out stuff in the info column */
    col_clear(pinfo->cinfo, COL_INFO);

    ti = proto_tree_add_item(tree, proto_iperf2, tvb, 0, IPERF2_HDR_SIZE, ENC_NA);
    iperf2_tree = proto_item_add_subtree(ti, ett_iperf2);

    return dissect_iperf2(tvb, iperf2_tree, 0);
}

static int
dissect_iperf2_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
{
    guint32 offset = 0;
    guint32 hdr_size = IPERF2_HDR_SIZE + IPERF2_UDP_HDR_SIZE;
    proto_item *ti;
    proto_tree *iperf2_tree, *udp_tree;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "iPerf2");
    /* Clear out stuff in the info column */
    col_clear(pinfo->cinfo, COL_INFO);

    ti = proto_tree_add_item(tree, proto_iperf2, tvb, offset, hdr_size, ENC_NA);
    iperf2_tree = proto_item_add_subtree(ti, ett_iperf2);

    udp_tree = proto_tree_add_subtree(iperf2_tree, tvb, offset, IPERF2_UDP_HDR_SIZE, ett_udphdr, NULL, "iPerf2 UDP Header");

    proto_tree_add_item(udp_tree, hf_iperf2_sequence, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    proto_tree_add_item(udp_tree, hf_iperf2_sec, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    proto_tree_add_item(udp_tree, hf_iperf2_usec, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;

    return dissect_iperf2(tvb, iperf2_tree, offset);
}

void
proto_register_iperf2(void)
{
    /* Setup list of header fields */
    static hf_register_info hf[] = {
        { &hf_iperf2_sequence,
            { "iPerf2 sequence", "iperf2.udp.sequence", FT_INT32, BASE_DEC,
            NULL, 0, NULL, HFILL }
        },
        { &hf_iperf2_sec,
            { "iPerf2 sec", "iperf2.udp.sec", FT_UINT32, BASE_DEC,
            NULL, 0, NULL, HFILL }
        },
        { &hf_iperf2_usec,
            { "iPerf2 usec", "iperf2.udp.usec", FT_UINT32, BASE_DEC,
            NULL, 0, NULL, HFILL }
        },
        { &hf_iperf2_flags,
            { "Flags", "iperf2.client.flags", FT_UINT32, BASE_DEC,
            NULL, 0, NULL, HFILL }
        },
        { &hf_iperf2_num_threads,
            { "Number of Threads", "iperf2.client.numthreads", FT_UINT32, BASE_DEC,
            NULL, 0, NULL, HFILL }
        },
        { &hf_iperf2_mport,
            { "Server Port", "iperf2.client.port", FT_UINT32, BASE_DEC,
            NULL, 0, NULL, HFILL }
        },
        { &hf_iperf2_bufferlen,
            { "Buffer Len", "iperf2.client.bufferlen", FT_UINT32, BASE_DEC,
            NULL, 0, NULL, HFILL }
        },
        { &hf_iperf2_mwinband,
            { "Bandwidth", "iperf2.client.bandwidth", FT_UINT32, BASE_HEX,
            NULL, 0, NULL, HFILL }
        },
        { &hf_iperf2_mamount,
            { "Number of Bytes", "iperf2.client.num_bytes", FT_UINT32, BASE_HEX,
            NULL, 0, NULL, HFILL }
        },
    };

    /* Setup protocol subtree array */
    static gint *ett[] = {
        &ett_iperf2,
        &ett_udphdr,
        &ett_client_hdr
    };

    /* Register the protocol name and description */
    proto_iperf2 = proto_register_protocol("iPerf2 Packet Data", "iPerf2", "iperf2");

    proto_register_field_array(proto_iperf2, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));

    iperf2_handle_tcp = register_dissector("iperf2_tcp", dissect_iperf2_tcp, proto_iperf2);
    iperf2_handle_udp = register_dissector("iperf2_udp", dissect_iperf2_udp, proto_iperf2);
}

void
proto_reg_handoff_iperf2(void)
{
    dissector_add_for_decode_as_with_preference("tcp.port", iperf2_handle_tcp);
    dissector_add_for_decode_as_with_preference("udp.port", iperf2_handle_udp);
}

/*
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 4
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 *
 * vi: set shiftwidth=4 tabstop=8 expandtab:
 * :indentSize=4:tabSize=8:noTabs=true:
 */