separate function for dissecting the adaptation field
[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  * $Id$
6  * Laurent Deniel <laurent.deniel@free.fr>
7  * Ralf Schneider <Ralf.Schneider@t-online.de>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 #include "config.h"
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <glib.h>
33
34 #include "osi-utils.h"
35 #include "emem.h"
36
37 /*
38  * XXX - shouldn't there be a centralized routine for dissecting NSAPs?
39  * See also "dissect_atm_nsap()" in epan/dissectors/packet-arp.c and
40  * "dissect_nsap()" in epan/dissectors/packet-isup.c.
41  */
42 gchar *
43 print_nsap_net( const guint8 *ad, int length )
44 {
45   gchar *cur;
46
47   cur = (gchar *)ep_alloc(MAX_NSAP_LEN * 3 + 50);
48   print_nsap_net_buf( ad, length, cur, MAX_NSAP_LEN * 3 + 50);
49   return( cur );
50 }
51
52 /* XXX - Should these be converted to string buffers? */
53 void
54 print_nsap_net_buf( const guint8 *ad, int length, gchar *buf, int buf_len)
55 {
56   gchar *cur;
57
58   /* to do : NSAP / NET decoding */
59
60   if ( (length <= 0 ) || ( length > MAX_NSAP_LEN ) ) {
61     g_snprintf(buf, buf_len, "<Invalid length of NSAP>");
62     return;
63   }
64   cur = buf;
65   if ( ( length == RFC1237_NSAP_LEN ) || ( length == RFC1237_NSAP_LEN + 1 ) ) {
66     print_area_buf(ad, RFC1237_FULLAREA_LEN, cur, buf_len);
67     cur += strlen( cur );
68     print_system_id_buf( ad + RFC1237_FULLAREA_LEN, RFC1237_SYSTEMID_LEN, cur, (int) (buf_len-(cur-buf)));
69     cur += strlen( cur );
70     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x]",
71                     ad[ RFC1237_FULLAREA_LEN + RFC1237_SYSTEMID_LEN ] );
72     if ( length == RFC1237_NSAP_LEN + 1 ) {
73       g_snprintf(cur, (int) (buf_len-(cur-buf)), "-%02x", ad[ length -1 ] );
74     }
75   }
76   else {    /* probably format as standard */
77     print_area_buf( ad, length, buf, buf_len);
78   }
79 } /* print_nsap */
80
81 gchar *
82 print_system_id( const guint8 *ad, int length )
83 {
84   gchar        *cur;
85
86   cur = (gchar *)ep_alloc(MAX_SYSTEMID_LEN * 3 + 5);
87   print_system_id_buf(ad, length, cur, MAX_SYSTEMID_LEN * 3 + 5);
88   return( cur );
89 }
90
91 void
92 print_system_id_buf( const guint8 *ad, int length, gchar *buf, int buf_len)
93 {
94   gchar        *cur;
95   int           tmp;
96
97   if ( ( length <= 0 ) || ( length > MAX_SYSTEMID_LEN ) ) {
98     g_snprintf(buf, buf_len, "<Invalid length of SYSTEM ID>");
99     return;
100   }
101
102   cur = buf;
103   if ( ( 6 == length ) || /* System-ID */
104        ( 7 == length ) || /* LAN-ID */
105        ( 8 == length )) { /* LSP-ID */
106     cur += g_snprintf(cur, buf_len, "%02x%02x.%02x%02x.%02x%02x", ad[0], ad[1],
107                     ad[2], ad[3], ad[4], ad[5] );
108     if ( ( 7 == length ) ||
109          ( 8 == length )) {
110         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), ".%02x", ad[6] );
111     }
112     if ( 8 == length ) {
113         g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-%02x", ad[7] );
114     }
115   }
116   else {
117     tmp = 0;
118     while ( tmp < length / 4 ) { /* 16 / 4 == 4 > four Octets left to print */
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       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
122       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x.", ad[tmp++] );
123     }
124     if ( 1 == tmp ) {   /* Special case for Designated IS */
125       cur--;
126       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), ".%02x", ad[tmp] );
127     }
128     else {
129       for ( ; tmp < length; ) {  /* print the rest without dot */
130         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
131       }
132     }
133   }
134 }
135
136 gchar *
137 print_area(const guint8 *ad, int length)
138 {
139   gchar *cur;
140
141   cur = (gchar *)ep_alloc(MAX_AREA_LEN * 3 + 20);
142   print_area_buf(ad, length, cur, MAX_AREA_LEN * 3 + 20);
143   return cur;
144 }
145
146 void
147 print_area_buf(const guint8 *ad, int length, gchar *buf, int buf_len)
148 {
149   gchar *cur;
150   int  tmp  = 0;
151
152   /* to do : all real area decoding now: NET is assumed if id len is 1 more byte
153    * and take away all these stupid resource consuming local statics
154    */
155   if (length <= 0 || length > MAX_AREA_LEN) {
156     g_snprintf(buf, buf_len, "<Invalid length of AREA>");
157     return;
158   }
159
160   cur = buf;
161   if ( (  ( NSAP_IDI_ISODCC          == *ad )
162        || ( NSAP_IDI_GOSIP2          == *ad )
163        )
164        &&
165        (  ( RFC1237_FULLAREA_LEN     ==  length )
166        || ( RFC1237_FULLAREA_LEN + 1 ==  length )
167        )
168      ) {    /* AFI is good and length is long enough  */
169
170     /* there used to be a check for (length > RFC1237_FULLAREA_LEN + 1) here,
171      * in order to report an invalied length of AREA for DCC / GOSIP AFI,
172      * but that can *never* be the case because the if() test above explicitly
173      * tests for (length == RFC1237_FULLAREA_LEN) or (length == RFC1237_FULLAREA_LEN + 1)
174      */
175
176     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x|%02x:%02x][%02x|%02x:%02x:%02x|%02x:%02x]",
177                     ad[0], ad[1], ad[2], ad[3], ad[4],
178                     ad[5], ad[6], ad[7], ad[8] );
179     cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "[%02x:%02x|%02x:%02x]",
180                     ad[9], ad[10],  ad[11], ad[12] );
181     if ( RFC1237_FULLAREA_LEN + 1 == length )
182       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-[%02x]", ad[20] );
183   }
184   else { /* print standard format */
185     if ( length == RFC1237_AREA_LEN ) {
186       g_snprintf(buf, buf_len, "%02x.%02x%02x", ad[0], ad[1], ad[2] );
187       return;
188     }
189     if ( length == 4 ) {
190       g_snprintf(buf, buf_len, "%02x%02x%02x%02x", ad[0], ad[1], ad[2], ad[3] );
191       return;
192     }
193     while ( tmp < length / 4 ) {      /* 16/4==4 > four Octets left to print */
194       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
195       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
196       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
197       cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x.", ad[tmp++] );
198     }
199     if ( 1 == tmp ) {                     /* Special case for Designated IS */
200       cur--;
201       g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "-%02x", ad[tmp] );
202     }
203     else {
204       for ( ; tmp < length; ) {  /* print the rest without dot or dash */
205         cur += g_snprintf(cur, (gulong) (buf_len-(cur-buf)), "%02x", ad[tmp++] );
206       }
207     }
208   }
209 } /* print_area_buf */
210