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