/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 | | */ |