Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/osi-utils.c
Line
Count
Source
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 uint8_t *, int, char *, int);
27
static void print_area_buf ( const uint8_t *, int, char *, int);
28
static void print_address_prefix_buf ( const uint8_t *, int, char *, 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
char *
36
print_nsap_net( wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length )
37
2.42k
{
38
2.42k
  char *cur;
39
40
2.42k
  cur = (char *)wmem_alloc(scope, MAX_NSAP_LEN * 3 + 50);
41
2.42k
  print_nsap_net_buf( tvb_get_ptr(tvb, offset, length), length, cur, MAX_NSAP_LEN * 3 + 50);
42
2.42k
  return( cur );
43
2.42k
}
44
45
static void
46
print_nsap_net_buf( const uint8_t *ad, int length, char *buf, int buf_len)
47
2.36k
{
48
2.36k
  char *cur;
49
50
  /* to do : NSAP / NET decoding */
51
52
2.36k
  if ( (length <= 0 ) || ( length > MAX_NSAP_LEN ) ) {
53
1.33k
    (void) g_strlcpy(buf, "<Invalid length of NSAP>", buf_len);
54
1.33k
    return;
55
1.33k
  }
56
1.02k
  cur = buf;
57
1.02k
  if ( ( length == RFC1237_NSAP_LEN ) || ( length == RFC1237_NSAP_LEN + 1 ) ) {
58
87
    print_area_buf(ad, RFC1237_FULLAREA_LEN, cur, buf_len);
59
87
    cur += strlen( cur );
60
87
    print_system_id_buf( ad + RFC1237_FULLAREA_LEN, RFC1237_SYSTEMID_LEN, cur, (int) (buf_len-(cur-buf)));
61
87
    cur += strlen( cur );
62
87
    cur += snprintf(cur, buf_len-(cur-buf), "[%02x]",
63
87
                    ad[ RFC1237_FULLAREA_LEN + RFC1237_SYSTEMID_LEN ] );
64
87
    if ( length == RFC1237_NSAP_LEN + 1 ) {
65
23
      snprintf(cur, (int) (buf_len-(cur-buf)), "-%02x", ad[ length -1 ] );
66
23
    }
67
87
  }
68
941
  else {    /* probably format as standard */
69
    /* XXX - this is an NSAP, not an area address/address prefix */
70
941
    print_area_buf( ad, length, buf, buf_len);
71
941
  }
72
1.02k
} /* print_nsap */
73
74
char *
75
print_system_id(wmem_allocator_t* scope, const uint8_t *ad, int length )
76
5.52k
{
77
5.52k
  char         *cur;
78
79
5.52k
  cur = (char *)wmem_alloc(scope, MAX_SYSTEMID_LEN * 3 + 5);
80
5.52k
  print_system_id_buf(ad, length, cur, MAX_SYSTEMID_LEN * 3 + 5);
81
5.52k
  return( cur );
82
5.52k
}
83
84
char *
85
tvb_print_system_id( wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length )
86
5.52k
{
87
5.52k
  return( print_system_id(scope, tvb_get_ptr(tvb, offset, length), length) );
88
5.52k
}
89
90
void
91
print_system_id_buf( const uint8_t *ad, int length, char *buf, int buf_len)
92
5.61k
{
93
5.61k
  char         *cur;
94
5.61k
  int           tmp;
95
96
5.61k
  if ( ( length <= 0 ) || ( length > MAX_SYSTEMID_LEN ) ) {
97
734
    (void) g_strlcpy(buf, "<Invalid length of SYSTEM ID>", buf_len);
98
734
    return;
99
734
  }
100
101
4.87k
  cur = buf;
102
4.87k
  if ( ( 6 == length ) || /* System-ID */
103
4.54k
       ( 7 == length ) || /* LAN-ID */
104
2.79k
       ( 8 == length )) { /* LSP-ID */
105
2.31k
    cur += snprintf(cur, buf_len, "%02x%02x.%02x%02x.%02x%02x", ad[0], ad[1],
106
2.31k
                    ad[2], ad[3], ad[4], ad[5] );
107
2.31k
    if ( ( 7 == length ) ||
108
1.98k
         ( 8 == length )) {
109
1.98k
        cur += snprintf(cur, buf_len-(cur-buf), ".%02x", ad[6] );
110
1.98k
    }
111
2.31k
    if ( 8 == length ) {
112
231
        snprintf(cur, buf_len-(cur-buf), "-%02x", ad[7] );
113
231
    }
114
2.31k
  }
115
2.56k
  else {
116
2.56k
    tmp = 0;
117
3.18k
    while ( tmp < length / 4 ) { /* 16 / 4 == 4 > four Octets left to print */
118
619
      cur += snprintf(cur, buf_len-(cur-buf), "%02x", ad[tmp++] );
119
619
      cur += snprintf(cur, buf_len-(cur-buf), "%02x", ad[tmp++] );
120
619
      cur += snprintf(cur, buf_len-(cur-buf), "%02x", ad[tmp++] );
121
619
      cur += snprintf(cur, buf_len-(cur-buf), "%02x.", ad[tmp++] );
122
619
    }
123
2.56k
    if ( 1 == tmp ) {   /* Special case for Designated IS */
124
0
      cur--;
125
0
      snprintf(cur, buf_len-(cur-buf), ".%02x", ad[tmp] );
126
0
    }
127
2.56k
    else {
128
7.29k
      for ( ; tmp < length; ) {  /* print the rest without dot */
129
4.72k
        cur += snprintf(cur, buf_len-(cur-buf), "%02x", ad[tmp++] );
130
4.72k
      }
131
2.56k
    }
132
2.56k
  }
133
4.87k
}
134
135
char *
136
print_area(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length)
137
14
{
138
14
  char *cur;
139
140
14
  cur = (char *)wmem_alloc(scope, MAX_AREA_LEN * 3 + 20);
141
14
  print_area_buf(tvb_get_ptr(tvb, offset, length), length, cur, MAX_AREA_LEN * 3 + 20);
142
14
  return cur;
143
14
}
144
145
/*
146
 * Note: length is in units of half-octets.
147
 */
148
char *
149
print_address_prefix(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length)
150
721
{
151
721
  char *cur;
152
153
721
  cur = (char *)wmem_alloc(scope, MAX_AREA_LEN * 3 + 20);
154
721
  print_address_prefix_buf(tvb_get_ptr(tvb, offset, (length+1)/2), length, cur, MAX_AREA_LEN * 3 + 20);
155
721
  return cur;
156
721
}
157
158
/*
159
 * Note: length is in units of octets.
160
 */
161
static void
162
print_area_buf(const uint8_t *ad, int length, char *buf, int buf_len)
163
1.04k
{
164
1.04k
  print_address_prefix_buf(ad, length*2, buf, buf_len);
165
1.04k
}
166
167
/*
168
 * Note: length is in units of half-octets.
169
 */
170
static void
171
print_address_prefix_buf(const uint8_t *ad, int length, char *buf, int buf_len)
172
1.75k
{
173
1.75k
  char *cur;
174
1.75k
  int  tmp  = 0;
175
176
  /* to do : all real area decoding now: NET is assumed if id len is 1 more byte
177
   */
178
1.75k
  if (length <= 0 || length > MAX_AREA_LEN*2) {
179
394
    (void) g_strlcpy(buf, "<Invalid length of AREA>", buf_len);
180
394
    return;
181
394
  }
182
183
1.35k
  cur = buf;
184
  /* Check the AFI and length. */
185
1.35k
  if ( (  ( NSAP_IDI_ISO_DCC_BIN      == *ad )
186
1.34k
       || ( NSAP_IDI_ISO_6523_ICD_BIN == *ad )
187
1.35k
       )
188
26
       &&
189
26
       (  ( RFC1237_FULLAREA_LEN*2       ==  length )
190
24
       || ( (RFC1237_FULLAREA_LEN + 1)*2 ==  length )
191
26
       )
192
1.35k
     ) {    /* AFI is good and length is long enough  */
193
194
    /* The AFI is either ISO DCC, binary or ISO 6523-ICD, binary,
195
     * and the area length corresponds either to the area length
196
     * for RFC 1237 (GOSIP) addresses or that length + 1.
197
     *
198
     * XXX - RFC 1237 doesn't mention ISO DCC, binary, as a valid
199
     * AFI; is that from GOSIP Version 1?  If it's ISO DCC, binary,
200
     * the IDI is 3 digits, i.e. 1 1/2 octets.
201
     */
202
    /* there used to be a check for (length > RFC1237_FULLAREA_LEN + 1) here,
203
     * in order to report an invalid length of AREA for DCC / ISO 6523 AFI,
204
     * but that can *never* be the case because the if() test above explicitly
205
     * tests for (length == RFC1237_FULLAREA_LEN) or (length == RFC1237_FULLAREA_LEN + 1)
206
     */
207
208
    /* Show the one-octet AFI, the two-octet IDI, the one-octet DFI, the
209
     * 3-octet AA, and the 2 reserved octets.
210
     */
211
2
    cur += snprintf(cur, buf_len-(cur-buf), "[%02x|%02x:%02x][%02x|%02x:%02x:%02x|%02x:%02x]",
212
2
                    ad[0], ad[1], ad[2], ad[3], ad[4],
213
2
                    ad[5], ad[6], ad[7], ad[8] );
214
    /* Show the 2-octet RD and the 2-octet Area. */
215
2
    cur += snprintf(cur, buf_len-(cur-buf), "[%02x:%02x|%02x:%02x]",
216
2
                    ad[9], ad[10],  ad[11], ad[12] );
217
    /* Show whatever the heck this is; it's not specified by RFC 1237,
218
     * but we also handle 14-octet areas.  Is it the "Designated IS"
219
     * stuff mentioned below?  (I didn't find anything in the IS-IS
220
     * spec about that.)
221
     */
222
2
    if ( (RFC1237_FULLAREA_LEN + 1)*2 == length )
223
2
      snprintf(cur, buf_len-(cur-buf), "-[%02x]", ad[13] );
224
2
  }
225
1.35k
  else {
226
    /* This doesn't look like a full RFC 1237 IS-IS area, so all we know
227
     * is that the first octet is an AFI.  Print it separately from all
228
     * the other octets.
229
     */
230
1.35k
    if ( length == RFC1237_AREA_LEN*2 ) {
231
      /* XXX - RFC1237_AREA_LEN, which is 3 octets, doesn't seem to
232
       * correspond to anything in RFC 1237.  Where did it come from?
233
       */
234
86
      snprintf(buf, buf_len, "%02x.%02x%02x", ad[0], ad[1], ad[2] );
235
86
      return;
236
86
    }
237
1.26k
    if ( length == 4*2 ) {
238
105
      snprintf(buf, buf_len, "%02x%02x%02x%02x", ad[0], ad[1], ad[2], ad[3] );
239
105
      return;
240
105
    }
241
1.77k
    while ( tmp < length / 8 ) {      /* 32/8==4 > four Octets left to print */
242
606
      cur += snprintf(cur, buf_len-(cur-buf), "%02x", ad[tmp++] );
243
606
      cur += snprintf(cur, buf_len-(cur-buf), "%02x", ad[tmp++] );
244
606
      cur += snprintf(cur, buf_len-(cur-buf), "%02x", ad[tmp++] );
245
606
      cur += snprintf(cur, buf_len-(cur-buf), "%02x.", ad[tmp++] );
246
606
    }
247
1.16k
    if ( 2 == tmp ) {                     /* Special case for Designated IS */
248
0
      cur--;
249
0
      snprintf(cur, buf_len-(cur-buf), "-%02x", ad[tmp] );
250
0
    }
251
1.16k
    else {
252
5.09k
      for ( ; tmp < length / 2; ) {  /* print the rest without dot or dash */
253
3.93k
        cur += snprintf(cur, buf_len-(cur-buf), "%02x", ad[tmp++] );
254
3.93k
      }
255
      /* Odd half-octet? */
256
1.16k
      if (length & 1) {
257
        /* Yes - print it (it's the upper half-octet) */
258
273
        snprintf(cur, buf_len-(cur-buf), "%x", (ad[tmp] & 0xF0)>>4 );
259
273
      }
260
1.16k
    }
261
1.16k
  }
262
1.35k
} /* print_address_prefix_buf */
263
264
/******************************************************************************
265
 * OSI Address Type
266
 ******************************************************************************/
267
static int osi_address_type = -1;
268
269
static int osi_address_to_str(const address* addr, char *buf, int buf_len)
270
0
{
271
0
    print_nsap_net_buf((const uint8_t *)addr->data, addr->len, buf, buf_len);
272
0
    return (int)strlen(buf)+1;
273
0
}
274
275
static int osi_address_str_len(const address* addr _U_)
276
0
{
277
0
    return MAX_NSAP_LEN * 3 + 50;
278
0
}
279
280
int get_osi_address_type(void)
281
354
{
282
354
    return osi_address_type;
283
354
}
284
285
void register_osi_address_type(void)
286
14
{
287
14
    if (osi_address_type != -1)
288
0
        return;
289
290
14
    osi_address_type = address_type_dissector_register("AT_OSI", "OSI Address", osi_address_to_str, osi_address_str_len, NULL, NULL, NULL, NULL, NULL);
291
14
}
292
293
294
/*
295
 * Editor modelines
296
 *
297
 * Local Variables:
298
 * c-basic-offset: 2
299
 * tab-width: 8
300
 * indent-tabs-mode: nil
301
 * End:
302
 *
303
 * ex: set shiftwidth=2 tabstop=8 expandtab:
304
 * :indentSize=2:tabSize=8:noTabs=true:
305
 */