Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-ancp.c
Line
Count
Source
1
/* packet-ancp.c
2
 *
3
 * Dissector for ANCP - Access Node Control Protocol
4
 *
5
 * More info on the protocol can be found on IETF:
6
 * https://tools.ietf.org/wg/ancp/
7
 * https://tools.ietf.org/html/draft-ietf-ancp-protocol-09
8
 * https://tools.ietf.org/html/rfc6320
9
 * https://tools.ietf.org/html/rfc7256
10
 * https://www.iana.org/assignments/ancp/ancp.xhtml
11
 *
12
 * Copyright 2010, Aniruddha.A (anira@cisco.com)
13
 * Uli Heilmeier, 2017; Update to RFC6320; current IANA registry types
14
 *
15
 * Wireshark - Network traffic analyzer
16
 * By Gerald Combs <gerald@wireshark.org>
17
 * Copyright 1998 Gerald Combs
18
 *
19
 * SPDX-License-Identifier: GPL-2.0-or-later
20
 */
21
22
#include "config.h"
23
24
#include <epan/packet.h>
25
#include <epan/stats_tree.h>
26
#include <epan/tfs.h>
27
#include <epan/unit_strings.h>
28
#include <wsutil/ws_roundup.h>
29
#include "packet-tcp.h"
30
31
14
#define ANCP_PORT 6068 /* The ANCP TCP port */
32
33
4
#define ANCP_MIN_HDR  4
34
47
#define ANCP_GSMP_ETHER_TYPE  0x880C
35
0
#define TECH_TYPE_DSL         0x5
36
0
#define TECH_TYPE_PON         0x1
37
38
14
#define ANCP_RESULT_MASK     0xF0
39
14
#define ANCP_CODE_MASK       0x0FFF
40
14
#define ANCP_I_FLAG_MASK     0x80
41
14
#define ANCP_SUBMSG_MASK     0x7FFF
42
14
#define ADJ_CODE_MASK        0x7F /* excluding MSB M-Flag */
43
44
0
#define ANCP_MTYPE_ADJ       10
45
0
#define ANCP_MTYPE_PORT_MGMT 32
46
0
#define ANCP_MTYPE_PORT_UP   80
47
0
#define ANCP_MTYPE_PORT_DN   81
48
0
#define ANCP_MTYPE_ADJ_UPD   85
49
0
#define ANCP_MTYPE_GEN_RSP   91
50
0
#define ANCP_MTYPE_PROV      93
51
52
/* Topology Discovery Extensions */
53
0
#define TLV_DSL_LINE_ATTRIBUTES         0x04
54
0
#define TLV_DSL_LINE_STATE              0x8F
55
0
#define TLV_DSL_TYPE                    0x91
56
57
/* Port Management Extensions */
58
0
#define TLV_PING_PARAMS                 0x07
59
0
#define TLV_PING_OPAQUE_DATA            0x08
60
#define TLV_PING_RES_STR                0x09
61
62
void proto_register_ancp(void);
63
void proto_reg_handoff_ancp(void);
64
65
static dissector_handle_t ancp_handle;
66
67
static int hf_ancp_len;
68
static int hf_ancp_len2;
69
static int hf_ancp_ver;
70
static int hf_ancp_mtype;
71
static int hf_ancp_timer;
72
static int hf_ancp_adj_code;
73
static int hf_ancp_sender_name;
74
static int hf_ancp_receiver_name;
75
static int hf_ancp_sender_port;
76
static int hf_ancp_receiver_port;
77
static int hf_ancp_p_info;
78
static int hf_ancp_sender_instance;
79
static int hf_ancp_p_id;
80
static int hf_ancp_receiver_instance;
81
static int hf_ancp_tech_type;
82
static int hf_ancp_num_tlvs;
83
static int hf_ancp_tot_len;
84
static int hf_ancp_cap;
85
static int hf_ancp_result;
86
static int hf_ancp_code;
87
static int hf_ancp_trans_id;
88
static int hf_ancp_i_flag;
89
static int hf_ancp_submsg_num;
90
static int hf_ancp_pudm_unused;
91
static int hf_ancp_function;
92
static int hf_ancp_x_function;
93
static int hf_ancp_ext_flags_res;
94
static int hf_ancp_reserved;
95
static int hf_ancp_blk_len;
96
static int hf_ancp_num_ext_tlvs;
97
static int hf_ancp_ext_tlv_type;
98
static int hf_ancp_ext_tlv_len;
99
static int hf_ancp_dsl_line_stlv_type;
100
static int hf_ancp_dsl_line_stlv_len;
101
static int hf_ancp_dsl_line_stlv_value;
102
static int hf_ancp_ext_tlv_value_str;
103
static int hf_ancp_oam_opaque;
104
static int hf_ancp_oam_loopb_cnt;
105
static int hf_ancp_oam_timeout;
106
107
static int ett_ancp_len;
108
static int ett_ancp_ver;
109
static int ett_ancp_mtype;
110
static int ett_ancp_timer;
111
static int ett_ancp_adj_code;
112
static int ett_ancp_sender_name;
113
static int ett_ancp_receiver_name;
114
static int ett_ancp_sender_port;
115
static int ett_ancp_receiver_port;
116
static int ett_ancp_p_info;
117
static int ett_ancp_sender_instance;
118
static int ett_ancp_p_id;
119
static int ett_ancp_receiver_instance;
120
static int ett_ancp_tech_type;
121
static int ett_ancp_num_tlvs;
122
static int ett_ancp_tot_len;
123
static int ett_ancp_cap;
124
static int ett_ancp_result;
125
static int ett_ancp_code;
126
static int ett_ancp_trans_id;
127
static int ett_ancp_i_flag;
128
static int ett_ancp_submsg_num;
129
static int ett_ancp_port;
130
static int ett_ancp_port_sess_num;
131
static int ett_ancp_evt_seq_num;
132
static int ett_ancp_label;
133
static int ett_ancp_reserved;
134
static int ett_ancp_blk_len;
135
static int ett_ancp_num_ext_tlvs;
136
static int ett_ancp_ext_tlv_type;
137
static int ett_ancp_dsl_line_stlv_type;
138
static int ett_ancp_dsl_line_stlv_val;
139
static int ett_ancp_ext_tlv_value_str;
140
static int ett_ancp_oam_opaque;
141
static int ett_ancp_oam_loopb_cnt;
142
static int ett_ancp_oam_timeout;
143
144
static int proto_ancp;
145
146
/* ANCP stats - Tap interface */
147
static const char *st_str_packets        = "Total Packets";
148
static const char *st_str_packet_types   = "ANCP Packet Types";
149
static const char *st_str_adj_pack_types = "ANCP Adjacency Packet Types";
150
151
static int st_node_packets = -1;
152
static int st_node_packet_types = -1;
153
static int st_node_adj_pack_types = -1;
154
static int ancp_tap;
155
156
struct ancp_tap_t {
157
    int ancp_mtype;
158
    int ancp_adjcode; /* valid for ancp adjacency message only */
159
};
160
161
/* Value Strings */
162
static const value_string mtype_names[] = {
163
    {  10, "Adjacency" },
164
    {  32, "Port-Management" },
165
    {  80, "Port-Up" },
166
    {  81, "Port-Down" },
167
    {  85, "Adjacency Update" },
168
    {  91, "Generic Response" },
169
    {  93, "Provisioning" },
170
    { 144, "Multicast Replication Control" },
171
    { 145, "Multicast Admission Control" },
172
    { 146, "Bandwidth Reallocation Request" },
173
    { 147, "Bandwidth Transfer" },
174
    { 148, "Delegated Bandwidth Query" },
175
    { 149, "Multicast Flow Query" },
176
    { 150, "Committed Bandwidth Report" },
177
    {   0,  NULL }
178
};
179
180
static const value_string adj_code_names[] = {
181
    { 1, "Syn" },
182
    { 2, "SynAck" },
183
    { 3, "Ack" },
184
    { 4, "Rstack" },
185
    { 0,  NULL }
186
};
187
188
static const value_string captype_names[] = {
189
    { 1, "Dynamic-Topology-Discovery" },
190
    { 2, "Line-Configuration" },
191
    { 3, "Transactional-Multicast" },
192
    { 4, "OAM" },
193
    { 0,  NULL }
194
};
195
196
static const value_string resulttype_names[] = {
197
    { 0, "Ignore" },
198
    { 1, "NAck" },
199
    { 2, "AckAll" },
200
    { 3, "Success" },
201
    { 4, "Failure" },
202
    { 0,  NULL }
203
};
204
205
static const value_string codetype_names[] = {
206
    { 0x000, "No result" },
207
    { 0x002, "Invalid request message" },
208
    { 0x006, "One or more of the specified ports are down" },
209
    { 0x013, "Out of resources" },
210
    { 0x051, "Request message type not implemented" },
211
    { 0x053, "Malformed message" },
212
    { 0x054, "Mandatory TLV missing" },
213
    { 0x055, "Invalid TLV contents" },
214
    { 0x064, "Command error" },
215
    { 0x065, "Invalid flow address" },
216
    { 0x066, "Multicast flow does not exist" },
217
    { 0x067, "Invalid preferred bandwidth amount" },
218
    { 0x068, "Inconsistent views of delegated bandwidth amount" },
219
    { 0x069, "Bandwidth request conflict" },
220
    { 0x500, "One or more of the specified ports do not exist" },
221
    { 0x501, "Loopback test timed out" },
222
    { 0x502, "Reserved" },
223
    { 0x503, "DSL access line status showtime" },
224
    { 0x504, "DSL access line status idle" },
225
    { 0x505, "DSL access line status silent" },
226
    { 0x506, "DSL access line status training" },
227
    { 0x507, "DSL access line integrity error" },
228
    { 0x508, "DSLAM resource not available" },
229
    { 0x509, "Invalid test parameter" },
230
    { 0,  NULL }
231
};
232
233
static const value_string techtype_str[] = {
234
    { 0x00,  "Not technology dependent" },
235
    { 0x01,  "PON" },
236
    { 0x05,  "DSL" },
237
    { 0xFF,  "Reserved" },
238
    { 0,  NULL }
239
};
240
241
static const value_string dsl_line_attrs[] = {
242
    { 0x91,  "DSL-Type" },
243
    { 0x81,  "Actual-Net-Data-Rate-Upstream" },
244
    { 0x82,  "Actual-Net-Data-Rate-Downstream" },
245
    { 0x83,  "Minimum-Net-Data-Rate-Upstream" },
246
    { 0x84,  "Minimum-Net-Data-Rate-Downstream" },
247
    { 0x85,  "Attainable-Net-Data-Rate-Upstream" },
248
    { 0x86,  "Attainable-Net-Data-Rate-Downstream" },
249
    { 0x87,  "Maximum-Net-Data-Rate-Upstream" },
250
    { 0x88,  "Maximum-Net-Data-Rate-Downstream" },
251
    { 0x89,  "Minimum-Net-Low-Power-Data-Rate-Upstream" },
252
    { 0x8A,  "Minimum-Net-Low-Power-Data-Rate-Downstream" },
253
    { 0x8B,  "Maximum-Interleaving-Delay-Upstream" },
254
    { 0x8C,  "Actual-Interleaving-Delay-Upstream" },
255
    { 0x8D,  "Maximum-Interleaving-Delay-Downstream" },
256
    { 0x8E,  "Actual-Interleaving-Delay-Downstream" },
257
    { 0x8F,  "DSL line state" },
258
    { 0x90,  "Access Loop Encapsulation" },
259
    { 0,  NULL }
260
};
261
262
static const value_string dsl_line_attr_units[] = {
263
    { 0x91,  "" },
264
    { 0x81,  "Kb/sec" },
265
    { 0x82,  "Kb/sec" },
266
    { 0x83,  "Kb/sec" },
267
    { 0x84,  "Kb/sec" },
268
    { 0x85,  "Kb/sec" },
269
    { 0x86,  "Kb/sec" },
270
    { 0x87,  "Kb/sec" },
271
    { 0x88,  "Kb/sec" },
272
    { 0x89,  "Kb/sec" },
273
    { 0x8A,  "Kb/sec" },
274
    { 0x8B,  "msec" },
275
    { 0x8C,  "msec" },
276
    { 0x8D,  "msec" },
277
    { 0x8E,  "msec" },
278
    { 0x8F,  "" },
279
    { 0x90,  "" },
280
    { 0,  NULL }
281
};
282
283
static const value_string dsl_line_type_names[] = {
284
    { 1,  "ADSL1" },
285
    { 2,  "ADSL2" },
286
    { 3,  "ADSL2+" },
287
    { 4,  "VDSL1" },
288
    { 5,  "VDSL2" },
289
    { 6,  "SDSL" },
290
    { 0,  NULL }
291
};
292
293
static const value_string dsl_line_state_names[] = {
294
    { 1,  "Showtime" },
295
    { 2,  "Idle" },
296
    { 3,  "Silent" },
297
    { 0,  NULL }
298
};
299
300
static const value_string function_names[] = {
301
    { 0,  "Reserved" },
302
    { 8,  "Configure Connection Service Data" },
303
    { 9,  "Remote Loopback" },
304
    { 0,  NULL }
305
};
306
307
static const value_string ext_tlv_types[] = {
308
    { 0x0000, "Reserved" },
309
    { 0x0001, "Access-Loop-Circuit-ID" },
310
    { 0x0002, "Access-Loop-Remote-ID" },
311
    { 0x0003, "Access-Aggregation-Circuit-ID-ASCII" },
312
    { 0x0004, "DSL Line Attributes" },
313
    { 0x0005, "Service-Profile-Name" },
314
    { 0x0006, "Access-Aggregation-Circuit-ID-Binary" },
315
    { 0x0007, "OAM-Loopback-Test-Parameters" },
316
    { 0x0008, "Opaque-Data" },
317
    { 0x0009, "OAM-Loopback-Test-Response-String" },
318
    { 0x0011, "Command" },
319
    { 0x0013, "Multicast-Service-Profile" },
320
    { 0x0015, "Bandwidth-Allocation" },
321
    { 0x0016, "Bandwidth-Request" },
322
    { 0x0018, "Multicast-Service-Profile-Name" },
323
    { 0x0019, "Multicast-Flow" },
324
    { 0x0021, "List-Action" },
325
    { 0x0022, "Sequence-Number" },
326
    { 0x0024, "White-List-CAC" },
327
    { 0x0025, "MRepCtl-CAC" },
328
    { 0x0081, "Actual-Net-Data-Rate-Upstream" },
329
    { 0x0082, "Actual-Net-Data-Rate-Downstream" },
330
    { 0x0083, "Minimum-Net-Data-Rate-Upstream" },
331
    { 0x0084, "Minimum-Net-Data-Rate-Downstream" },
332
    { 0x0085, "Attainable-Net-Data-Rate-Upstream" },
333
    { 0x0086, "Attainable-Net-Data-Rate-Downstream" },
334
    { 0x0087, "Maximum-Net-Data-Rate-Upstream" },
335
    { 0x0088, "Maximum-Net-Data-Rate-Downstream" },
336
    { 0x0089, "Minimum-Net-Low-Power-Data-Rate-Upstream" },
337
    { 0x008A, "Minimum-Net-Low-Power-Data-Rate-Downstream" },
338
    { 0x008B, "Maximum-Interleaving-Delay-Upstream" },
339
    { 0x008C, "Actual-Interleaving-Delay-Upstream" },
340
    { 0x008D, "Maximum-Interleaving-Delay-Downstream" },
341
    { 0x008E, "Actual-Interleaving-Delay-Downstream" },
342
    { 0x008F, "DSL-Line-State" },
343
    { 0x0090, "Access-Loop-Encapsulation" },
344
    { 0x0091, "DSL-Type" },
345
    { 0x0092, "Request-Source-IP" },
346
    { 0x0093, "Request-Source-MAC" },
347
    { 0x0094, "Report-Buffering-Time" },
348
    { 0x0095, "Committed-Bandwidth" },
349
    { 0x0096, "Request-Source-Device-Id" },
350
    { 0x0106, "Status-Info" },
351
    { 0x1000, "Target (single access line variant)" },
352
    { 0,  NULL }
353
};
354
static value_string_ext ext_tlv_types_ext = VALUE_STRING_EXT_INIT(ext_tlv_types);
355
356
static int
357
dissect_ancp_tlv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tlv_tree, int offset)
358
0
{
359
0
        uint16_t    tlen, ttype;
360
0
        int16_t     num_stlvs;
361
0
        proto_item *tti;
362
363
0
            proto_tree_add_item_ret_uint16(tlv_tree, hf_ancp_ext_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN, &ttype);
364
0
            offset += 2;
365
366
0
            tti = proto_tree_add_item_ret_uint16(tlv_tree, hf_ancp_ext_tlv_len, tvb, offset, 2, ENC_BIG_ENDIAN, &tlen);
367
0
            offset += 2;
368
369
            /*
370
             * Extension Block is common for event message and port
371
             * management message, but the TLVs that can appear
372
             * are different
373
             */
374
0
            switch (ttype) {
375
0
                case TLV_DSL_LINE_ATTRIBUTES:
376
0
                {
377
0
                    proto_tree *dsl_tree;
378
0
                    uint16_t    stlvtype, stlvlen;
379
0
                    int         val;
380
381
                    /* Create a DSL Attribute SubTree */
382
0
                    dsl_tree = proto_item_add_subtree(tti, ett_ancp_ext_tlv_type);
383
0
                    num_stlvs = tlen / 8; /* TODO - better way? */
384
0
                    for ( ;num_stlvs; num_stlvs--) {
385
0
                        proto_tree_add_item(dsl_tree,
386
0
                                hf_ancp_dsl_line_stlv_type, tvb, offset,
387
0
                                2, ENC_BIG_ENDIAN);
388
0
                        stlvtype = tvb_get_ntohs(tvb, offset);
389
0
                        offset += 2;
390
0
                        proto_tree_add_item(dsl_tree,
391
0
                                hf_ancp_dsl_line_stlv_len, tvb, offset,
392
0
                                2, ENC_BIG_ENDIAN);
393
0
                        stlvlen = tvb_get_ntohs(tvb, offset);
394
0
                        offset += 2; /* Sub TLV Length */
395
396
0
                        tti = proto_tree_add_item(dsl_tree,
397
0
                                hf_ancp_dsl_line_stlv_value, tvb, offset,
398
0
                                stlvlen, ENC_BIG_ENDIAN);
399
0
                        val = tvb_get_ntohl(tvb, offset);
400
401
0
                        switch (stlvtype) {
402
0
                            case TLV_DSL_LINE_STATE:
403
0
                                proto_item_append_text(tti, " (%s)",
404
0
                                        val_to_str(pinfo->pool, val, dsl_line_state_names,
405
0
                                            "Unknown (0x%02x)"));
406
0
                                break;
407
0
                            case TLV_DSL_TYPE:
408
0
                                proto_item_append_text(tti, " (%s)",
409
0
                                        val_to_str(pinfo->pool, val, dsl_line_type_names,
410
0
                                            "Unknown (0x%02x)"));
411
0
                                break;
412
413
0
                            default:
414
                                /* Add Unit */
415
0
                                proto_item_append_text(tti, " %s",
416
0
                                        val_to_str(pinfo->pool, stlvtype,
417
0
                                            dsl_line_attr_units,
418
0
                                            "Unknown (0x%02x)"));
419
0
                                break;
420
0
                        }
421
0
                        offset += WS_ROUNDUP_4(stlvlen); /* Except loop-encap, rest are 4B */
422
0
                    }
423
0
                    break;
424
0
                }
425
0
                case TLV_PING_OPAQUE_DATA:
426
                    /* 2 32b values*/
427
0
                    proto_tree_add_item(tlv_tree, hf_ancp_oam_opaque,
428
0
                            tvb, offset, 4, ENC_BIG_ENDIAN);
429
0
                    offset += 4;
430
0
                    proto_tree_add_item(tlv_tree, hf_ancp_oam_opaque,
431
0
                            tvb, offset, 4, ENC_BIG_ENDIAN);
432
0
                    offset += 4;
433
0
                    break;
434
0
                case TLV_PING_PARAMS:
435
                    /* Count (1B) Timeout (1B), 2B empty */
436
0
                    proto_tree_add_item(tlv_tree,
437
0
                            hf_ancp_oam_loopb_cnt, tvb, offset, 1, ENC_BIG_ENDIAN);
438
0
                    offset += 1;
439
0
                    proto_tree_add_item(tlv_tree,
440
0
                            hf_ancp_oam_timeout, tvb, offset, 1, ENC_BIG_ENDIAN);
441
0
                    offset += 1;
442
                    /* Lets not bother about 2B until IETF WG figures out */
443
0
                    offset += 2;
444
0
                    break;
445
0
                default:
446
                    /* Assume TLV value is string - covers ALCID, OAM resp */
447
0
                    proto_tree_add_item(tlv_tree, hf_ancp_ext_tlv_value_str,
448
0
                            tvb, offset, tlen, ENC_ASCII);
449
0
                    offset += WS_ROUNDUP_4(tlen);
450
0
                    break;
451
0
            } /* end switch {ttype} */
452
0
            return offset;
453
0
}
454
455
static void
456
dissect_ancp_port_up_dn_mgmt(tvbuff_t *tvb, packet_info* pinfo, proto_tree *ancp_tree, int offset, uint8_t mtype)
457
0
{
458
0
    uint8_t tech_type;
459
0
    int16_t num_tlvs;
460
0
    proto_item *sti;
461
462
0
    if (mtype == ANCP_MTYPE_PORT_MGMT) {
463
0
        proto_tree_add_item(ancp_tree, hf_ancp_pudm_unused,    tvb, offset, 14, ENC_NA);
464
0
        offset += 14;
465
466
0
        proto_tree_add_item(ancp_tree, hf_ancp_function,       tvb, offset, 1, ENC_BIG_ENDIAN);
467
0
        offset += 1;
468
469
0
        proto_tree_add_item(ancp_tree, hf_ancp_x_function,     tvb, offset, 1, ENC_BIG_ENDIAN);
470
0
        offset += 1;
471
472
0
        proto_tree_add_item(ancp_tree, hf_ancp_pudm_unused,    tvb, offset, 4, ENC_NA);
473
0
        offset += 4;
474
0
    } else {
475
0
        proto_tree_add_item(ancp_tree, hf_ancp_pudm_unused,    tvb, offset, 20, ENC_NA);
476
0
        offset += 20;
477
0
    }
478
479
0
    proto_tree_add_item(ancp_tree, hf_ancp_ext_flags_res, tvb, offset, 1, ENC_NA);
480
0
    offset += 1;
481
482
0
    proto_tree_add_item(ancp_tree, hf_ancp_mtype,         tvb, offset, 1, ENC_BIG_ENDIAN);
483
0
    offset += 1;
484
485
0
    if (mtype == ANCP_MTYPE_PORT_MGMT) {
486
0
        proto_tree_add_item(ancp_tree, hf_ancp_reserved,      tvb, offset, 2, ENC_NA);
487
0
        offset += 2;
488
0
        tech_type = 0;
489
0
    } else {
490
0
        proto_tree_add_item_ret_uint8(ancp_tree, hf_ancp_tech_type,  tvb, offset, 1, ENC_BIG_ENDIAN, &tech_type);
491
0
        offset += 1;
492
493
0
        proto_tree_add_item(ancp_tree, hf_ancp_reserved,      tvb, offset, 1, ENC_NA);
494
0
        offset += 1;
495
0
    }
496
497
0
    proto_tree_add_item(ancp_tree, hf_ancp_num_ext_tlvs, tvb, offset, 2, ENC_BIG_ENDIAN);
498
0
    num_tlvs = tvb_get_ntohs(tvb, offset);
499
0
    offset += 2;
500
501
0
    sti = proto_tree_add_item(ancp_tree, hf_ancp_blk_len,       tvb, offset, 2, ENC_BIG_ENDIAN);
502
0
    offset += 2;
503
504
0
    if (tech_type == TECH_TYPE_DSL || tech_type == TECH_TYPE_PON) {
505
0
        proto_tree *tlv_tree;
506
507
        /* Create a TLV sub tree */
508
0
        tlv_tree = proto_item_add_subtree(sti, ett_ancp_len);
509
510
0
        for( ;num_tlvs; num_tlvs--) {
511
0
            offset = dissect_ancp_tlv(tvb, pinfo, tlv_tree, offset);
512
0
        } /* end for {numtlvs} */
513
0
    } /* end if {DSL} */
514
0
}
515
516
static void
517
dissect_ancp_adj_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ancp_tree,
518
                     int offset, struct ancp_tap_t *ancp_info
519
)
520
0
{
521
0
    proto_item *sti;
522
0
    proto_tree *ancp_cap_tree;
523
0
    uint8_t     byte, numcaps, adjcode;
524
0
    uint16_t    tlv_len;
525
526
0
    sti = proto_tree_add_item(ancp_tree, hf_ancp_timer, tvb, offset, 1,
527
0
            ENC_BIG_ENDIAN);
528
0
    offset += 1;
529
0
    proto_item_append_text(sti, " msec");
530
531
0
    sti = proto_tree_add_item(ancp_tree, hf_ancp_adj_code, tvb, offset, 1,
532
0
            ENC_BIG_ENDIAN);
533
0
    byte = tvb_get_uint8(tvb, offset);
534
0
    offset += 1;
535
0
    adjcode = byte & ADJ_CODE_MASK;
536
0
    ancp_info->ancp_adjcode = adjcode; /* stats */
537
0
    proto_item_append_text(sti, " (%s, M Flag %s)",
538
0
            val_to_str(pinfo->pool, adjcode, adj_code_names, "Unknown (0x%02x)"),
539
0
            (byte >> 7) ? "Set" : "Unset");
540
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
541
0
            val_to_str(pinfo->pool, adjcode, adj_code_names, "Unknown (0x%02x)"));
542
543
0
    proto_tree_add_item(ancp_tree, hf_ancp_sender_name, tvb, offset, 6, ENC_NA);
544
0
    offset += 6;
545
546
0
    proto_tree_add_item(ancp_tree, hf_ancp_receiver_name, tvb,offset, 6, ENC_NA);
547
0
    offset += 6;
548
549
0
    proto_tree_add_item(ancp_tree, hf_ancp_sender_port, tvb, offset, 4, ENC_BIG_ENDIAN);
550
0
    offset += 4;
551
552
0
    proto_tree_add_item(ancp_tree, hf_ancp_receiver_port, tvb,offset, 4, ENC_BIG_ENDIAN);
553
0
    offset += 4;
554
555
0
    sti = proto_tree_add_item(ancp_tree, hf_ancp_p_info, tvb,
556
0
            offset, 1, ENC_BIG_ENDIAN);
557
0
    byte = tvb_get_uint8(tvb, offset);
558
0
    offset += 1;
559
0
    proto_item_append_text(sti, " (Type = %d, Flag = %d)",
560
0
            byte >> 4, byte & 0x0F);
561
562
0
    proto_tree_add_item(ancp_tree, hf_ancp_sender_instance, tvb, offset, 3, ENC_BIG_ENDIAN);
563
0
    offset += 3;
564
565
0
    proto_tree_add_item(ancp_tree, hf_ancp_p_id, tvb, offset, 1, ENC_BIG_ENDIAN);
566
0
    offset += 1;
567
568
0
    proto_tree_add_item(ancp_tree, hf_ancp_receiver_instance, tvb, offset, 3, ENC_BIG_ENDIAN);
569
0
    offset += 3;
570
571
0
    proto_tree_add_item(ancp_tree, hf_ancp_reserved, tvb, offset, 1, ENC_NA);
572
0
    offset += 1;
573
574
0
    sti = proto_tree_add_item(ancp_tree, hf_ancp_num_tlvs, tvb, offset, 1, ENC_BIG_ENDIAN);
575
0
    numcaps = tvb_get_uint8(tvb, offset);
576
0
    offset += 1;
577
578
    /* Start the capability subtree */
579
0
    ancp_cap_tree = proto_item_add_subtree(sti, ett_ancp_tot_len);
580
581
0
    proto_tree_add_item(ancp_cap_tree, hf_ancp_tot_len, tvb, offset, 2, ENC_BIG_ENDIAN);
582
0
    offset += 2;
583
584
0
    for ( ;numcaps; numcaps--) {
585
0
        sti = proto_tree_add_item(ancp_cap_tree, hf_ancp_cap, tvb, offset, 2, ENC_BIG_ENDIAN);
586
0
        offset += 2;
587
588
0
        tlv_len = tvb_get_ntohs(tvb, offset);
589
0
        offset += 2;
590
0
        proto_item_append_text(sti, " (%d bytes)", tlv_len);
591
        /* TODO - if there are non boolean caps, validate before use */
592
0
    }
593
0
}
594
595
static void
596
ancp_stats_tree_init(stats_tree *st)
597
0
{
598
0
    st_node_packets = stats_tree_create_node(st, st_str_packets, 0, STAT_DT_INT, true);
599
0
    st_node_packet_types = stats_tree_create_pivot(st, st_str_packet_types,
600
0
            st_node_packets);
601
0
    st_node_adj_pack_types = stats_tree_create_node(st, st_str_adj_pack_types,
602
0
            st_node_packets, STAT_DT_INT, true);
603
0
}
604
605
static tap_packet_status
606
ancp_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_,
607
                       epan_dissect_t* edt _U_ , const void* p, tap_flags_t flags _U_)
608
0
{
609
0
    const struct ancp_tap_t *pi = (const struct ancp_tap_t *) p;
610
611
0
    tick_stat_node(st, st_str_packets, 0, false);
612
0
    stats_tree_tick_pivot(st, st_node_packet_types,
613
0
            val_to_str(pinfo->pool, pi->ancp_mtype, mtype_names,
614
0
                "Unknown packet type (%d)"));
615
0
    if (pi->ancp_mtype == ANCP_MTYPE_ADJ)
616
0
        stats_tree_tick_pivot(st, st_node_adj_pack_types,
617
0
                val_to_str(pinfo->pool, pi->ancp_adjcode, adj_code_names,
618
0
                    "Unknown Adjacency packet (%d)"));
619
0
    return TAP_PACKET_REDRAW;
620
0
}
621
622
static int
623
dissect_ancp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
624
47
{
625
47
    int                offset;
626
47
    uint8_t            mtype;
627
47
    struct ancp_tap_t *ancp_info;
628
47
    proto_item        *ti;
629
47
    proto_item        *sti;
630
47
    proto_item        *tti = NULL;
631
47
    proto_tree        *ancp_tree;
632
47
    proto_tree        *tlv_tree;
633
47
    uint8_t            byte;
634
47
    uint16_t           len;
635
636
47
    offset = 0;
637
47
    if (tvb_get_ntohs(tvb, offset) != ANCP_GSMP_ETHER_TYPE)
638
47
        return 0; /* XXX: this dissector is not a heuristic dissector */
639
                /* Should do "expert" & dissect rest as "data"      */
640
                /*  (after setting COL_PROTOCOL & etc) ?            */
641
642
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ANCP");
643
0
    col_clear(pinfo->cinfo, COL_INFO);
644
645
0
    ancp_info = wmem_new(pinfo->pool, struct ancp_tap_t);
646
0
    ancp_info->ancp_mtype   = 0;
647
0
    ancp_info->ancp_adjcode = 0;
648
649
0
    ti = proto_tree_add_item(tree, proto_ancp, tvb, 0, -1, ENC_NA);
650
651
0
    ancp_tree = proto_item_add_subtree(ti, ett_ancp_len);
652
653
0
    offset = 2; /* skip ether type */
654
655
0
    proto_tree_add_item_ret_uint16(ancp_tree, hf_ancp_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
656
0
    offset += 2;
657
658
0
    sti  = proto_tree_add_item_ret_uint8(ancp_tree, hf_ancp_ver, tvb, offset, 1, ENC_BIG_ENDIAN, &byte);
659
0
    offset += 1;
660
0
    proto_item_append_text(sti, " (%d.%d)", byte >> 4, byte & 0x0F);
661
662
    /* ANCP message type */
663
0
    sti = proto_tree_add_item_ret_uint8(ancp_tree, hf_ancp_mtype, tvb, offset, 1, ENC_BIG_ENDIAN, &mtype);
664
0
    ancp_info->ancp_mtype = mtype; /* stats */
665
0
    offset += 1;
666
667
0
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s Message",
668
0
                 val_to_str(pinfo->pool, mtype, mtype_names, "Unknown (0x%02x)"));
669
670
0
    if (mtype != ANCP_MTYPE_ADJ) {
671
        /* Dissect common header */
672
0
        proto_tree_add_item(ancp_tree, hf_ancp_result, tvb, offset, 1,
673
0
                            ENC_BIG_ENDIAN); /* treat as 1B, but don't change offset */
674
675
0
        proto_tree_add_item(ancp_tree, hf_ancp_code, tvb, offset, 2,
676
0
                            ENC_BIG_ENDIAN);
677
0
        offset += 2;
678
679
0
        proto_tree_add_item(ancp_tree, hf_ancp_p_id, tvb, offset,
680
0
                            1, ENC_BIG_ENDIAN);
681
0
        offset += 1;
682
683
0
        proto_tree_add_item(ancp_tree, hf_ancp_trans_id, tvb,
684
0
                            offset, 3, ENC_BIG_ENDIAN);
685
0
        offset += 3;
686
687
0
        proto_tree_add_item(ancp_tree, hf_ancp_i_flag, tvb, offset, 1,
688
0
                            ENC_BIG_ENDIAN); /* treat as 1B, but don't change offset */
689
690
0
        proto_tree_add_item(ancp_tree, hf_ancp_submsg_num, tvb,
691
0
                                  offset, 2, ENC_BIG_ENDIAN);
692
0
        offset += 2;
693
694
0
        tti = proto_tree_add_item(ancp_tree, hf_ancp_len2, tvb, offset,
695
0
                            2, ENC_BIG_ENDIAN);
696
0
        offset += 2; /* Length */
697
0
    }
698
699
0
    switch(mtype) {
700
0
    case ANCP_MTYPE_ADJ:
701
0
        dissect_ancp_adj_msg(tvb, pinfo, ancp_tree, offset, ancp_info);
702
0
        break;
703
0
    case ANCP_MTYPE_PORT_DN:
704
        /* FALL THRU */
705
0
    case ANCP_MTYPE_PORT_MGMT:
706
        /* FALL THRU */
707
0
    case ANCP_MTYPE_PORT_UP:
708
0
        dissect_ancp_port_up_dn_mgmt(tvb, pinfo, ancp_tree, offset, mtype);
709
0
        break;
710
0
    case ANCP_MTYPE_PROV:
711
        /* FALL THRU */
712
0
    case ANCP_MTYPE_GEN_RSP:
713
0
        tlv_tree = proto_item_add_subtree(tti, ett_ancp_len);
714
715
0
        while( offset < len + 4) {
716
0
            offset = dissect_ancp_tlv(tvb, pinfo, tlv_tree, offset);
717
0
        }
718
0
        break;
719
0
    case ANCP_MTYPE_ADJ_UPD:
720
0
        break;
721
0
    default:
722
0
        proto_item_append_text(sti, " (Unknown Message %d)", mtype);
723
0
        break;
724
0
    }
725
0
    tap_queue_packet(ancp_tap, pinfo, ancp_info);
726
727
0
    return tvb_reported_length(tvb);
728
0
}
729
730
static unsigned
731
get_ancp_msg_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
732
47
{
733
47
    return (unsigned)tvb_get_ntohs(tvb, offset + 2) + 4; /* 2B len + 4B hdr */
734
47
}
735
736
static int
737
dissect_ancp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
738
4
{
739
4
    tcp_dissect_pdus(tvb, pinfo, tree, true, ANCP_MIN_HDR,
740
4
            get_ancp_msg_len, dissect_ancp_message, data);
741
742
4
    return tvb_reported_length(tvb);
743
4
}
744
745
void
746
proto_register_ancp(void)
747
14
{
748
14
    static hf_register_info hf[] = {
749
14
        { &hf_ancp_len,
750
14
            { "Length", "ancp.len",
751
14
                FT_UINT16, BASE_DEC,
752
14
                NULL, 0x0,
753
14
                NULL, HFILL }
754
14
        },
755
14
        { &hf_ancp_len2,
756
14
            { "Length", "ancp.len2",
757
14
                FT_UINT16, BASE_DEC,
758
14
                NULL, 0x0,
759
14
                NULL, HFILL }
760
14
        },
761
14
        { &hf_ancp_ver,
762
14
            { "Version", "ancp.ver",
763
14
                FT_UINT8, BASE_HEX,
764
14
                NULL, 0x0,
765
14
                NULL, HFILL }
766
14
        },
767
14
        { &hf_ancp_mtype,
768
14
            { "Message Type", "ancp.mtype",
769
14
                FT_UINT8, BASE_DEC,
770
14
                VALS(mtype_names), 0x0,
771
14
                NULL, HFILL }
772
14
        },
773
14
        { &hf_ancp_timer,
774
14
            { "Timer", "ancp.timer",
775
14
                FT_UINT8, BASE_DEC|BASE_UNIT_STRING,
776
14
                UNS(&units_milliseconds), 0x0,
777
14
                NULL, HFILL }
778
14
        },
779
14
        { &hf_ancp_adj_code,
780
14
            { "Code", "ancp.adjcode", /* this is diff from code */
781
14
                FT_UINT8, BASE_DEC,   /* for Adjacency msg only */
782
14
                NULL, ADJ_CODE_MASK,
783
14
                NULL, HFILL }
784
14
        },
785
14
        { &hf_ancp_sender_name,
786
14
            { "Sender Name", "ancp.sender_name",
787
14
                FT_ETHER, BASE_NONE,
788
14
                NULL, 0x0,
789
14
                NULL, HFILL }
790
14
        },
791
14
        { &hf_ancp_receiver_name,
792
14
            { "Receiver Name", "ancp.receiver_name",
793
14
                FT_ETHER, BASE_NONE,
794
14
                NULL, 0x0,
795
14
                NULL, HFILL }
796
14
        },
797
14
        { &hf_ancp_sender_port,
798
14
            { "Sender Port", "ancp.sender_port",
799
14
                FT_UINT64, BASE_DEC,
800
14
                NULL, 0x0,
801
14
                NULL, HFILL }
802
14
        },
803
14
        { &hf_ancp_receiver_port,
804
14
            { "Receiver Port", "ancp.receiver_port",
805
14
                FT_UINT64, BASE_DEC,
806
14
                NULL, 0x0,
807
14
                NULL, HFILL }
808
14
        },
809
14
        { &hf_ancp_p_info,
810
14
            { "Partition Info", "ancp.partition_info",
811
14
                FT_UINT8, BASE_HEX,
812
14
                NULL, 0x0,
813
14
                NULL, HFILL }
814
14
        },
815
14
        { &hf_ancp_sender_instance,
816
14
            { "Sender Instance", "ancp.sender_instance",
817
14
                FT_UINT24, BASE_DEC,
818
14
                NULL, 0x0,
819
14
                NULL, HFILL }
820
14
        },
821
14
        { &hf_ancp_p_id,
822
14
            { "Partition ID", "ancp.partition_id",
823
14
                FT_UINT8, BASE_DEC,
824
14
                NULL, 0x0,
825
14
                NULL, HFILL }
826
14
        },
827
14
        { &hf_ancp_receiver_instance,
828
14
            { "Receiver Instance", "ancp.receiver_instance",
829
14
                FT_UINT24, BASE_DEC,
830
14
                NULL, 0x0,
831
14
                NULL, HFILL }
832
14
        },
833
14
        { &hf_ancp_tech_type,
834
14
            { "Tech Type", "ancp.tech_type",
835
14
                FT_UINT8, BASE_DEC,
836
14
                VALS(techtype_str), 0x0,
837
14
                NULL, HFILL }
838
14
        },
839
14
        { &hf_ancp_num_tlvs,
840
14
            { "Num TLVs", "ancp.num_tlvs",
841
14
                FT_UINT8, BASE_DEC,
842
14
                NULL, 0x0,
843
14
                NULL, HFILL }
844
14
        },
845
14
        { &hf_ancp_tot_len,
846
14
            { "Length", "ancp.tot_len", /* name just Len to reuse*/
847
14
                FT_UINT16, BASE_DEC,
848
14
                NULL, 0x0,
849
14
                NULL, HFILL }
850
14
        },
851
14
        { &hf_ancp_cap,
852
14
            { "Capability", "ancp.capability",
853
14
                FT_UINT16, BASE_DEC,
854
14
                VALS(captype_names), 0x0,
855
14
                NULL, HFILL }
856
14
        },
857
14
        { &hf_ancp_result,
858
14
            { "Result", "ancp.result",
859
14
                FT_UINT8, BASE_DEC,
860
14
                VALS(resulttype_names), ANCP_RESULT_MASK,
861
14
                NULL, HFILL }
862
14
        },
863
14
        { &hf_ancp_code,
864
14
            { "Code", "ancp.code",
865
14
                FT_UINT16, BASE_HEX,
866
14
                VALS(codetype_names), ANCP_CODE_MASK,
867
14
                NULL, HFILL }
868
14
        },
869
14
        { &hf_ancp_trans_id,
870
14
            { "Transaction ID", "ancp.transaction_id",
871
14
                FT_UINT24, BASE_DEC,
872
14
                NULL, 0x0,
873
14
                NULL, HFILL }
874
14
        },
875
14
        { &hf_ancp_i_flag,
876
14
            { "I Flag", "ancp.i_flag",
877
14
                FT_BOOLEAN, 8,
878
14
                TFS(&tfs_set_notset), ANCP_I_FLAG_MASK,
879
14
                NULL, HFILL }
880
14
        },
881
14
        { &hf_ancp_submsg_num,
882
14
            { "SubMessage Number", "ancp.submessage_number",
883
14
                FT_UINT16, BASE_DEC,
884
14
                NULL, ANCP_SUBMSG_MASK,
885
14
                NULL, HFILL }
886
14
        },
887
14
        { &hf_ancp_pudm_unused,
888
14
            { "Unused Bytes", "ancp.unused",
889
14
                FT_BYTES, BASE_NONE,
890
14
                NULL, 0x0,
891
14
                NULL, HFILL }
892
14
        },
893
14
        { &hf_ancp_function,
894
14
            { "Function", "ancp.function",
895
14
                FT_UINT8, BASE_DEC,
896
14
                VALS(function_names), 0x0,
897
14
                NULL, HFILL }
898
14
        },
899
14
        { &hf_ancp_x_function,
900
14
            { "X-Function", "ancp.x_function",
901
14
                FT_UINT8, BASE_DEC,
902
14
                NULL, 0x0,
903
14
                NULL, HFILL }
904
14
        },
905
14
        { &hf_ancp_ext_flags_res,
906
14
            { "Extension Flags Reserved", "ancp.ext_flags",
907
14
                FT_BYTES, BASE_NONE,
908
14
                NULL, 0x0,
909
14
                NULL, HFILL }
910
14
        },
911
14
        { &hf_ancp_reserved,
912
14
            { "Reserved", "ancp.reserved",
913
14
                FT_BYTES, BASE_NONE,
914
14
                NULL, 0x0,
915
14
                NULL, HFILL }
916
14
        },
917
14
        { &hf_ancp_blk_len,
918
14
            { "Block Length", "ancp.blk_len",
919
14
                FT_UINT16, BASE_DEC,
920
14
                NULL, 0x0,
921
14
                NULL, HFILL }
922
14
        },
923
14
        { &hf_ancp_num_ext_tlvs,
924
14
            { "Num TLVs", "ancp.ext_tlvs.count",
925
14
                FT_UINT16, BASE_DEC,
926
14
                NULL, 0x0,
927
14
                NULL, HFILL }
928
14
        },
929
14
        { &hf_ancp_ext_tlv_type,
930
14
            { "TLV Type", "ancp.ext_tlv.type",
931
14
                FT_UINT16, BASE_DEC|BASE_EXT_STRING,
932
14
                &ext_tlv_types_ext, 0x0,
933
14
                NULL, HFILL }
934
14
        },
935
14
        { &hf_ancp_ext_tlv_len,
936
14
            { "TLV Length", "ancp.ext_tlv.len",
937
14
                FT_UINT16, BASE_DEC,
938
14
                NULL, 0x0,
939
14
                NULL, HFILL }
940
14
        },
941
14
        { &hf_ancp_dsl_line_stlv_type,
942
14
            { "Sub-TLV", "ancp.sub_tlv_type",
943
14
                FT_UINT16, BASE_HEX,
944
14
                VALS(dsl_line_attrs), 0x0,
945
14
                NULL, HFILL }
946
14
        },
947
14
        { &hf_ancp_dsl_line_stlv_len,
948
14
            { "Sub-TLV Length", "ancp.sub_tlv_len",
949
14
                FT_UINT16, BASE_DEC,
950
14
                NULL, 0x0,
951
14
                NULL, HFILL }
952
14
        },
953
14
        { &hf_ancp_dsl_line_stlv_value,
954
14
            { "Value", "ancp.dsl_line_param",
955
14
                FT_UINT32, BASE_DEC,
956
14
                NULL, 0x0,
957
14
                NULL, HFILL }
958
14
        },
959
14
        { &hf_ancp_ext_tlv_value_str,
960
14
            { "Value", "ancp.ext_tlv.value",
961
14
                FT_STRING, BASE_NONE,
962
14
                NULL, 0x0,
963
14
                NULL, HFILL }
964
14
        },
965
14
        { &hf_ancp_oam_opaque,
966
14
            { "Opaque", "ancp.oam.opaque", /* There will be 2 such 32b vals */
967
14
                FT_UINT32, BASE_DEC,
968
14
                NULL, 0x0,
969
14
                NULL, HFILL }
970
14
        },
971
14
        { &hf_ancp_oam_loopb_cnt,
972
14
            { "OAM Loopback Count", "ancp.oam.loopback_count",
973
14
                FT_UINT8, BASE_DEC,
974
14
                NULL, 0x0,
975
14
                NULL, HFILL }
976
14
        },
977
14
        { &hf_ancp_oam_timeout,
978
14
            { "OAM Timeout", "ancp.oam.timeout",
979
14
                FT_UINT8, BASE_DEC,
980
14
                NULL, 0x0,
981
14
                NULL, HFILL }
982
14
        },
983
14
    };
984
985
    /* Setup protocol subtree array */
986
14
    static int *ett[] = {
987
14
        &ett_ancp_len,
988
14
        &ett_ancp_ver,
989
14
        &ett_ancp_mtype,
990
14
        &ett_ancp_timer,
991
14
        &ett_ancp_adj_code,
992
14
        &ett_ancp_sender_name,
993
14
        &ett_ancp_receiver_name,
994
14
        &ett_ancp_sender_port,
995
14
        &ett_ancp_receiver_port,
996
14
        &ett_ancp_p_info,
997
14
        &ett_ancp_sender_instance,
998
14
        &ett_ancp_p_id,
999
14
        &ett_ancp_receiver_instance,
1000
14
        &ett_ancp_tech_type,
1001
14
        &ett_ancp_num_tlvs,
1002
14
        &ett_ancp_tot_len,
1003
14
        &ett_ancp_cap,
1004
14
        &ett_ancp_result,
1005
14
        &ett_ancp_code,
1006
14
        &ett_ancp_trans_id,
1007
14
        &ett_ancp_i_flag,
1008
14
        &ett_ancp_submsg_num,
1009
14
        &ett_ancp_port,
1010
14
        &ett_ancp_port_sess_num,
1011
14
        &ett_ancp_evt_seq_num,
1012
14
        &ett_ancp_label,
1013
14
        &ett_ancp_reserved,
1014
14
        &ett_ancp_blk_len,
1015
14
        &ett_ancp_num_ext_tlvs,
1016
14
        &ett_ancp_ext_tlv_type,
1017
14
        &ett_ancp_dsl_line_stlv_type,
1018
14
        &ett_ancp_dsl_line_stlv_val,
1019
14
        &ett_ancp_ext_tlv_value_str,
1020
14
        &ett_ancp_oam_opaque,
1021
14
        &ett_ancp_oam_loopb_cnt,
1022
14
        &ett_ancp_oam_timeout,
1023
14
    };
1024
1025
14
    proto_ancp = proto_register_protocol ("Access Node Control Protocol", "ANCP", "ancp");
1026
1027
14
    proto_register_field_array(proto_ancp, hf, array_length(hf));
1028
14
    proto_register_subtree_array(ett, array_length(ett));
1029
14
    ancp_tap = register_tap("ancp");
1030
1031
14
    ancp_handle = register_dissector("ancp", dissect_ancp, proto_ancp);
1032
14
}
1033
1034
void
1035
proto_reg_handoff_ancp(void)
1036
14
{
1037
14
    dissector_add_uint_with_preference("tcp.port", ANCP_PORT, ancp_handle);
1038
14
    stats_tree_register("ancp", "ancp", "ANCP", 0,
1039
            ancp_stats_tree_packet, ancp_stats_tree_init, NULL);
1040
14
}
1041
1042
/*
1043
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1044
 *
1045
 * Local variables:
1046
 * c-basic-offset: 4
1047
 * tab-width: 8
1048
 * indent-tabs-mode: nil
1049
 * End:
1050
 *
1051
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1052
 * :indentSize=4:tabSize=8:noTabs=true:
1053
 */