epan: use SPDX indentifiers.
[metze/wireshark/wip.git] / epan / osi-utils.c
1 /* osi-utils.c
2  * Routines for ISO/OSI network and transport protocol packet disassembly
3  * Main entrance point and common functions
4  *
5  * Laurent Deniel <laurent.deniel@free.fr>
6  * Ralf Schneider <Ralf.Schneider@t-online.de>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * SPDX-License-Identifier: GPL-2.0-or-later
13  */
14
15 #include "config.h"
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <glib.h>
20
21 #include "tvbuff.h"
22 #include "osi-utils.h"
23 #include "address.h"
24 #include "address_types.h"
25
26 static void print_nsap_net_buf( const guint8 *, int, gchar *, int);
27 static void print_area_buf ( const guint8 *, int, gchar *, int);
28 static void print_address_prefix_buf ( const guint8 *, int, gchar *, int);
29
30 /*
31  * XXX - shouldn't there be a centralized routine for dissecting NSAPs?
32  * See also "dissect_atm_nsap()" in epan/dissectors/packet-arp.c and
33  * "dissect_nsap()" in epan/dissectors/packet-isup.c.
34  */
35 gchar *
36 print_nsap_net( tvbuff_t *tvb, const gint offset, int length )
37 {
38   gchar *cur;
39
40   cur = (gchar *)wmem_alloc(wmem_packet_scope(), MAX_NSAP_LEN * 3 + 50);
41   print_nsap_net_buf( tvb_get_ptr(tvb, offset, length), length, cur, MAX_NSAP_LEN * 3 + 50);
42   return( cur );
43 }
44
45 static void
46 print_nsap_net_buf( const guint8 *ad, int length, gchar *buf, int buf_len)
47 {
48   gchar *cur;
49
50   /* to do : NSAP / NET decoding */
51
52   if ( (length <= 0 ) || ( length > MAX_NSAP_LEN ) ) {
53     g_strlcpy(buf, "<Invalid length of NSAP>", buf_len);
54     return;
55   }
56   cur = buf;
57   if ( ( length == RFC1237_NSAP_LEN ) || ( length == RFC1237_NSAP_LEN + 1 ) ) {
58     print_area_buf(ad, RFC1237_FULLAREA_LEN, cur, buf_len);
59     cur += strlen( cur );
60     print_system_id_buf( ad + RFC1237_FULLAREA_LEN, RFC1237_SYSTEMID_LEN, cur, (int) (buf_len-(cur-buf)));
61     cur += strlen( cur );
62     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x]",
63                     ad[ RFC1237_FULLAREA_LEN + RFC1237_SYSTEMID_LEN ] );
64     if ( length == RFC1237_NSAP_LEN + 1 ) {
65       g_snprintf(cur, (int) (buf_len-(cur-buf)), "-%02x", ad[ length -1 ] );
66     }
67   }
68   else {    /* probably format as standard */
69     print_area_buf( ad, length, buf, buf_len);
70   }
71 } /* print_nsap */
72
73 gchar *
74 print_system_id(wmem_allocator_t* scope, const guint8 *ad, int length )
75 {
76   gchar        *cur;
77
78   cur = (gchar *)wmem_alloc(scope, MAX_SYSTEMID_LEN * 3 + 5);
79   print_system_id_buf(ad, length, cur, MAX_SYSTEMID_LEN * 3 + 5);
80   return( cur );
81 }
82
83 gchar *
84 tvb_print_system_id( tvbuff_t *tvb, const gint offset, int length )
85 {
86   return( print_system_id(wmem_packet_scope(), tvb_get_ptr(tvb, offset, length), length) );
87 }
88
89 void
90 print_system_id_buf( const guint8 *ad, int length, gchar *buf, int buf_len)
91 {
92   gchar        *cur;
93   int           tmp;
94
95   if ( ( length <= 0 ) || ( length > MAX_SYSTEMID_LEN ) ) {
96     g_strlcpy(buf, "<Invalid length of SYSTEM ID>", buf_len);
97     return;
98   }
99
100   cur = buf;
101   if ( ( 6 == length ) || /* System-ID */
102        ( 7 == length ) || /* LAN-ID */
103        ( 8 == length )) { /* LSP-ID */
104     cur += g_snprintf(cur, buf_len, "%02x%02x.%02x%02x.%02x%02x", ad[0], ad[1],
105                     ad[2], ad[3], ad[4], ad[5] );
106     if ( ( 7 == length ) ||
107          ( 8 == length )) {
108         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), ".%02x", ad[6] );
109     }
110     if ( 8 == length ) {
111         g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-%02x", ad[7] );
112     }
113   }
114   else {
115     tmp = 0;
116     while ( tmp < length / 4 ) { /* 16 / 4 == 4 > four Octets left to print */
117       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
118       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
119       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
120       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x.", ad[tmp++] );
121     }
122     if ( 1 == tmp ) {   /* Special case for Designated IS */
123       cur--;
124       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), ".%02x", ad[tmp] );
125     }
126     else {
127       for ( ; tmp < length; ) {  /* print the rest without dot */
128         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
129       }
130     }
131   }
132 }
133
134 gchar *
135 print_area(tvbuff_t *tvb, const gint offset, int length)
136 {
137   gchar *cur;
138
139   cur = (gchar *)wmem_alloc(wmem_packet_scope(), MAX_AREA_LEN * 3 + 20);
140   print_area_buf(tvb_get_ptr(tvb, offset, length), length, cur, MAX_AREA_LEN * 3 + 20);
141   return cur;
142 }
143
144 /*
145  * Note: length is in units of half-octets.
146  */
147 gchar *
148 print_address_prefix(tvbuff_t *tvb, const gint offset, int length)
149 {
150   gchar *cur;
151
152   cur = (gchar *)wmem_alloc(wmem_packet_scope(), MAX_AREA_LEN * 3 + 20);
153   print_address_prefix_buf(tvb_get_ptr(tvb, offset, (length+1)/2), length, cur, MAX_AREA_LEN * 3 + 20);
154   return cur;
155 }
156
157 /*
158  * Note: length is in units of octets.
159  */
160 static void
161 print_area_buf(const guint8 *ad, int length, gchar *buf, int buf_len)
162 {
163   print_address_prefix_buf(ad, length*2, buf, buf_len);
164 }
165
166 /*
167  * Note: length is in units of half-octets.
168  */
169 static void
170 print_address_prefix_buf(const guint8 *ad, int length, gchar *buf, int buf_len)
171 {
172   gchar *cur;
173   int  tmp  = 0;
174
175   /* to do : all real area decoding now: NET is assumed if id len is 1 more byte
176    */
177   if (length <= 0 || length > MAX_AREA_LEN*2) {
178     g_strlcpy(buf, "<Invalid length of AREA>", buf_len);
179     return;
180   }
181
182   cur = buf;
183   if ( (  ( NSAP_IDI_ISO_DCC_BIN      == *ad )
184        || ( NSAP_IDI_ISO_6523_ICD_BIN == *ad )
185        )
186        &&
187        (  ( RFC1237_FULLAREA_LEN*2       ==  length )
188        || ( (RFC1237_FULLAREA_LEN + 1)*2 ==  length )
189        )
190      ) {    /* AFI is good and length is long enough  */
191
192     /* there used to be a check for (length > RFC1237_FULLAREA_LEN + 1) here,
193      * in order to report an invalied length of AREA for DCC / ISO 6523 AFI,
194      * but that can *never* be the case because the if() test above explicitly
195      * tests for (length == RFC1237_FULLAREA_LEN) or (length == RFC1237_FULLAREA_LEN + 1)
196      */
197
198     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x|%02x:%02x][%02x|%02x:%02x:%02x|%02x:%02x]",
199                     ad[0], ad[1], ad[2], ad[3], ad[4],
200                     ad[5], ad[6], ad[7], ad[8] );
201     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x:%02x|%02x:%02x]",
202                     ad[9], ad[10],  ad[11], ad[12] );
203     if ( (RFC1237_FULLAREA_LEN + 1)*2 == length )
204       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-[%02x]", ad[20] );
205   }
206   else { /* print standard format */
207     if ( length == RFC1237_AREA_LEN*2 ) {
208       g_snprintf(buf, buf_len, "%02x.%02x%02x", ad[0], ad[1], ad[2] );
209       return;
210     }
211     if ( length == 4*2 ) {
212       g_snprintf(buf, buf_len, "%02x%02x%02x%02x", ad[0], ad[1], ad[2], ad[3] );
213       return;
214     }
215     while ( tmp < length / 8 ) {      /* 32/8==4 > four Octets left to print */
216       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
217       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
218       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
219       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x.", ad[tmp++] );
220     }
221     if ( 2 == tmp ) {                     /* Special case for Designated IS */
222       cur--;
223       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-%02x", ad[tmp] );
224     }
225     else {
226       for ( ; tmp < length / 2; ) {  /* print the rest without dot or dash */
227         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
228       }
229       /* Odd half-octet? */
230       if (length & 1) {
231         /* Yes - print it (it's the upper half-octet) */
232         g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%x", (ad[tmp] & 0xF0)>>4 );
233       }
234     }
235   }
236 } /* print_address_prefix_buf */
237
238 /******************************************************************************
239  * OSI Address Type
240  ******************************************************************************/
241 static int osi_address_type = -1;
242
243 static int osi_address_to_str(const address* addr, gchar *buf, int buf_len)
244 {
245     print_nsap_net_buf((const guint8 *)addr->data, addr->len, buf, buf_len);
246     return (int)strlen(buf)+1;
247 }
248
249 static int osi_address_str_len(const address* addr _U_)
250 {
251     return MAX_NSAP_LEN * 3 + 50;
252 }
253
254 int get_osi_address_type(void)
255 {
256     return osi_address_type;
257 }
258
259 void register_osi_address_type(void)
260 {
261     if (osi_address_type != -1)
262         return;
263
264     osi_address_type = address_type_dissector_register("AT_OSI", "OSI Address", osi_address_to_str, osi_address_str_len, NULL, NULL, NULL, NULL, NULL);
265 }
266
267
268 /*
269  * Editor modelines
270  *
271  * Local Variables:
272  * c-basic-offset: 2
273  * tab-width: 8
274  * indent-tabs-mode: nil
275  * End:
276  *
277  * ex: set shiftwidth=2 tabstop=8 expandtab:
278  * :indentSize=2:tabSize=8:noTabs=true:
279  */