Note that non-GNU "make"s appear not to be able to build Ethereal, and
[metze/wireshark/wip.git] / packet-llc.c
1 /* packet-llc.c
2  * Routines for IEEE 802.2 LLC layer
3  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
4  *
5  * $Id: packet-llc.c,v 1.14 1999/03/23 03:14:39 gram Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
9  * Copyright 1998 Gerald Combs
10  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <glib.h>
36 #include "packet.h"
37
38 typedef void (capture_func_t)(const u_char *, int, guint32, packet_counts *);
39 typedef void (dissect_func_t)(const u_char *, int, frame_data *, proto_tree *);
40
41 struct sap_info {
42         guint8  sap;
43         capture_func_t *capture_func;
44         dissect_func_t *dissect_func;
45         char    *text;
46 };
47
48 static struct sap_info  saps[] = {
49         { 0x00, NULL,           NULL,           "NULL LSAP" },
50         { 0x02, NULL,           NULL,           "LLC Sub-Layer Management Individual" },
51         { 0x03, NULL,           NULL,           "LLC Sub-Layer Management Group" },
52         { 0x04, NULL,           NULL,           "SNA Path Control Individual" },
53         { 0x05, NULL,           NULL,           "SNA Path Control Group" },
54         { 0x06, capture_ip,     dissect_ip,     "TCP/IP" },
55         { 0x08, NULL,           NULL,           "SNA" },
56         { 0x0C, NULL,           NULL,           "SNA" },
57         { 0x42, NULL,           NULL,           "Spanning Tree BPDU" },
58         { 0x7F, NULL,           NULL,           "ISO 802.2" },
59         { 0x80, NULL,           NULL,           "XNS" },
60         { 0xAA, NULL,           NULL,           "SNAP" },
61         /*{ 0xBA, NULL,         dissect_vines,  "Banyan Vines" },
62         { 0xBC, NULL,           dissect_vines,  "Banyan Vines" },*/
63         { 0xBA, NULL,           NULL,           "Banyan Vines" },
64         { 0xBC, NULL,           NULL,           "Banyan Vines" },
65         { 0xE0, NULL,           dissect_ipx,    "NetWare" },
66         { 0xF0, NULL,           NULL,           "NetBIOS" },
67         { 0xF4, NULL,           NULL,           "IBM Net Management Individual" },
68         { 0xF5, NULL,           NULL,           "IBM Net Management Group" },
69         { 0xF8, NULL,           NULL,           "Remote Program Load" },
70         { 0xFC, NULL,           NULL,           "Remote Program Load" },
71         { 0xFE, NULL,           dissect_osi,    "ISO Network Layer" },
72         { 0xFF, NULL,           NULL,           "Global LSAP" },
73         { 0x00, NULL,           NULL,           NULL }
74 };
75
76
77 static char*
78 sap_text(u_char sap) {
79         int i=0;
80
81         while (saps[i].text != NULL) {
82                 if (saps[i].sap == sap) {
83                         return saps[i].text;
84                 }
85                 i++;
86         }
87         return "Unknown";
88 }
89
90 static capture_func_t *
91 sap_capture_func(u_char sap) {
92         int i=0;
93
94         while (saps[i].text != NULL) {
95                 if (saps[i].sap == sap) {
96                         return saps[i].capture_func;
97                 }
98                 i++;
99         }
100         return NULL;
101 }
102
103 static dissect_func_t *
104 sap_dissect_func(u_char sap) {
105         int i=0;
106
107         while (saps[i].text != NULL) {
108                 if (saps[i].sap == sap) {
109                         return saps[i].dissect_func;
110                 }
111                 i++;
112         }
113         return dissect_data;
114 }
115
116 static char*
117 llc_org(const u_char *ptr) {
118
119         unsigned long org = (ptr[0] << 16) | (ptr[1] << 8) | ptr[2];
120         char *llc_org[1] = {
121                 "Encapsulated Ethernet"};
122
123         if (org > 0) {
124                 return "Unknown";
125         }
126         else {
127                 return llc_org[org];
128         }
129 }
130
131 void
132 capture_llc(const u_char *pd, int offset, guint32 cap_len, packet_counts *ld) {
133
134         guint16         etype;
135         int             is_snap;
136         capture_func_t  *capture;
137
138         is_snap = (pd[offset] == 0xAA) && (pd[offset+1] == 0xAA);
139         if (is_snap) {
140                 etype  = (pd[offset+6] << 8) | pd[offset+7];
141                 offset += 8;
142                 capture_ethertype(etype, offset, pd, cap_len, ld);
143         }               
144         else {
145                 capture = sap_capture_func(pd[offset]);
146
147                 /* non-SNAP */
148                 offset += 3;
149
150                 if (capture) {
151                         capture(pd, offset, cap_len, ld);
152                 }
153                 else {
154                         ld->other++;
155                 }
156
157         }
158 }
159
160 void
161 dissect_llc(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
162
163         proto_tree      *llc_tree = NULL;
164         proto_item      *ti;
165         guint16         etype;
166         int             is_snap;
167         dissect_func_t  *dissect;
168
169         /* LLC Strings */
170         char *llc_ctrl[4] = {
171                 "Information Transfer", "Supervisory",
172                 "", "Unnumbered Information" };
173
174         is_snap = (pd[offset] == 0xAA) && (pd[offset+1] == 0xAA);
175
176         if (check_col(fd, COL_PROTOCOL)) {
177                 col_add_str(fd, COL_PROTOCOL, "LLC");
178         }
179   
180         if (tree) {
181                 ti = proto_tree_add_item(tree, offset, (is_snap ? 8 : 3),
182                         "Logical-Link Control");
183                 llc_tree = proto_tree_new();
184                 proto_item_add_subtree(ti, llc_tree, ETT_LLC);
185                 proto_tree_add_item(llc_tree, offset,      1, "DSAP: %s (0x%02X)",
186                         sap_text(pd[offset]), pd[offset]);
187                 proto_tree_add_item(llc_tree, offset+1,    1, "SSAP: %s (0x%02X)",
188                         sap_text(pd[offset+1]), pd[offset+1]);
189                 proto_tree_add_item(llc_tree, offset+2,    1, "Control: %s",
190                         llc_ctrl[pd[offset+2] & 3]);
191         }
192
193         if (is_snap) {
194                 if (check_col(fd, COL_INFO)) {
195                         col_add_str(fd, COL_INFO, "802.2 LLC (SNAP)");
196                 }
197                 if (tree) {
198                         proto_tree_add_item(llc_tree, offset+3,    3,
199                                 "Organization Code: %s (%02X-%02X-%02X)",
200                                 llc_org(&pd[offset+3]), 
201                                 pd[offset+3], pd[offset+4], pd[offset+5]);
202                 }
203                 etype  = (pd[offset+6] << 8) | pd[offset+7];
204                 offset += 8;
205                 ethertype(etype, offset, pd, fd, tree, llc_tree);
206         }               
207         else {
208                 if (check_col(fd, COL_INFO)) {
209                         col_add_fstr(fd, COL_INFO, "802.2 LLC (%s)", sap_text(pd[offset]));
210                 }
211
212                 dissect = sap_dissect_func(pd[offset]);
213
214                 /* non-SNAP */
215                 offset += 3;
216
217                 if (dissect) {
218                         dissect(pd, offset, fd, tree);
219                 }
220                 else {
221                         dissect_data(pd, offset, fd, tree);
222                 }
223
224         }
225 }