EPL: Fix segmented transfer complete detection
[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 /*
39  * XXX - shouldn't there be a centralized routine for dissecting NSAPs?
40  * See also "dissect_atm_nsap()" in epan/dissectors/packet-arp.c and
41  * "dissect_nsap()" in epan/dissectors/packet-isup.c.
42  */
43 gchar *
44 print_nsap_net( tvbuff_t *tvb, const gint offset, int length )
45 {
46   gchar *cur;
47
48   cur = (gchar *)wmem_alloc(wmem_packet_scope(), MAX_NSAP_LEN * 3 + 50);
49   print_nsap_net_buf( tvb_get_ptr(tvb, offset, length), length, cur, MAX_NSAP_LEN * 3 + 50);
50   return( cur );
51 }
52
53 /* XXX - Should these be converted to string buffers? */
54 void
55 print_nsap_net_buf( const guint8 *ad, int length, gchar *buf, int buf_len)
56 {
57   gchar *cur;
58
59   /* to do : NSAP / NET decoding */
60
61   if ( (length <= 0 ) || ( length > MAX_NSAP_LEN ) ) {
62     g_strlcpy(buf, "<Invalid length of NSAP>", buf_len);
63     return;
64   }
65   cur = buf;
66   if ( ( length == RFC1237_NSAP_LEN ) || ( length == RFC1237_NSAP_LEN + 1 ) ) {
67     print_area_buf(ad, RFC1237_FULLAREA_LEN, cur, buf_len);
68     cur += strlen( cur );
69     print_system_id_buf( ad + RFC1237_FULLAREA_LEN, RFC1237_SYSTEMID_LEN, cur, (int) (buf_len-(cur-buf)));
70     cur += strlen( cur );
71     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x]",
72                     ad[ RFC1237_FULLAREA_LEN + RFC1237_SYSTEMID_LEN ] );
73     if ( length == RFC1237_NSAP_LEN + 1 ) {
74       g_snprintf(cur, (int) (buf_len-(cur-buf)), "-%02x", ad[ length -1 ] );
75     }
76   }
77   else {    /* probably format as standard */
78     print_area_buf( ad, length, buf, buf_len);
79   }
80 } /* print_nsap */
81
82 gchar *
83 print_system_id(wmem_allocator_t* scope, const guint8 *ad, int length )
84 {
85   gchar        *cur;
86
87   cur = (gchar *)wmem_alloc(scope, MAX_SYSTEMID_LEN * 3 + 5);
88   print_system_id_buf(ad, length, cur, MAX_SYSTEMID_LEN * 3 + 5);
89   return( cur );
90 }
91
92 gchar *
93 tvb_print_system_id( tvbuff_t *tvb, const gint offset, int length )
94 {
95   return( print_system_id(wmem_packet_scope(), tvb_get_ptr(tvb, offset, length), length) );
96 }
97
98 void
99 print_system_id_buf( const guint8 *ad, int length, gchar *buf, int buf_len)
100 {
101   gchar        *cur;
102   int           tmp;
103
104   if ( ( length <= 0 ) || ( length > MAX_SYSTEMID_LEN ) ) {
105     g_strlcpy(buf, "<Invalid length of SYSTEM ID>", buf_len);
106     return;
107   }
108
109   cur = buf;
110   if ( ( 6 == length ) || /* System-ID */
111        ( 7 == length ) || /* LAN-ID */
112        ( 8 == length )) { /* LSP-ID */
113     cur += g_snprintf(cur, buf_len, "%02x%02x.%02x%02x.%02x%02x", ad[0], ad[1],
114                     ad[2], ad[3], ad[4], ad[5] );
115     if ( ( 7 == length ) ||
116          ( 8 == length )) {
117         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), ".%02x", ad[6] );
118     }
119     if ( 8 == length ) {
120         g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-%02x", ad[7] );
121     }
122   }
123   else {
124     tmp = 0;
125     while ( tmp < length / 4 ) { /* 16 / 4 == 4 > four Octets left to print */
126       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
127       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
128       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
129       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x.", ad[tmp++] );
130     }
131     if ( 1 == tmp ) {   /* Special case for Designated IS */
132       cur--;
133       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), ".%02x", ad[tmp] );
134     }
135     else {
136       for ( ; tmp < length; ) {  /* print the rest without dot */
137         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
138       }
139     }
140   }
141 }
142
143 gchar *
144 print_area(tvbuff_t *tvb, const gint offset, int length)
145 {
146   gchar *cur;
147
148   cur = (gchar *)wmem_alloc(wmem_packet_scope(), MAX_AREA_LEN * 3 + 20);
149   print_area_buf(tvb_get_ptr(tvb, offset, length), length, cur, MAX_AREA_LEN * 3 + 20);
150   return cur;
151 }
152
153 void
154 print_area_buf(const guint8 *ad, int length, gchar *buf, int buf_len)
155 {
156   gchar *cur;
157   int  tmp  = 0;
158
159   /* to do : all real area decoding now: NET is assumed if id len is 1 more byte
160    * and take away all these stupid resource consuming local statics
161    */
162   if (length <= 0 || length > MAX_AREA_LEN) {
163     g_strlcpy(buf, "<Invalid length of AREA>", buf_len);
164     return;
165   }
166
167   cur = buf;
168   if ( (  ( NSAP_IDI_ISODCC          == *ad )
169        || ( NSAP_IDI_GOSIP2          == *ad )
170        )
171        &&
172        (  ( RFC1237_FULLAREA_LEN     ==  length )
173        || ( RFC1237_FULLAREA_LEN + 1 ==  length )
174        )
175      ) {    /* AFI is good and length is long enough  */
176
177     /* there used to be a check for (length > RFC1237_FULLAREA_LEN + 1) here,
178      * in order to report an invalied length of AREA for DCC / GOSIP AFI,
179      * but that can *never* be the case because the if() test above explicitly
180      * tests for (length == RFC1237_FULLAREA_LEN) or (length == RFC1237_FULLAREA_LEN + 1)
181      */
182
183     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x|%02x:%02x][%02x|%02x:%02x:%02x|%02x:%02x]",
184                     ad[0], ad[1], ad[2], ad[3], ad[4],
185                     ad[5], ad[6], ad[7], ad[8] );
186     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x:%02x|%02x:%02x]",
187                     ad[9], ad[10],  ad[11], ad[12] );
188     if ( RFC1237_FULLAREA_LEN + 1 == length )
189       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-[%02x]", ad[20] );
190   }
191   else { /* print standard format */
192     if ( length == RFC1237_AREA_LEN ) {
193       g_snprintf(buf, buf_len, "%02x.%02x%02x", ad[0], ad[1], ad[2] );
194       return;
195     }
196     if ( length == 4 ) {
197       g_snprintf(buf, buf_len, "%02x%02x%02x%02x", ad[0], ad[1], ad[2], ad[3] );
198       return;
199     }
200     while ( tmp < length / 4 ) {      /* 16/4==4 > four Octets left to print */
201       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
202       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
203       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
204       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x.", ad[tmp++] );
205     }
206     if ( 1 == tmp ) {                     /* Special case for Designated IS */
207       cur--;
208       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-%02x", ad[tmp] );
209     }
210     else {
211       for ( ; tmp < length; ) {  /* print the rest without dot or dash */
212         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
213       }
214     }
215   }
216 } /* print_area_buf */
217
218 /******************************************************************************
219  * OSI Address Type
220  ******************************************************************************/
221 static int osi_address_type = -1;
222
223 static int osi_address_to_str(const address* addr, gchar *buf, int buf_len)
224 {
225     print_nsap_net_buf((const guint8 *)addr->data, addr->len, buf, buf_len);
226     return (int)strlen(buf)+1;
227 }
228
229 static int osi_address_str_len(const address* addr _U_)
230 {
231     return MAX_NSAP_LEN * 3 + 50;
232 }
233
234 int get_osi_address_type(void)
235 {
236     return osi_address_type;
237 }
238
239 void register_osi_address_type(void)
240 {
241     if (osi_address_type != -1)
242         return;
243
244     osi_address_type = address_type_dissector_register("AT_OSI", "OSI Address", osi_address_to_str, osi_address_str_len, NULL, NULL, NULL, NULL);
245 }
246
247
248 /*
249  * Editor modelines
250  *
251  * Local Variables:
252  * c-basic-offset: 2
253  * tab-width: 8
254  * indent-tabs-mode: nil
255  * End:
256  *
257  * ex: set shiftwidth=2 tabstop=8 expandtab:
258  * :indentSize=2:tabSize=8:noTabs=true:
259  */