2 * Routines for lapb frame disassembly
3 * Olivier Abad <abad@daba.dhis.org>
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@zing.org>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
38 #define LAPB_I 0x00 /* Information frames */
39 #define LAPB_S 0x01 /* Supervisory frames */
40 #define LAPB_U 0x03 /* Unnumbered frames */
42 #define LAPB_RR 0x01 /* Receiver ready */
43 #define LAPB_RNR 0x05 /* Receiver not ready */
44 #define LAPB_REJ 0x09 /* Reject */
45 #define LAPB_SABM 0x2F /* Set Asynchronous Balanced Mode */
46 #define LAPB_SABME 0x6F /* Set Asynchronous Balanced Mode Extended */
47 #define LAPB_DISC 0x43 /* Disconnect */
48 #define LAPB_DM 0x0F /* Disconnected mode */
49 #define LAPB_UA 0x63 /* Unnumbered acknowledge */
50 #define LAPB_FRMR 0x87 /* Frame reject */
55 int hf_lapb_address = -1;
56 int hf_lapb_control = -1;
59 dissect_lapb(const u_char *pd, frame_data *fd, proto_tree *tree)
61 proto_tree *lapb_tree, *ti;
65 if (check_col(fd, COL_PROTOCOL))
66 col_add_str(fd, COL_PROTOCOL, "LAPB");
68 sprintf(lapb_addr, "%2d", (int)pd[0]);
69 if(check_col(fd, COL_RES_DL_SRC))
70 col_add_str(fd, COL_RES_DL_SRC, lapb_addr);
72 switch (pd[1] & 0x0F) {
74 if(check_col(fd, COL_INFO)) {
75 sprintf(info, "RR N(R):%d", (pd[1] >> 5) & 0x7);
76 if ((pd[1] >> 4) && 0x01) { /* P/F bit */
77 if (((fd->flags & FROM_DCE) && pd[0] == 0x01) ||
78 (!(fd->flags & FROM_DCE) && pd[0] == 0x03))
83 col_add_str(fd, COL_INFO, info);
85 if (fd->flags & FROM_DCE) {
86 if(check_col(fd, COL_RES_DL_DST))
87 col_add_str(fd, COL_RES_DL_DST, "DTE");
88 if(check_col(fd, COL_RES_DL_SRC))
89 col_add_str(fd, COL_RES_DL_SRC, "DCE");
92 if(check_col(fd, COL_RES_DL_DST))
93 col_add_str(fd, COL_RES_DL_DST, "DCE");
94 if(check_col(fd, COL_RES_DL_SRC))
95 col_add_str(fd, COL_RES_DL_SRC, "DTE");
99 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
101 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
102 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, pd[0],
103 "Address : 0x%02X", (int)pd[0]);
104 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, "RR",
105 "Control field : 0x%02X", (int)pd[1]);
106 proto_tree_add_text(lapb_tree, 1, 1,
107 " %d%d%d..... : N(R) = %d",
112 proto_tree_add_text(lapb_tree, 1, 1,
113 " ...%d.... : Poll/Final bit",
115 proto_tree_add_text(lapb_tree, 1, 1,
116 " ....0001 : Receive Ready (RR)");
120 if(check_col(fd, COL_INFO)) {
121 sprintf(info, "RNR N(R):%d", (pd[1] >> 5) & 0x7);
122 if ((pd[1] >> 4) && 0x01) { /* P/F bit */
123 if (((fd->flags & FROM_DCE) && pd[0] == 0x01) ||
124 (!(fd->flags & FROM_DCE) && pd[0] == 0x03))
129 col_add_str(fd, COL_INFO, info);
131 if (fd->flags & FROM_DCE) {
132 if(check_col(fd, COL_RES_DL_DST))
133 col_add_str(fd, COL_RES_DL_DST, "DTE");
134 if(check_col(fd, COL_RES_DL_SRC))
135 col_add_str(fd, COL_RES_DL_SRC, "DCE");
138 if(check_col(fd, COL_RES_DL_DST))
139 col_add_str(fd, COL_RES_DL_DST, "DCE");
140 if(check_col(fd, COL_RES_DL_SRC))
141 col_add_str(fd, COL_RES_DL_SRC, "DTE");
145 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
147 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
148 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, pd[0],
149 "Address : 0x%02X", (int)pd[0]);
150 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, "RNR",
151 "Control field : 0x%02X", (int)pd[1]);
152 proto_tree_add_text(lapb_tree, 1, 1,
153 " %d%d%d..... : N(R) = %d",
158 proto_tree_add_text(lapb_tree, 1, 1,
159 " ...%d.... : Poll/Final bit",
161 proto_tree_add_text(lapb_tree, 1, 1,
162 " ....0101 : Receive Not Ready (RNR)");
166 if(check_col(fd, COL_INFO)) {
167 sprintf(info, "REJ N(R):%d", (pd[1] >> 5) & 0x7);
168 if ((pd[1] >> 4) && 0x01) { /* P/F bit */
169 if (((fd->flags & FROM_DCE) && pd[0] == 0x01) ||
170 (!(fd->flags & FROM_DCE) && pd[0] == 0x03))
175 col_add_str(fd, COL_INFO, info);
177 if (fd->flags & FROM_DCE) {
178 if(check_col(fd, COL_RES_DL_DST))
179 col_add_str(fd, COL_RES_DL_DST, "DTE");
180 if(check_col(fd, COL_RES_DL_SRC))
181 col_add_str(fd, COL_RES_DL_SRC, "DCE");
184 if(check_col(fd, COL_RES_DL_DST))
185 col_add_str(fd, COL_RES_DL_DST, "DCE");
186 if(check_col(fd, COL_RES_DL_SRC))
187 col_add_str(fd, COL_RES_DL_SRC, "DTE");
191 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
193 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
194 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, pd[0],
195 "Address : 0x%02X", (int)pd[0]);
196 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, "REJ",
197 "Control field : 0x%02X", (int)pd[1]);
198 proto_tree_add_text(lapb_tree, 1, 1,
199 " %d%d%d..... : N(R) = %d",
204 proto_tree_add_text(lapb_tree, 1, 1,
205 " ...%d.... : Poll/Final bit",
207 proto_tree_add_text(lapb_tree, 1, 1,
208 " ....1001 : Reeject (REJ)");
213 /* not a RR/RNR/REJ frame */
215 if (pd[1] & 0x01) { /* not an information frame */
216 switch (pd[1] & 0xEF) { /* don't check Poll/Final bit */
218 if (fd->flags & FROM_DCE) {
219 if(check_col(fd, COL_RES_DL_DST))
220 col_add_str(fd, COL_RES_DL_DST, "DTE");
221 if(check_col(fd, COL_RES_DL_SRC))
222 col_add_str(fd, COL_RES_DL_SRC, "DCE");
225 if(check_col(fd, COL_RES_DL_DST))
226 col_add_str(fd, COL_RES_DL_DST, "DCE");
227 if(check_col(fd, COL_RES_DL_SRC))
228 col_add_str(fd, COL_RES_DL_SRC, "DTE");
230 if(check_col(fd, COL_INFO)) {
232 col_add_str(fd, COL_INFO, "SABM P");
234 col_add_str(fd, COL_INFO, "SABM");
237 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
239 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
240 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1,
241 pd[0], "Address: 0x%02X",
243 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1,
245 "Set Asynchronous Balanced Mode (SABM)");
246 proto_tree_add_text(lapb_tree, 1, 1,
247 "...%d.... : Poll bit",
252 if (fd->flags & FROM_DCE) {
253 if(check_col(fd, COL_RES_DL_DST))
254 col_add_str(fd, COL_RES_DL_DST, "DTE");
255 if(check_col(fd, COL_RES_DL_SRC))
256 col_add_str(fd, COL_RES_DL_SRC, "DCE");
259 if(check_col(fd, COL_RES_DL_DST))
260 col_add_str(fd, COL_RES_DL_DST, "DCE");
261 if(check_col(fd, COL_RES_DL_SRC))
262 col_add_str(fd, COL_RES_DL_SRC, "DTE");
264 if(check_col(fd, COL_INFO)) {
266 col_add_str(fd, COL_INFO, "DISC P");
268 col_add_str(fd, COL_INFO, "DISC");
271 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
273 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
274 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1,
275 pd[0], "Address: 0x%02X",
277 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1,
278 "DISC", "Disconnect (DISC)");
279 proto_tree_add_text(lapb_tree, 1, 1,
280 "...%d.... : Poll bit",
285 if (fd->flags & FROM_DCE) {
286 if(check_col(fd, COL_RES_DL_DST))
287 col_add_str(fd, COL_RES_DL_DST, "DTE");
288 if(check_col(fd, COL_RES_DL_SRC))
289 col_add_str(fd, COL_RES_DL_SRC, "DCE");
292 if(check_col(fd, COL_RES_DL_DST))
293 col_add_str(fd, COL_RES_DL_DST, "DCE");
294 if(check_col(fd, COL_RES_DL_SRC))
295 col_add_str(fd, COL_RES_DL_SRC, "DTE");
297 if(check_col(fd, COL_INFO)) {
299 col_add_str(fd, COL_INFO, "DM F");
301 col_add_str(fd, COL_INFO, "DM");
304 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
306 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
307 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1,
308 pd[0], "Address: 0x%02X",
310 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1,
311 "DM", "Disconnect Mode (DM)");
312 proto_tree_add_text(lapb_tree, 1, 1,
313 "...%d.... : Final bit",
318 if (fd->flags & FROM_DCE) {
319 if(check_col(fd, COL_RES_DL_DST))
320 col_add_str(fd, COL_RES_DL_DST, "DTE");
321 if(check_col(fd, COL_RES_DL_SRC))
322 col_add_str(fd, COL_RES_DL_SRC, "DCE");
325 if(check_col(fd, COL_RES_DL_DST))
326 col_add_str(fd, COL_RES_DL_DST, "DCE");
327 if(check_col(fd, COL_RES_DL_SRC))
328 col_add_str(fd, COL_RES_DL_SRC, "DTE");
330 if(check_col(fd, COL_INFO)) {
332 col_add_str(fd, COL_INFO, "UA F");
334 col_add_str(fd, COL_INFO, "UA");
337 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
339 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
340 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1,
341 pd[0], "Address: 0x%02X",
343 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1,
344 "UA", "Unnumbered Acknowledge (UA)");
345 proto_tree_add_text(lapb_tree, 1, 1,
346 "...%d.... : Final bit",
351 if (fd->flags & FROM_DCE) {
352 if(check_col(fd, COL_RES_DL_DST))
353 col_add_str(fd, COL_RES_DL_DST, "DTE");
354 if(check_col(fd, COL_RES_DL_SRC))
355 col_add_str(fd, COL_RES_DL_SRC, "DCE");
358 if(check_col(fd, COL_RES_DL_DST))
359 col_add_str(fd, COL_RES_DL_DST, "DCE");
360 if(check_col(fd, COL_RES_DL_SRC))
361 col_add_str(fd, COL_RES_DL_SRC, "DTE");
363 if(check_col(fd, COL_INFO)) {
365 col_add_str(fd, COL_INFO, "FRMR F");
367 col_add_str(fd, COL_INFO, "FRMR");
370 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
372 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
373 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1,
374 pd[0], "Address: 0x%02X",
376 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1,
377 "FRMR", "Frame Reject (FRMR)");
378 proto_tree_add_text(lapb_tree, 1, 1,
379 "...%d.... : Final bit",
385 else /* information frame */
387 if (fd->flags & FROM_DCE) {
388 if(check_col(fd, COL_RES_DL_DST))
389 col_add_str(fd, COL_RES_DL_DST, "DTE");
390 if(check_col(fd, COL_RES_DL_SRC))
391 col_add_str(fd, COL_RES_DL_SRC, "DCE");
394 if(check_col(fd, COL_RES_DL_DST))
395 col_add_str(fd, COL_RES_DL_DST, "DCE");
396 if(check_col(fd, COL_RES_DL_SRC))
397 col_add_str(fd, COL_RES_DL_SRC, "DTE");
399 if(check_col(fd, COL_INFO)) {
400 sprintf(info, "I N(R):%d N(S):%d",
403 if ((pd[1] >> 4) && 0x01) /* P/F bit */
405 col_add_str(fd, COL_INFO, info);
408 ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL,
410 lapb_tree = proto_item_add_subtree(ti, ETT_LAPB);
411 proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1,
412 pd[0], "Address: 0x%02X",
414 proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1,
415 "I", "Control field : 0x%02X",
417 proto_tree_add_text(lapb_tree, 1, 1,
418 " %d%d%d..... : N(R) = %d",
423 proto_tree_add_text(lapb_tree, 1, 1,
424 " ...%d.... : Poll/Final bit",
426 proto_tree_add_text(lapb_tree, 1, 1,
427 " ....%d%d%d. : N(S) = %d",
432 proto_tree_add_text(lapb_tree, 1, 1,
433 " .......0 : Information Transfer (I)");
437 /* not end of frame ==> X.25 */
438 if (fd->cap_len > 2) dissect_x25(pd, 2, fd, tree);
442 proto_register_lapb(void)
444 static hf_register_info hf[] = {
446 { "Address Field", "lapb.address", FT_UINT8, NULL} },
448 { "Control Field", "lapb.control", FT_STRING, NULL} },
451 proto_lapb = proto_register_protocol ("LAPB", "lapb");
452 proto_register_field_array (proto_lapb, hf, array_length(hf));