print-m3ua.c revision 1.7
1/* Copyright (c) 2013, The TCPDUMP project
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this
8 *    list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright notice,
10 *    this list of conditions and the following disclaimer in the documentation
11 *    and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include <sys/cdefs.h>
26#ifndef lint
27__RCSID("$NetBSD: print-m3ua.c,v 1.7 2023/08/17 20:19:40 christos Exp $");
28#endif
29
30/* \summary: Message Transfer Part 3 (MTP3) User Adaptation Layer (M3UA) printer */
31
32/* RFC 4666 */
33
34#ifdef HAVE_CONFIG_H
35#include <config.h>
36#endif
37
38#include "netdissect-stdinc.h"
39
40#define ND_LONGJMP_FROM_TCHECK
41#include "netdissect.h"
42#include "extract.h"
43
44
45#define M3UA_REL_1_0 1
46
47struct m3ua_common_header {
48  nd_uint8_t  v;
49  nd_uint8_t  reserved;
50  nd_uint8_t  msg_class;
51  nd_uint8_t  msg_type;
52  nd_uint32_t len;
53};
54
55struct m3ua_param_header {
56  nd_uint16_t tag;
57  nd_uint16_t len;
58};
59
60/* message classes */
61#define M3UA_MSGC_MGMT 0
62#define M3UA_MSGC_TRANSFER 1
63#define M3UA_MSGC_SSNM 2
64#define M3UA_MSGC_ASPSM 3
65#define M3UA_MSGC_ASPTM 4
66/* reserved values */
67#define M3UA_MSGC_RKM 9
68
69static const struct tok MessageClasses[] = {
70	{ M3UA_MSGC_MGMT,     "Management"            },
71	{ M3UA_MSGC_TRANSFER, "Transfer"              },
72	{ M3UA_MSGC_SSNM,     "SS7"                   },
73	{ M3UA_MSGC_ASPSM,    "ASP"                   },
74	{ M3UA_MSGC_ASPTM,    "ASP"                   },
75	{ M3UA_MSGC_RKM,      "Routing Key Management"},
76	{ 0, NULL }
77};
78
79/* management messages */
80#define M3UA_MGMT_ERROR 0
81#define M3UA_MGMT_NOTIFY 1
82
83static const struct tok MgmtMessages[] = {
84  { M3UA_MGMT_ERROR, "Error" },
85  { M3UA_MGMT_NOTIFY, "Notify" },
86  { 0, NULL }
87};
88
89/* transfer messages */
90#define M3UA_TRANSFER_DATA 1
91
92static const struct tok TransferMessages[] = {
93  { M3UA_TRANSFER_DATA, "Data" },
94  { 0, NULL }
95};
96
97/* SS7 Signaling Network Management messages */
98#define M3UA_SSNM_DUNA 1
99#define M3UA_SSNM_DAVA 2
100#define M3UA_SSNM_DAUD 3
101#define M3UA_SSNM_SCON 4
102#define M3UA_SSNM_DUPU 5
103#define M3UA_SSNM_DRST 6
104
105static const struct tok SS7Messages[] = {
106  { M3UA_SSNM_DUNA, "Destination Unavailable" },
107  { M3UA_SSNM_DAVA, "Destination Available" },
108  { M3UA_SSNM_DAUD, "Destination State Audit" },
109  { M3UA_SSNM_SCON, "Signalling Congestion" },
110  { M3UA_SSNM_DUPU, "Destination User Part Unavailable" },
111  { M3UA_SSNM_DRST, "Destination Restricted" },
112  { 0, NULL }
113};
114
115/* ASP State Maintenance messages */
116#define M3UA_ASP_UP 1
117#define M3UA_ASP_DN 2
118#define M3UA_ASP_BEAT 3
119#define M3UA_ASP_UP_ACK 4
120#define M3UA_ASP_DN_ACK 5
121#define M3UA_ASP_BEAT_ACK 6
122
123static const struct tok ASPStateMessages[] = {
124  { M3UA_ASP_UP, "Up" },
125  { M3UA_ASP_DN, "Down" },
126  { M3UA_ASP_BEAT, "Heartbeat" },
127  { M3UA_ASP_UP_ACK, "Up Acknowledgement" },
128  { M3UA_ASP_DN_ACK, "Down Acknowledgement" },
129  { M3UA_ASP_BEAT_ACK, "Heartbeat Acknowledgement" },
130  { 0, NULL }
131};
132
133/* ASP Traffic Maintenance messages */
134#define M3UA_ASP_AC 1
135#define M3UA_ASP_IA 2
136#define M3UA_ASP_AC_ACK 3
137#define M3UA_ASP_IA_ACK 4
138
139static const struct tok ASPTrafficMessages[] = {
140  { M3UA_ASP_AC, "Active" },
141  { M3UA_ASP_IA, "Inactive" },
142  { M3UA_ASP_AC_ACK, "Active Acknowledgement" },
143  { M3UA_ASP_IA_ACK, "Inactive Acknowledgement" },
144  { 0, NULL }
145};
146
147/* Routing Key Management messages */
148#define M3UA_RKM_REQ 1
149#define M3UA_RKM_RSP 2
150#define M3UA_RKM_DEREQ 3
151#define M3UA_RKM_DERSP 4
152
153static const struct tok RoutingKeyMgmtMessages[] = {
154  { M3UA_RKM_REQ, "Registration Request" },
155  { M3UA_RKM_RSP, "Registration Response" },
156  { M3UA_RKM_DEREQ, "Deregistration Request" },
157  { M3UA_RKM_DERSP, "Deregistration Response" },
158  { 0, NULL }
159};
160
161static const struct uint_tokary m3ua_msgc2tokary[] = {
162	{ M3UA_MSGC_MGMT,     MgmtMessages           },
163	{ M3UA_MSGC_TRANSFER, TransferMessages       },
164	{ M3UA_MSGC_SSNM,     SS7Messages            },
165	{ M3UA_MSGC_ASPSM,    ASPStateMessages       },
166	{ M3UA_MSGC_ASPTM,    ASPTrafficMessages     },
167	{ M3UA_MSGC_RKM,      RoutingKeyMgmtMessages },
168	/* uint2tokary() does not use array termination. */
169};
170
171/* M3UA Parameters */
172#define M3UA_PARAM_INFO 0x0004
173#define M3UA_PARAM_ROUTING_CTX 0x0006
174#define M3UA_PARAM_DIAGNOSTIC 0x0007
175#define M3UA_PARAM_HB_DATA 0x0009
176#define M3UA_PARAM_TRAFFIC_MODE_TYPE 0x000b
177#define M3UA_PARAM_ERROR_CODE 0x000c
178#define M3UA_PARAM_STATUS 0x000d
179#define M3UA_PARAM_ASP_ID 0x0011
180#define M3UA_PARAM_AFFECTED_POINT_CODE 0x0012
181#define M3UA_PARAM_CORR_ID 0x0013
182
183#define M3UA_PARAM_NETWORK_APPEARANCE 0x0200
184#define M3UA_PARAM_USER 0x0204
185#define M3UA_PARAM_CONGESTION_INDICATION 0x0205
186#define M3UA_PARAM_CONCERNED_DST 0x0206
187#define M3UA_PARAM_ROUTING_KEY 0x0207
188#define M3UA_PARAM_REG_RESULT 0x0208
189#define M3UA_PARAM_DEREG_RESULT 0x0209
190#define M3UA_PARAM_LOCAL_ROUTING_KEY_ID 0x020a
191#define M3UA_PARAM_DST_POINT_CODE 0x020b
192#define M3UA_PARAM_SI 0x020c
193#define M3UA_PARAM_ORIGIN_POINT_CODE_LIST 0x020e
194#define M3UA_PARAM_PROTO_DATA 0x0210
195#define M3UA_PARAM_REG_STATUS 0x0212
196#define M3UA_PARAM_DEREG_STATUS 0x0213
197
198static const struct tok ParamName[] = {
199  { M3UA_PARAM_INFO, "INFO String" },
200  { M3UA_PARAM_ROUTING_CTX, "Routing Context" },
201  { M3UA_PARAM_DIAGNOSTIC, "Diagnostic Info" },
202  { M3UA_PARAM_HB_DATA, "Heartbeat Data" },
203  { M3UA_PARAM_TRAFFIC_MODE_TYPE, "Traffic Mode Type" },
204  { M3UA_PARAM_ERROR_CODE, "Error Code" },
205  { M3UA_PARAM_STATUS, "Status" },
206  { M3UA_PARAM_ASP_ID, "ASP Identifier" },
207  { M3UA_PARAM_AFFECTED_POINT_CODE, "Affected Point Code" },
208  { M3UA_PARAM_CORR_ID, "Correlation ID" },
209  { M3UA_PARAM_NETWORK_APPEARANCE, "Network Appearance" },
210  { M3UA_PARAM_USER, "User/Cause" },
211  { M3UA_PARAM_CONGESTION_INDICATION, "Congestion Indications" },
212  { M3UA_PARAM_CONCERNED_DST, "Concerned Destination" },
213  { M3UA_PARAM_ROUTING_KEY, "Routing Key" },
214  { M3UA_PARAM_REG_RESULT, "Registration Result" },
215  { M3UA_PARAM_DEREG_RESULT, "Deregistration Result" },
216  { M3UA_PARAM_LOCAL_ROUTING_KEY_ID, "Local Routing Key Identifier" },
217  { M3UA_PARAM_DST_POINT_CODE, "Destination Point Code" },
218  { M3UA_PARAM_SI, "Service Indicators" },
219  { M3UA_PARAM_ORIGIN_POINT_CODE_LIST, "Originating Point Code List" },
220  { M3UA_PARAM_PROTO_DATA, "Protocol Data" },
221  { M3UA_PARAM_REG_STATUS, "Registration Status" },
222  { M3UA_PARAM_DEREG_STATUS, "Deregistration Status" },
223  { 0, NULL }
224};
225
226static void
227tag_value_print(netdissect_options *ndo,
228                const u_char *buf, const uint16_t tag, const uint16_t size)
229{
230  switch (tag) {
231  case M3UA_PARAM_NETWORK_APPEARANCE:
232  case M3UA_PARAM_ROUTING_CTX:
233  case M3UA_PARAM_CORR_ID:
234    /* buf and size don't include the header */
235    if (size < 4)
236      goto invalid;
237    ND_PRINT("0x%08x", GET_BE_U_4(buf));
238    break;
239  /* ... */
240  default:
241    ND_PRINT("(length %zu)", size + sizeof(struct m3ua_param_header));
242  }
243  ND_TCHECK_LEN(buf, size);
244  return;
245
246invalid:
247  nd_print_invalid(ndo);
248  ND_TCHECK_LEN(buf, size);
249}
250
251/*
252 *     0                   1                   2                   3
253 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
254 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
255 *    |          Parameter Tag        |       Parameter Length        |
256 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
257 *    \                                                               \
258 *    /                       Parameter Value                         /
259 *    \                                                               \
260 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
261 */
262static void
263m3ua_tags_print(netdissect_options *ndo,
264                const u_char *buf, const u_int size)
265{
266  const u_char *p = buf;
267  int align;
268  uint16_t hdr_tag;
269  uint16_t hdr_len;
270
271  while (p < buf + size) {
272    if (p + sizeof(struct m3ua_param_header) > buf + size)
273      goto invalid;
274    /* Parameter Tag */
275    hdr_tag = GET_BE_U_2(p);
276    ND_PRINT("\n\t\t\t%s: ", tok2str(ParamName, "Unknown Parameter (0x%04x)", hdr_tag));
277    /* Parameter Length */
278    hdr_len = GET_BE_U_2(p + 2);
279    if (hdr_len < sizeof(struct m3ua_param_header))
280      goto invalid;
281    /* Parameter Value */
282    align = (p + hdr_len - buf) % 4;
283    align = align ? 4 - align : 0;
284    ND_TCHECK_LEN(p, hdr_len + align);
285    tag_value_print(ndo, p, hdr_tag, hdr_len - sizeof(struct m3ua_param_header));
286    p += hdr_len + align;
287  }
288  return;
289
290invalid:
291  nd_print_invalid(ndo);
292  ND_TCHECK_LEN(buf, size);
293}
294
295/*
296 *     0                   1                   2                   3
297 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
298 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
299 *    |    Version    |   Reserved    | Message Class | Message Type  |
300 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
301 *    |                        Message Length                         |
302 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
303 *    \                                                               \
304 *    /                                                               /
305 */
306UNALIGNED_OK
307void
308m3ua_print(netdissect_options *ndo,
309           const u_char *buf, const u_int size)
310{
311  const struct m3ua_common_header *hdr = (const struct m3ua_common_header *) buf;
312  const struct tok *dict;
313  uint8_t msg_class;
314
315  ndo->ndo_protocol = "m3ua";
316  /* size includes the header */
317  if (size < sizeof(struct m3ua_common_header))
318    goto invalid;
319  ND_TCHECK_SIZE(hdr);
320  if (GET_U_1(hdr->v) != M3UA_REL_1_0)
321    return;
322
323  msg_class = GET_U_1(hdr->msg_class);
324  dict = uint2tokary(m3ua_msgc2tokary, msg_class);
325
326  ND_PRINT("\n\t\t%s", tok2str(MessageClasses, "Unknown message class %i", msg_class));
327  if (dict != NULL)
328    ND_PRINT(" %s Message",
329             tok2str(dict, "Unknown (0x%02x)", GET_U_1(hdr->msg_type)));
330
331  if (size != GET_BE_U_4(hdr->len))
332    ND_PRINT("\n\t\t\t@@@@@@ Corrupted length %u of message @@@@@@",
333             GET_BE_U_4(hdr->len));
334  else
335    m3ua_tags_print(ndo, buf + sizeof(struct m3ua_common_header),
336                    GET_BE_U_4(hdr->len) - sizeof(struct m3ua_common_header));
337  return;
338
339invalid:
340  nd_print_invalid(ndo);
341  ND_TCHECK_LEN(buf, size);
342}
343