3 * Dissector for ANCP - Access Node Control Protocol
5 * More info on the protocol can be found on IETF:
6 * http://tools.ietf.org/wg/ancp/
7 * http://tools.ietf.org/html/draft-ietf-ancp-protocol-09
9 * Copyright 2010, Aniruddha.A (anira@cisco.com)
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <epan/packet.h>
35 #include <epan/wmem/wmem.h>
36 #include <epan/dissectors/packet-tcp.h>
38 #include <epan/stats_tree.h>
40 #define ANCP_PORT 6068 /* The ANCP TCP port:draft-ietf-ancp-protocol-09.txt */
42 #define ANCP_MIN_HDR 4
43 #define ANCP_GSMP_ETHER_TYPE 0x880C
44 #define TECH_TYPE_DSL 0x5
46 #define ANCP_RESULT_MASK 0xF0
47 #define ANCP_CODE_MASK 0x0FFF
48 #define ANCP_I_FLAG_MASK 0x80
49 #define ANCP_SUBMSG_MASK 0x7FFF
50 #define ADJ_CODE_MASK 0x7F /* excluding MSB M-Flag */
52 #define ANCP_MTYPE_ADJ 10
53 #define ANCP_MTYPE_PORT_MGMT 32
54 #define ANCP_MTYPE_PORT_UP 80
55 #define ANCP_MTYPE_PORT_DN 81
57 /* Topology Discovery Extensions */
58 #define TLV_DSL_LINE_ATTRIBUTES 0x04
59 #define TLV_DSL_LINE_STATE 0x8F
60 #define TLV_DSL_TYPE 0x91
62 /* Port Management Extensions */
63 #define TLV_PING_PARAMS 0x07
64 #define TLV_PING_OPAQUE_DATA 0x08
65 #define TLV_PING_RES_STR 0x09
67 #define SKIPPADDING(_ofst, _len) \
70 _ofst += (4 - ((_len) % 4)); \
73 void proto_register_ancp(void);
74 void proto_reg_handoff_ancp(void);
76 static int hf_ancp_len
= -1;
77 static int hf_ancp_ver
= -1;
78 static int hf_ancp_mtype
= -1;
79 static int hf_ancp_timer
= -1;
80 static int hf_ancp_adj_code
= -1;
81 static int hf_ancp_sender_name
= -1;
82 static int hf_ancp_receiver_name
= -1;
83 static int hf_ancp_sender_port
= -1;
84 static int hf_ancp_receiver_port
= -1;
85 static int hf_ancp_p_info
= -1;
86 static int hf_ancp_sender_instance
= -1;
87 static int hf_ancp_p_id
= -1;
88 static int hf_ancp_receiver_instance
= -1;
89 static int hf_ancp_tech_type
= -1;
90 static int hf_ancp_num_tlvs
= -1;
91 static int hf_ancp_tot_len
= -1;
92 static int hf_ancp_cap
= -1;
93 static int hf_ancp_result
= -1;
94 static int hf_ancp_code
= -1;
95 static int hf_ancp_trans_id
= -1;
96 static int hf_ancp_i_flag
= -1;
97 static int hf_ancp_submsg_num
= -1;
98 static int hf_ancp_port
= -1;
99 static int hf_ancp_port_sess_num
= -1;
100 static int hf_ancp_evt_seq_num
= -1;
101 static int hf_ancp_label
= -1;
102 static int hf_ancp_reserved
= -1;
103 static int hf_ancp_blk_len
= -1;
104 static int hf_ancp_num_ext_tlvs
= -1;
105 static int hf_ancp_ext_tlv_type
= -1;
106 static int hf_ancp_dsl_line_stlv_type
= -1;
107 static int hf_ancp_dsl_line_stlv_value
= -1;
108 static int hf_ancp_ext_tlv_value_str
= -1;
109 static int hf_ancp_oam_opaque
= -1;
110 static int hf_ancp_oam_loopb_cnt
= -1;
111 static int hf_ancp_oam_timeout
= -1;
113 static gint ett_ancp_len
= -1;
114 static gint ett_ancp_ver
= -1;
115 static gint ett_ancp_mtype
= -1;
116 static gint ett_ancp_timer
= -1;
117 static gint ett_ancp_adj_code
= -1;
118 static gint ett_ancp_sender_name
= -1;
119 static gint ett_ancp_receiver_name
= -1;
120 static gint ett_ancp_sender_port
= -1;
121 static gint ett_ancp_receiver_port
= -1;
122 static gint ett_ancp_p_info
= -1;
123 static gint ett_ancp_sender_instance
= -1;
124 static gint ett_ancp_p_id
= -1;
125 static gint ett_ancp_receiver_instance
= -1;
126 static gint ett_ancp_tech_type
= -1;
127 static gint ett_ancp_num_tlvs
= -1;
128 static gint ett_ancp_tot_len
= -1;
129 static gint ett_ancp_cap
= -1;
130 static gint ett_ancp_result
= -1;
131 static gint ett_ancp_code
= -1;
132 static gint ett_ancp_trans_id
= -1;
133 static gint ett_ancp_i_flag
= -1;
134 static gint ett_ancp_submsg_num
= -1;
135 static gint ett_ancp_port
= -1;
136 static gint ett_ancp_port_sess_num
= -1;
137 static gint ett_ancp_evt_seq_num
= -1;
138 static gint ett_ancp_label
= -1;
139 static gint ett_ancp_reserved
= -1;
140 static gint ett_ancp_blk_len
= -1;
141 static gint ett_ancp_num_ext_tlvs
= -1;
142 static gint ett_ancp_ext_tlv_type
= -1;
143 static gint ett_ancp_dsl_line_stlv_type
= -1;
144 static gint ett_ancp_dsl_line_stlv_val
= -1;
145 static gint ett_ancp_ext_tlv_value_str
= -1;
146 static gint ett_ancp_oam_opaque
= -1;
147 static gint ett_ancp_oam_loopb_cnt
= -1;
148 static gint ett_ancp_oam_timeout
= -1;
150 static int proto_ancp
= -1;
152 /* ANCP stats - Tap interface */
153 static const guint8
*st_str_packets
= "Total Packets";
154 static const guint8
*st_str_packet_types
= "ANCP Packet Types";
155 static const guint8
*st_str_adj_pack_types
= "ANCP Adjacency Packet Types";
157 static int st_node_packets
= -1;
158 static int st_node_packet_types
= -1;
159 static int st_node_adj_pack_types
= -1;
160 static int ancp_tap
= -1;
164 gint ancp_adjcode
; /* valid for ancp adjacency message only */
168 static const value_string mtype_names
[] = {
170 { 32, "Port-Management" },
176 static const value_string adj_code_names
[] = {
184 static const value_string captype_names
[] = {
185 { 1, "Dynamic-Topology-Discovery" },
186 { 2, "Line-Configuration" },
187 { 3, "Transactional-Multicast" },
192 static const value_string resulttype_names
[] = {
201 static const value_string codetype_names
[] = { /* For now, these are OAM codes*/
202 { 0x500, "Access-line-doesn't-exist" },
203 { 0x501, "Loopback-Test-Timeout" },
204 { 0x502, "Reserved" },
205 { 0x503, "DSL-line-status-showtime" },
206 { 0x504, "DSL-line-status-idle" },
207 { 0x505, "DSL-line-status-silent" },
208 { 0x506, "DSL-line-status-training" },
209 { 0x507, "DSL-line-integrity-error" },
210 { 0x508, "DSLAM resource-unavailable" },
211 { 0x509, "Invalid Test Parameter" },
215 static const value_string techtype_str
[] = {
221 static const value_string dsl_line_attrs
[] = {
222 { 0x91, "DSL-Type" },
223 { 0x81, "Actual-Net-Data-Rate-Upstream" },
224 { 0x82, "Actual-Net-Data-Rate-Downstream" },
225 { 0x83, "Minimum-Net-Data-Rate-Upstream" },
226 { 0x84, "Minimum-Net-Data-Rate-Downstream" },
227 { 0x85, "Attainable-Net-Data-Rate-Upstream" },
228 { 0x86, "Attainable-Net-Data-Rate-Downstream" },
229 { 0x87, "Maximum-Net-Data-Rate-Upstream" },
230 { 0x88, "Maximum-Net-Data-Rate-Downstream" },
231 { 0x89, "Minimum-Net-Low-Power-Data-Rate-Upstream" },
232 { 0x8A, "Minimum-Net-Low-Power-Data-Rate-Downstream" },
233 { 0x8B, "Maximum-Interleaving-Delay-Upstream" },
234 { 0x8C, "Actual-Interleaving-Delay-Upstream" },
235 { 0x8D, "Maximum-Interleaving-Delay-Downstream" },
236 { 0x8E, "Actual-Interleaving-Delay-Downstream" },
237 { 0x8F, "DSL line state" },
238 { 0x90, "Access Loop Encapsulation" },
242 static const value_string dsl_line_attr_units
[] = {
263 static const value_string dsl_line_type_names
[] = {
273 static const value_string dsl_line_state_names
[] = {
280 static const value_string ext_tlv_types
[] = {
281 { 0x01, "Access-Loop-Circuit-ID" },
282 { 0x02, "Access-Loop-Remote-ID" },
283 { 0x03, "Access-Aggregation-Circuit-ID-ASCII" },
284 { 0x04, "DSL Line Attributes" },
285 { 0x06, "Access-Aggregation-Circuit-ID-Binary" },
286 { 0x07, "OAM-Loopback-Test-Parameters" },
287 { 0x08, "Opaque-Data" },
288 { 0x09, "OAM-Loopback-Test-Response-String" },
293 dissect_ancp_port_up_dn_mgmt(tvbuff_t
*tvb
, proto_tree
*ancp_tree
, gint offset
)
297 proto_tree_add_item(ancp_tree
, hf_ancp_port
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
300 proto_tree_add_item(ancp_tree
, hf_ancp_port_sess_num
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
303 proto_tree_add_item(ancp_tree
, hf_ancp_evt_seq_num
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
306 proto_tree_add_item(ancp_tree
, hf_ancp_label
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
309 /* Start of the Extension Block */
310 proto_tree_add_item(ancp_tree
, hf_ancp_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
313 * We have already displayed the message type in the common header dissect
314 * so need not display this again here - skip it
316 offset
+= 1; /* Message type in Ext Blk */
318 proto_tree_add_item(ancp_tree
, hf_ancp_tech_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
319 tech_type
= tvb_get_guint8(tvb
, offset
);
322 proto_tree_add_item(ancp_tree
, hf_ancp_blk_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
325 if (tech_type
== TECH_TYPE_DSL
) {
327 proto_tree
*tlv_tree
;
329 gint16 num_tlvs
, num_stlvs
;
331 proto_tree_add_item(ancp_tree
, hf_ancp_num_ext_tlvs
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
332 num_tlvs
= tvb_get_ntohs(tvb
, offset
);
335 sti
= proto_tree_add_item(ancp_tree
, hf_ancp_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
336 proto_item_append_text(sti
, " (Extension Block)");
339 /* Create a TLV sub tree */
340 tlv_tree
= proto_item_add_subtree(sti
, ett_ancp_len
);
342 for( ;num_tlvs
; num_tlvs
--) {
343 proto_tree_add_item(tlv_tree
, hf_ancp_ext_tlv_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
344 ttype
= tvb_get_ntohs(tvb
, offset
);
347 sti
= proto_tree_add_item(tlv_tree
, hf_ancp_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
348 tlen
= tvb_get_ntohs(tvb
, offset
);
352 * Extension Block is common for event message and port
353 * management message, but the TLVs that can appear
357 case TLV_DSL_LINE_ATTRIBUTES
:
359 proto_tree
*dsl_tree
;
360 guint16 stlvtype
, stlvlen
;
363 /* Create a DSL Attribute SubTree */
364 dsl_tree
= proto_item_add_subtree(sti
, ett_ancp_ext_tlv_type
);
365 num_stlvs
= tlen
/ 8; /* TODO - better way? */
366 for ( ;num_stlvs
; num_stlvs
--) {
367 proto_tree_add_item(dsl_tree
,
368 hf_ancp_dsl_line_stlv_type
, tvb
, offset
,
370 stlvtype
= tvb_get_ntohs(tvb
, offset
);
372 /* Skip sub-tlv-len display for now */
373 stlvlen
= tvb_get_ntohs(tvb
, offset
);
374 offset
+= 2; /* Sub TLV Length */
376 sti
= proto_tree_add_item(dsl_tree
,
377 hf_ancp_dsl_line_stlv_value
, tvb
, offset
,
378 stlvlen
, ENC_BIG_ENDIAN
);
379 val
= tvb_get_ntohl(tvb
, offset
);
380 offset
+= stlvlen
; /* Except loop-encap, rest are 4B */
383 case TLV_DSL_LINE_STATE
:
384 proto_item_append_text(sti
, " (%s)",
385 val_to_str(val
, dsl_line_state_names
,
386 "Unknown (0x%02x)"));
389 proto_item_append_text(sti
, " (%s)",
390 val_to_str(val
, dsl_line_type_names
,
391 "Unknown (0x%02x)"));
396 proto_item_append_text(sti
, " %s",
399 "Unknown (0x%02x)"));
402 SKIPPADDING(offset
, stlvlen
);
406 case TLV_PING_OPAQUE_DATA
:
408 proto_tree_add_item(tlv_tree
, hf_ancp_oam_opaque
,
409 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
411 proto_tree_add_item(tlv_tree
, hf_ancp_oam_opaque
,
412 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
415 case TLV_PING_PARAMS
:
416 /* Count (1B) Timeout (1B), 2B empty */
417 proto_tree_add_item(tlv_tree
,
418 hf_ancp_oam_loopb_cnt
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
420 proto_tree_add_item(tlv_tree
,
421 hf_ancp_oam_timeout
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
423 /* Lets not bother about 2B until IETF WG figures out */
427 /* Assume TLV value is string - covers ALCID, OAM resp */
428 proto_tree_add_item(tlv_tree
, hf_ancp_ext_tlv_value_str
,
429 tvb
, offset
, tlen
, ENC_ASCII
|ENC_NA
);
431 SKIPPADDING(offset
, tlen
);
433 } /* end switch {ttype} */
434 } /* end for {numtlvs} */
439 dissect_ancp_adj_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*ancp_tree
,
440 gint offset
, struct ancp_tap_t
*ancp_info
444 proto_tree
*ancp_cap_tree
;
445 guint8 byte
, numcaps
, adjcode
;
448 sti
= proto_tree_add_item(ancp_tree
, hf_ancp_timer
, tvb
, offset
, 1,
451 proto_item_append_text(sti
, " msec");
453 sti
= proto_tree_add_item(ancp_tree
, hf_ancp_adj_code
, tvb
, offset
, 1,
455 byte
= tvb_get_guint8(tvb
, offset
);
457 adjcode
= byte
& ADJ_CODE_MASK
;
458 ancp_info
->ancp_adjcode
= adjcode
; /* stats */
459 proto_item_append_text(sti
, " (%s, M Flag %s)",
460 val_to_str(adjcode
, adj_code_names
, "Unknown (0x%02x)"),
461 (byte
>> 7) ? "Set" : "Unset");
462 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)",
463 val_to_str(adjcode
, adj_code_names
, "Unknown (0x%02x)"));
465 proto_tree_add_item(ancp_tree
, hf_ancp_sender_name
, tvb
, offset
, 6, ENC_NA
);
468 proto_tree_add_item(ancp_tree
, hf_ancp_receiver_name
, tvb
,offset
, 6, ENC_NA
);
471 proto_tree_add_item(ancp_tree
, hf_ancp_sender_port
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
474 proto_tree_add_item(ancp_tree
, hf_ancp_receiver_port
, tvb
,offset
, 4, ENC_BIG_ENDIAN
);
477 sti
= proto_tree_add_item(ancp_tree
, hf_ancp_p_info
, tvb
,
478 offset
, 1, ENC_BIG_ENDIAN
);
479 byte
= tvb_get_guint8(tvb
, offset
);
481 proto_item_append_text(sti
, " (Type = %d, Flag = %d)",
482 byte
>> 4, byte
& 0x0F);
484 proto_tree_add_item(ancp_tree
, hf_ancp_sender_instance
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
487 proto_tree_add_item(ancp_tree
, hf_ancp_p_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
490 proto_tree_add_item(ancp_tree
, hf_ancp_receiver_instance
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
493 proto_tree_add_item(ancp_tree
, hf_ancp_tech_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
496 sti
= proto_tree_add_item(ancp_tree
, hf_ancp_num_tlvs
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
497 numcaps
= tvb_get_guint8(tvb
, offset
);
500 /* Start the capability subtree */
501 ancp_cap_tree
= proto_item_add_subtree(sti
, ett_ancp_tot_len
);
503 proto_tree_add_item(ancp_cap_tree
, hf_ancp_tot_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
506 for ( ;numcaps
; numcaps
--) {
507 sti
= proto_tree_add_item(ancp_cap_tree
, hf_ancp_cap
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
510 tlv_len
= tvb_get_ntohs(tvb
, offset
);
512 proto_item_append_text(sti
, " (%d bytes)", tlv_len
);
513 /* TODO - if there are non boolean caps, validate before use */
518 ancp_stats_tree_init(stats_tree
*st
)
520 st_node_packets
= stats_tree_create_node(st
, st_str_packets
, 0, TRUE
);
521 st_node_packet_types
= stats_tree_create_pivot(st
, st_str_packet_types
,
523 st_node_adj_pack_types
= stats_tree_create_node(st
, st_str_adj_pack_types
,
524 st_node_packets
, TRUE
);
528 ancp_stats_tree_packet(stats_tree
* st
, packet_info
* pinfo _U_
,
529 epan_dissect_t
* edt _U_
, const void* p
)
531 struct ancp_tap_t
*pi
= (struct ancp_tap_t
*) p
;
533 tick_stat_node(st
, st_str_packets
, 0, FALSE
);
534 stats_tree_tick_pivot(st
, st_node_packet_types
,
535 val_to_str(pi
->ancp_mtype
, mtype_names
,
536 "Unknown packet type (%d)"));
537 if (pi
->ancp_mtype
== ANCP_MTYPE_ADJ
)
538 stats_tree_tick_pivot(st
, st_node_adj_pack_types
,
539 val_to_str(pi
->ancp_adjcode
, adj_code_names
,
540 "Unknown Adjacency packet (%d)"));
545 dissect_ancp_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
549 struct ancp_tap_t
*ancp_info
;
552 proto_tree
*ancp_tree
;
556 if (tvb_get_ntohs(tvb
, offset
) != ANCP_GSMP_ETHER_TYPE
)
557 return 0; /* XXX: this dissector is not a heuristic dissector */
558 /* Should do "expert" & dissect rest as "data" */
559 /* (after setting COL_PROTOCOL & etc) ? */
561 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ANCP");
562 col_clear(pinfo
->cinfo
, COL_INFO
);
564 ancp_info
= wmem_new(wmem_packet_scope(), struct ancp_tap_t
);
565 ancp_info
->ancp_mtype
= 0;
566 ancp_info
->ancp_adjcode
= 0;
568 ti
= proto_tree_add_item(tree
, proto_ancp
, tvb
, 0, -1, ENC_NA
);
570 ancp_tree
= proto_item_add_subtree(ti
, ett_ancp_len
);
572 offset
= 2; /* skip ether type */
574 proto_tree_add_item(ancp_tree
, hf_ancp_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
577 sti
= proto_tree_add_item(ancp_tree
, hf_ancp_ver
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
578 byte
= tvb_get_guint8(tvb
, offset
);
580 proto_item_append_text(sti
, " (%d.%d)", byte
>> 4, byte
& 0x0F);
582 sti
= proto_tree_add_item(ancp_tree
, hf_ancp_mtype
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
583 mtype
= tvb_get_guint8(tvb
, offset
); /* ANCP message type */
584 ancp_info
->ancp_mtype
= mtype
; /* stats */
587 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s Message",
588 val_to_str(mtype
, mtype_names
, "Unknown (0x%02x)"));
590 if (mtype
!= ANCP_MTYPE_ADJ
) {
591 /* Dissect common header */
592 proto_tree_add_item(ancp_tree
, hf_ancp_result
, tvb
, offset
, 1,
593 ENC_BIG_ENDIAN
); /* treat as 1B, but dont change offset */
595 proto_tree_add_item(ancp_tree
, hf_ancp_code
, tvb
, offset
, 2,
599 proto_tree_add_item(ancp_tree
, hf_ancp_p_id
, tvb
, offset
,
603 proto_tree_add_item(ancp_tree
, hf_ancp_trans_id
, tvb
,
604 offset
, 3, ENC_BIG_ENDIAN
);
607 proto_tree_add_item(ancp_tree
, hf_ancp_i_flag
, tvb
, offset
, 1,
608 ENC_BIG_ENDIAN
); /* treat as 1B, but dont change offset */
610 sti
= proto_tree_add_item(ancp_tree
, hf_ancp_submsg_num
, tvb
,
611 offset
, 2, ENC_BIG_ENDIAN
);
615 * Lets not display the 'Length' field now, it is anyway same
617 * which we have already displayed at the start of the dissect
619 offset
+= 2; /* Length */
624 dissect_ancp_adj_msg(tvb
, pinfo
, ancp_tree
, offset
, ancp_info
);
626 case ANCP_MTYPE_PORT_DN
:
628 case ANCP_MTYPE_PORT_MGMT
:
630 case ANCP_MTYPE_PORT_UP
:
631 dissect_ancp_port_up_dn_mgmt(tvb
, ancp_tree
, offset
);
634 proto_item_append_text(sti
, " (Unknown Message %d)", mtype
);
637 tap_queue_packet(ancp_tap
, pinfo
, ancp_info
);
639 return tvb_length(tvb
);
643 get_ancp_msg_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
)
645 return (guint
)tvb_get_ntohs(tvb
, offset
+ 2) + 4; /* 2B len + 4B hdr */
649 dissect_ancp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
651 tcp_dissect_pdus(tvb
, pinfo
, tree
, TRUE
, ANCP_MIN_HDR
,
652 get_ancp_msg_len
, dissect_ancp_message
, data
);
654 return tvb_length(tvb
);
658 proto_register_ancp(void)
660 static hf_register_info hf
[] = {
662 { "Length", "ancp.len",
668 { "Version", "ancp.ver",
674 { "Message Type", "ancp.mtype",
676 VALS(mtype_names
), 0x0,
680 { "Timer", "ancp.timer",
686 { "Code", "ancp.adjcode", /* this is diff from code */
687 FT_UINT8
, BASE_DEC
, /* for Adjacency msg only */
691 { &hf_ancp_sender_name
,
692 { "Sender Name", "ancp.sender_name",
697 { &hf_ancp_receiver_name
,
698 { "Receiver Name", "ancp.receiver_name",
703 { &hf_ancp_sender_port
,
704 { "Sender Port", "ancp.sender_port",
709 { &hf_ancp_receiver_port
,
710 { "Receiver Port", "ancp.receiver_port",
716 { "Partition Info", "ancp.partition_info",
721 { &hf_ancp_sender_instance
,
722 { "Sender Instance", "ancp.sender_instance",
728 { "Partition ID", "ancp.partition_id",
733 { &hf_ancp_receiver_instance
,
734 { "Receiver Instance", "ancp.receiver_instance",
739 { &hf_ancp_tech_type
,
740 { "Tech Type", "ancp.tech_type",
742 VALS(techtype_str
), 0x0,
746 { "Num TLVs", "ancp.num_tlvs",
752 { "Length", "ancp.tot_len", /* name just Len to reuse*/
758 { "Capability", "ancp.capability",
760 VALS(captype_names
), 0x0,
764 { "Result", "ancp.result",
766 VALS(resulttype_names
), ANCP_RESULT_MASK
,
770 { "Code", "ancp.code",
772 VALS(codetype_names
), ANCP_CODE_MASK
,
776 { "Transaction ID", "ancp.transaction_id",
782 { "I Flag", "ancp.i_flag",
784 TFS(&tfs_set_notset
), ANCP_I_FLAG_MASK
,
787 { &hf_ancp_submsg_num
,
788 { "SubMessage Number", "ancp.submessage_number",
790 NULL
, ANCP_SUBMSG_MASK
,
794 { "Port", "ancp.port",
799 { &hf_ancp_port_sess_num
,
800 { "Port Session Number", "ancp.port_sess_num",
805 { &hf_ancp_evt_seq_num
,
806 { "Event Sequence Number", "ancp.evt_seq_num",
812 { "Label", "ancp.label", /* Not used in proto */
818 { "Reserved", "ancp.reserved",
824 { "Block Length", "ancp.blk_len",
829 { &hf_ancp_num_ext_tlvs
,
830 { "Num TLVs", "ancp.ext_tlvs.count",
835 { &hf_ancp_ext_tlv_type
,
836 { "TLV", "ancp.ext_tlv.type",
838 VALS(ext_tlv_types
), 0x0,
841 { &hf_ancp_dsl_line_stlv_type
,
842 { "Sub-TLV", "ancp.sub_tlv_type",
844 VALS(dsl_line_attrs
), 0x0,
847 { &hf_ancp_dsl_line_stlv_value
,
848 { "Value", "ancp.dsl_line_param",
853 { &hf_ancp_ext_tlv_value_str
,
854 { "Value", "ancp.ext_tlv.value",
855 FT_STRING
, BASE_NONE
,
859 { &hf_ancp_oam_opaque
,
860 { "Opaque", "ancp.oam.opaque", /* There will be 2 such 32b vals */
865 { &hf_ancp_oam_loopb_cnt
,
866 { "OAM Loopback Count", "ancp.oam.loopback_count",
871 { &hf_ancp_oam_timeout
,
872 { "OAM Timeout", "ancp.oam.timeout",
879 /* Setup protocol subtree array */
880 static gint
*ett
[] = {
886 &ett_ancp_sender_name
,
887 &ett_ancp_receiver_name
,
888 &ett_ancp_sender_port
,
889 &ett_ancp_receiver_port
,
891 &ett_ancp_sender_instance
,
893 &ett_ancp_receiver_instance
,
902 &ett_ancp_submsg_num
,
904 &ett_ancp_port_sess_num
,
905 &ett_ancp_evt_seq_num
,
909 &ett_ancp_num_ext_tlvs
,
910 &ett_ancp_ext_tlv_type
,
911 &ett_ancp_dsl_line_stlv_type
,
912 &ett_ancp_dsl_line_stlv_val
,
913 &ett_ancp_ext_tlv_value_str
,
914 &ett_ancp_oam_opaque
,
915 &ett_ancp_oam_loopb_cnt
,
916 &ett_ancp_oam_timeout
,
919 proto_ancp
= proto_register_protocol (
920 "Access Node Control Protocol",
925 proto_register_field_array(proto_ancp
, hf
, array_length(hf
));
926 proto_register_subtree_array(ett
, array_length(ett
));
927 ancp_tap
= register_tap("ancp");
931 proto_reg_handoff_ancp(void)
933 dissector_handle_t ancp_handle
;
935 ancp_handle
= new_create_dissector_handle(dissect_ancp
, proto_ancp
);
936 dissector_add_uint("tcp.port", ANCP_PORT
, ancp_handle
);
937 stats_tree_register("ancp", "ancp", "ANCP", 0,
938 ancp_stats_tree_packet
, ancp_stats_tree_init
, NULL
);