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