Ethereal-dev: Re: [ethereal-dev] LAPB/X.25 patch
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Mon, 2 Aug 1999 23:26:40 -0700
> Hmmm, NetBEUI uses SABME, but looks remarkably like X.25 apart from that. Or, at least, like LAPB; it uses LLC Type 1 and 2, and I think LLC, like thousands of other protocols across the globe (LAPB, LAPD, etc.) is an HDLC derivative (amazing how many packets flying around the world are ultimately descended from something IBM came up with to let 3270 terminals and mainframes communicate...). > I am not sure if it uses a modulo-128 window size, but probably does. I seem to remember seeing something on some Web page saying it does, but maybe I'm thinking of http://www.lebarge.com/clark/NetBasics/netbeui.htm which said both The client computer sends a Set Asynchronous Balance Mode Extended (SABME) frame, and the server returns an Unnumbered Acknowledgment (UA) frame. Then the client sends a Receive Ready (RR) frame, notifying the server that it is ready to receive Informational (I) frames whose sequence number is currently 0. The server acknowledges this frame. and THERE WOULD BE A PICTURE HERE IF MICROSOFT WASN'T ON CRACK AND PUT AN IMAGE OF THE TDI AND TCP/IP CONNECTION. > Anyway, seems like the two protocols share a lot ... Yup. Here's a patch to the current CVS tree, which adds "xdlc.c and "xdlc.h" files; "xdlc.c" defines a routine "dissect_xdlc_control()" to dissect the control field of a frame in an SDLC-derived protocol (although there may be some places where the processing has to be protocol-dependent). I modified "packet-llc.c" and "packet-lapb.c" to use it; it creates a subtree for the control field, giving a bitfield decode if you open up the subtree. It *should* handle both basic and extended mode - its caller passes in an argument to specify which mode it is (although I guess they should pass in a pointer to that flag, and it should set that flag if it sees one of the Set XXX Mode Extended commands; there'd still be a need to set it from outside, though, as you might not have that command in the capture). Olivier, feel free to change it; the only frames I deal with that have SDLC-derived protocols in them are FDDI and 802.3 frames, and I'm not sure I've seen any one other than a Boring Old Unnumbered Information field. I'm not checking it in, so that people can review it first (so if you want changes, tell me what you want changed, or send in a patch to do the change). Note that I will probably want to change "decode_numeric_bitfield()" so that it either 1) takes as an argument the bitfield value shifted appropriately or 2) shifts it appropriately itself so that the N(R) and N(S) values display properly; the other files that use it are "packet-gre.c" and "packet-tr.c", and I *suspect* they'd want it to display them properly (i.e., if a bitfield is the upper 5 bits of a byte, and the byte has the value 01100111 the value should be 12 or 0xC, not 96 or 0x60) - if that's not the case, let me know. (If it is the case, I can do the shifting inside "decode_numeric_bitfield()"; if it's not the case, its caller will have to do the shifting, or not do it, as the case may be, and pass the result on to "decode_numeric_bitfield()".) diff -c -N ../ethereal.vanilla/Makefile.am ./Makefile.am *** ../ethereal.vanilla/Makefile.am Sun Aug 1 19:04:25 1999 --- ./Makefile.am Mon Aug 2 20:57:07 1999 *************** *** 104,114 **** resolv.c \ resolv.h \ smb.h \ - timestamp.h \ - util.c \ summary.c \ summary.h \ ! util.h EXTRA_ethereal_SOURCES = \ dfilter-grammar.c \ --- 104,116 ---- resolv.c \ resolv.h \ smb.h \ summary.c \ summary.h \ ! timestamp.h \ ! util.c \ ! util.h \ ! xdlc.c \ ! xdlc.h EXTRA_ethereal_SOURCES = \ dfilter-grammar.c \ diff -c -N ../ethereal.vanilla/packet-lapb.c ./packet-lapb.c *** ../ethereal.vanilla/packet-lapb.c Sun Aug 1 19:26:17 1999 --- ./packet-lapb.c Mon Aug 2 21:41:13 1999 *************** *** 34,53 **** #include <glib.h> #include <string.h> #include "packet.h" ! ! #define LAPB_I 0x00 /* Information frames */ ! #define LAPB_S 0x01 /* Supervisory frames */ ! #define LAPB_U 0x03 /* Unnumbered frames */ ! ! #define LAPB_RR 0x01 /* Receiver ready */ ! #define LAPB_RNR 0x05 /* Receiver not ready */ ! #define LAPB_REJ 0x09 /* Reject */ ! #define LAPB_SABM 0x2F /* Set Asynchronous Balanced Mode */ ! #define LAPB_SABME 0x6F /* Set Asynchronous Balanced Mode Extended */ ! #define LAPB_DISC 0x43 /* Disconnect */ ! #define LAPB_DM 0x0F /* Disconnected mode */ ! #define LAPB_UA 0x63 /* Unnumbered acknowledge */ ! #define LAPB_FRMR 0x87 /* Frame reject */ #define FROM_DCE 0x80 --- 34,40 ---- #include <glib.h> #include <string.h> #include "packet.h" ! #include "xdlc.h" #define FROM_DCE 0x80 *************** *** 59,438 **** dissect_lapb(const u_char *pd, frame_data *fd, proto_tree *tree) { proto_tree *lapb_tree, *ti; ! char lapb_addr[3]; ! char info[80]; if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "LAPB"); - sprintf(lapb_addr, "%2d", (int)pd[0]); if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, lapb_addr); ! ! switch (pd[1] & 0x0F) { ! case LAPB_RR: ! if(check_col(fd, COL_INFO)) { ! sprintf(info, "RR N(R):%d", (pd[1] >> 5) & 0x7); ! if ((pd[1] >> 4) && 0x01) { /* P/F bit */ ! if (((fd->flags & FROM_DCE) && pd[0] == 0x01) || ! (!(fd->flags & FROM_DCE) && pd[0] == 0x03)) ! strcat(info, " F"); ! else ! strcat(info, " P"); ! } ! col_add_str(fd, COL_INFO, info); ! } ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if (tree) ! { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, ! "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, pd[0], ! "Address : 0x%02X", (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, "RR", ! "Control field : 0x%02X", (int)pd[1]); ! proto_tree_add_text(lapb_tree, 1, 1, ! " %d%d%d..... : N(R) = %d", ! (pd[1] >> 7) & 0x1, ! (pd[1] >> 6) & 0x1, ! (pd[1] >> 5) & 0x1, ! (pd[1] >> 5) & 0x7); ! proto_tree_add_text(lapb_tree, 1, 1, ! " ...%d.... : Poll/Final bit", ! (pd[1] >> 4) & 0x1); ! proto_tree_add_text(lapb_tree, 1, 1, ! " ....0001 : Receive Ready (RR)"); ! } ! return; ! case LAPB_RNR: ! if(check_col(fd, COL_INFO)) { ! sprintf(info, "RNR N(R):%d", (pd[1] >> 5) & 0x7); ! if ((pd[1] >> 4) && 0x01) { /* P/F bit */ ! if (((fd->flags & FROM_DCE) && pd[0] == 0x01) || ! (!(fd->flags & FROM_DCE) && pd[0] == 0x03)) ! strcat(info, " F"); ! else ! strcat(info, " P"); ! } ! col_add_str(fd, COL_INFO, info); ! } ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if (tree) ! { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, ! "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, pd[0], ! "Address : 0x%02X", (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, "RNR", ! "Control field : 0x%02X", (int)pd[1]); ! proto_tree_add_text(lapb_tree, 1, 1, ! " %d%d%d..... : N(R) = %d", ! (pd[1] >> 7) & 0x1, ! (pd[1] >> 6) & 0x1, ! (pd[1] >> 5) & 0x1, ! (pd[1] >> 5) & 0x7); ! proto_tree_add_text(lapb_tree, 1, 1, ! " ...%d.... : Poll/Final bit", ! (pd[1] >> 4) & 0x1); ! proto_tree_add_text(lapb_tree, 1, 1, ! " ....0101 : Receive Not Ready (RNR)"); ! } ! return; ! case LAPB_REJ: ! if(check_col(fd, COL_INFO)) { ! sprintf(info, "REJ N(R):%d", (pd[1] >> 5) & 0x7); ! if ((pd[1] >> 4) && 0x01) { /* P/F bit */ ! if (((fd->flags & FROM_DCE) && pd[0] == 0x01) || ! (!(fd->flags & FROM_DCE) && pd[0] == 0x03)) ! strcat(info, " F"); ! else ! strcat(info, " P"); ! } ! col_add_str(fd, COL_INFO, info); ! } ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if (tree) ! { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, ! "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, pd[0], ! "Address : 0x%02X", (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, "REJ", ! "Control field : 0x%02X", (int)pd[1]); ! proto_tree_add_text(lapb_tree, 1, 1, ! " %d%d%d..... : N(R) = %d", ! (pd[1] >> 7) & 0x1, ! (pd[1] >> 6) & 0x1, ! (pd[1] >> 5) & 0x1, ! (pd[1] >> 5) & 0x7); ! proto_tree_add_text(lapb_tree, 1, 1, ! " ...%d.... : Poll/Final bit", ! (pd[1] >> 4) & 0x1); ! proto_tree_add_text(lapb_tree, 1, 1, ! " ....1001 : Reeject (REJ)"); ! } ! return; } ! /* not a RR/RNR/REJ frame */ ! if (pd[1] & 0x01) { /* not an information frame */ ! switch (pd[1] & 0xEF) { /* don't check Poll/Final bit */ ! case LAPB_SABM: ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if(check_col(fd, COL_INFO)) { ! if (pd[1] & 0x10) ! col_add_str(fd, COL_INFO, "SABM P"); ! else ! col_add_str(fd, COL_INFO, "SABM"); ! } ! if (tree) { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, ! "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, ! pd[0], "Address: 0x%02X", ! (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, ! "SABM", ! "Set Asynchronous Balanced Mode (SABM)"); ! proto_tree_add_text(lapb_tree, 1, 1, ! "...%d.... : Poll bit", ! (pd[1] >> 4) & 0x1); ! } ! break; ! case LAPB_DISC: ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if(check_col(fd, COL_INFO)) { ! if (pd[1] & 0x10) ! col_add_str(fd, COL_INFO, "DISC P"); ! else ! col_add_str(fd, COL_INFO, "DISC"); ! } ! if (tree) { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, ! "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, ! pd[0], "Address: 0x%02X", ! (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, ! "DISC", "Disconnect (DISC)"); ! proto_tree_add_text(lapb_tree, 1, 1, ! "...%d.... : Poll bit", ! (pd[1] >> 4) & 0x1); ! } ! break; ! case LAPB_DM: ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if(check_col(fd, COL_INFO)) { ! if (pd[1] & 0x10) ! col_add_str(fd, COL_INFO, "DM F"); ! else ! col_add_str(fd, COL_INFO, "DM"); ! } ! if (tree) { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, ! "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, ! pd[0], "Address: 0x%02X", ! (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, ! "DM", "Disconnect Mode (DM)"); ! proto_tree_add_text(lapb_tree, 1, 1, ! "...%d.... : Final bit", ! (pd[1] >> 4) & 0x1); ! } ! break; ! case LAPB_UA: ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if(check_col(fd, COL_INFO)) { ! if (pd[1] & 0x10) ! col_add_str(fd, COL_INFO, "UA F"); ! else ! col_add_str(fd, COL_INFO, "UA"); ! } ! if (tree) { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, ! "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, ! pd[0], "Address: 0x%02X", ! (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, ! "UA", "Unnumbered Acknowledge (UA)"); ! proto_tree_add_text(lapb_tree, 1, 1, ! "...%d.... : Final bit", ! (pd[1] >> 4) & 0x1); ! } ! break; ! case LAPB_FRMR: ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if(check_col(fd, COL_INFO)) { ! if (pd[1] & 0x10) ! col_add_str(fd, COL_INFO, "FRMR F"); ! else ! col_add_str(fd, COL_INFO, "FRMR"); ! } ! if (tree) { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, ! "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, ! pd[0], "Address: 0x%02X", ! (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, ! "FRMR", "Frame Reject (FRMR)"); ! proto_tree_add_text(lapb_tree, 1, 1, ! "...%d.... : Final bit", ! (pd[1] >> 4) & 0x1); ! } ! break; ! } ! } ! else /* information frame */ ! { ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); ! } ! if(check_col(fd, COL_INFO)) { ! sprintf(info, "I N(R):%d N(S):%d", ! (pd[1] >> 5) & 0x7, ! (pd[1] >> 1) & 0x7); ! if ((pd[1] >> 4) && 0x01) /* P/F bit */ ! strcat(info, " P"); ! col_add_str(fd, COL_INFO, info); ! } ! if (tree) { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, ! pd[0], "Address: 0x%02X", ! (int)pd[0]); ! proto_tree_add_item_format(lapb_tree, hf_lapb_control, 1, 1, ! "I", "Control field : 0x%02X", ! (int)pd[1]); ! proto_tree_add_text(lapb_tree, 1, 1, ! " %d%d%d..... : N(R) = %d", ! (pd[1] >> 7) & 0x1, ! (pd[1] >> 6) & 0x1, ! (pd[1] >> 5) & 0x1, ! (pd[1] >> 5) & 0x7); ! proto_tree_add_text(lapb_tree, 1, 1, ! " ...%d.... : Poll/Final bit", ! (pd[1] >> 4) & 0x1); ! proto_tree_add_text(lapb_tree, 1, 1, ! " ....%d%d%d. : N(S) = %d", ! (pd[1] >> 3) & 0x1, ! (pd[1] >> 2) & 0x1, ! (pd[1] >> 1) & 0x1, ! (pd[1] >> 1) & 0x7); ! proto_tree_add_text(lapb_tree, 1, 1, ! " .......0 : Information Transfer (I)"); ! } } /* not end of frame ==> X.25 */ if (fd->cap_len > 2) dissect_x25(pd, 2, fd, tree); --- 46,88 ---- dissect_lapb(const u_char *pd, frame_data *fd, proto_tree *tree) { proto_tree *lapb_tree, *ti; ! int is_response; if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "LAPB"); if(check_col(fd, COL_RES_DL_SRC)) ! col_add_fstr(fd, COL_RES_DL_SRC, "0x%02X", pd[0]); ! if (fd->flags & FROM_DCE) { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DTE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DCE"); ! } ! else { ! if(check_col(fd, COL_RES_DL_DST)) ! col_add_str(fd, COL_RES_DL_DST, "DCE"); ! if(check_col(fd, COL_RES_DL_SRC)) ! col_add_str(fd, COL_RES_DL_SRC, "DTE"); } ! if (((fd->flags & FROM_DCE) && pd[0] == 0x01) || ! (!(fd->flags & FROM_DCE) && pd[0] == 0x03)) ! is_response = TRUE; ! else ! is_response = FALSE; ! if (tree) { ! ti = proto_tree_add_item_format(tree, proto_lapb, 0, 2, NULL, "LAPB"); ! lapb_tree = proto_item_add_subtree(ti, ETT_LAPB); ! proto_tree_add_item_format(lapb_tree, hf_lapb_address, 0, 1, pd[0], ! "Address: 0x%02X", pd[0]); } + else + lapb_tree = NULL; + dissect_xdlc_control(pd, 1, fd, lapb_tree, hf_lapb_control, + FALSE, is_response); /* not end of frame ==> X.25 */ if (fd->cap_len > 2) dissect_x25(pd, 2, fd, tree); diff -c -N ../ethereal.vanilla/packet-llc.c ./packet-llc.c *** ../ethereal.vanilla/packet-llc.c Wed Jul 28 22:46:58 1999 --- ./packet-llc.c Mon Aug 2 23:07:51 1999 *************** *** 34,39 **** --- 34,40 ---- #include <glib.h> #include "packet.h" + #include "xdlc.h" static int proto_llc = -1; static int hf_llc_dsap = -1; *************** *** 207,215 **** llc_tree = proto_item_add_subtree(ti, ETT_LLC); proto_tree_add_item(llc_tree, hf_llc_dsap, offset, 1, pd[offset]); proto_tree_add_item(llc_tree, hf_llc_ssap, offset+1, 1, pd[offset+1]); ! proto_tree_add_item(llc_tree, hf_llc_ctrl, offset+2, 1, pd[offset+2] & 3); ! } if (is_snap) { if (check_col(fd, COL_INFO)) { col_add_str(fd, COL_INFO, "802.2 LLC (SNAP)"); --- 208,254 ---- llc_tree = proto_item_add_subtree(ti, ETT_LLC); proto_tree_add_item(llc_tree, hf_llc_dsap, offset, 1, pd[offset]); proto_tree_add_item(llc_tree, hf_llc_ssap, offset+1, 1, pd[offset+1]); ! } else ! llc_tree = NULL; ! ! /* ! * XXX - we need to determine ! * ! * 1) whether a frame is an LLC-level command or response ! * (RFC 1390, "Transmission of IP and ARP over FDDI ! * Networks", says ! * ! * Command frames are identified by having the ! * low order bit of the SSAP address reset to ! * zero. Response frames have the low order ! * bit of the SSAP address set to one. ! * ! * but I don't know if that's an LLC standard, a ! * SNAP encapsulation standard, or just some ! * convention of RFC 1390) ! * ! * and ! * ! * 2) whether we have basic or extended operation (if ! * we see an SABME command in the session, it's ! * extended operation - but the capture might start ! * after the SABME is sent, in which case we'd ! * either have to be told by the user which it is, ! * or somehow infer it from the contents of the ! * packets). ! */ ! dissect_xdlc_control(pd, offset+2, fd, llc_tree, hf_llc_ctrl, ! FALSE, TRUE); + /* + * XXX - do we want to append the SAP information to the stuff + * "dissect_xdlc_control()" put in the COL_INFO column, rather + * than overwriting it? + * + * XXX - we shouldn't, as far as I know, pass S frames to + * "ethertype" or "dissect", and we may have to treat I frames + * differently from U frames. + */ if (is_snap) { if (check_col(fd, COL_INFO)) { col_add_str(fd, COL_INFO, "802.2 LLC (SNAP)"); diff -c -N ../ethereal.vanilla/packet.h ./packet.h *** ../ethereal.vanilla/packet.h Sun Aug 1 19:04:26 1999 --- ./packet.h Mon Aug 2 21:10:21 1999 *************** *** 297,302 **** --- 297,303 ---- ETT_RADIUS_AVP, ETT_LAPB, ETT_X25, + ETT_XDLC_CONTROL, NUM_TREE_TYPES /* last item number plus one */ }; diff -c -N ../ethereal.vanilla/xdlc.c ./xdlc.c *** ../ethereal.vanilla/xdlc.c Wed Dec 31 16:00:00 1969 --- ./xdlc.c Mon Aug 2 23:09:15 1999 *************** *** 0 **** --- 1,354 ---- + /* xdlc.c + * Routines for use by various SDLC-derived protocols, such as HDLC + * and its derivatives LAPB, IEEE 802.2 LLC, etc.. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + #ifdef HAVE_CONFIG_H + # include "config.h" + #endif + + #ifdef HAVE_SYS_TYPES_H + # include <sys/types.h> + #endif + + #include <stdio.h> + #include <string.h> + + #include <glib.h> + #include "packet.h" + #include "xdlc.h" + + /* + * N(S) and N(R) fields, in basic and extended operation. + */ + #define XDLC_N_R_MASK 0xE0 /* basic */ + #define XDLC_N_R_SHIFT 5 + #define XDLC_N_R_EXT_MASK 0xFE00 /* extended */ + #define XDLC_N_R_EXT_SHIFT 9 + #define XDLC_N_S_MASK 0x0E /* basic */ + #define XDLC_N_S_SHIFT 1 + #define XDLC_N_S_EXT_MASK 0x00FE /* extended */ + #define XDLC_N_S_EXT_SHIFT 1 + + /* + * Poll/Final bit, in basic and extended operation. + */ + #define XDLC_P_F 0x10 /* basic */ + #define XDLC_P_F_EXT 0x0100 /* extended */ + + /* + * S-format frame types. + */ + #define XDLC_S_FTYPE_MASK 0x0C + #define XDLC_RR 0x00 /* Receiver ready */ + #define XDLC_RNR 0x04 /* Receiver not ready */ + #define XDLC_REJ 0x08 /* Reject */ + #define XDLC_SREJ 0x0C /* Selective reject */ + + static const value_string stype_vals[] = { + { XDLC_RR, "Receiver ready" }, + { XDLC_RNR, "Receiver not ready" }, + { XDLC_REJ, "Reject" }, + { XDLC_SREJ, "Selective reject" }, + { 0, NULL } + }; + + /* + * U-format modifiers. + */ + #define XDLC_U_MODIFIER_MASK 0xEC + #define XDLC_UI 0x00 /* Unnumbered Information */ + #define XDLC_UP 0x20 /* Unnumbered Poll */ + #define XDLC_DISC 0x40 /* Disconnect */ + #define XDLC_UA 0x60 /* Unnumbered Acknowledge */ + #define XDLC_SNRM 0x80 /* Set Normal Response Mode */ + #define XDLC_TEST 0xC0 /* Test */ + #define XDLC_RIM 0x04 /* Request Initialization Mode */ + #define XDLC_SIM 0x44 /* Set Initialization Mode */ + #define XDLC_FRMR 0x84 /* Frame reject */ + #define XDLC_CFGR 0xC4 /* Configure */ + #define XDLC_DM 0x0C /* Disconnected mode */ + #define XDLC_SARM 0x0C /* Set Asynchronous Response Mode */ + #define XDLC_SABM 0x2C /* Set Asynchronous Balanced Mode */ + #define XDLC_SARME 0x4C /* Set Asynchronous Response Mode Extended */ + #define XDLC_SABME 0x6C /* Set Asynchronous Balanced Mode Extended */ + #define XDLC_RESET 0x8C /* Reset */ + #define XDLC_SNRME 0xCC /* Set Normal Response Mode Extended */ + #define XDLC_BCN 0xEC /* Beacon */ + + static const value_string modifier_short_vals[] = { + { XDLC_UI, "UI" }, + { XDLC_UP, "UP" }, + { XDLC_DISC, "DISC" }, + { XDLC_UA, "UA" }, + { XDLC_SNRM, "SNRM" }, + { XDLC_TEST, "TEST" }, + { XDLC_RIM, "RIM" }, + { XDLC_SIM, "SIM" }, + { XDLC_FRMR, "FRMR" }, + { XDLC_CFGR, "CFGR" }, + { XDLC_DM, "DM" }, /* XXX - same as SARM */ + { XDLC_SARM, "SARM" }, + { XDLC_SABM, "SABM" }, + { XDLC_SARME, "SARME" }, + { XDLC_SABME, "SABME" }, + { XDLC_RESET, "RESET" }, + { XDLC_SNRME, "SNRME" }, + { XDLC_BCN, "BCN" }, + { 0, NULL } + }; + + static const value_string modifier_vals[] = { + { XDLC_UI, "Unnumbered Information" }, + { XDLC_UP, "Unnumbered Poll" }, + { XDLC_DISC, "Disconnect" }, + { XDLC_UA, "Unnumbered Acknowledge" }, + { XDLC_SNRM, "Set Normal Response Mode" }, + { XDLC_TEST, "Test" }, + { XDLC_RIM, "Request Initialization Mode" }, + { XDLC_SIM, "Set Initialization Mode" }, + { XDLC_FRMR, "Frame reject" }, + { XDLC_CFGR, "Configure" }, + { XDLC_DM, "Disconnected mode" }, /* XXX - same as SARM */ + { XDLC_SARM, "Set Asynchronous Response Mode" }, + { XDLC_SABM, "Set Asynchronous Balanced Mode" }, + { XDLC_SARME, "Set Asynchronous Response Mode Extended" }, + { XDLC_SABME, "Set Asynchronous Balanced Mode Extended" }, + { XDLC_RESET, "Reset" }, + { XDLC_SNRME, "Set Normal Response Mode Extended" }, + { XDLC_BCN, "Beacon" }, + { 0, NULL } + }; + + /* + * XXX - is "is_response" determined by the modifier value? + */ + int + dissect_xdlc_control(const u_char *pd, int offset, frame_data *fd, + proto_tree *xdlc_tree, int hf_xdlc_control, + int is_response, int is_extended) + { + guint16 control; + char info[80]; + proto_tree *tc, *control_tree; + gchar *frame_type = NULL; + gchar *modifier; + + switch (pd[offset] & 0x03) { + + case XDLC_S: + /* + * Supervisory frame. + */ + if (is_extended) + control = pletohs(&pd[offset]); + else + control = pd[offset]; + switch (control & XDLC_S_FTYPE_MASK) { + case XDLC_RR: + frame_type = "RR"; + break; + + case XDLC_RNR: + frame_type = "RNR"; + break; + + case XDLC_REJ: + frame_type = "REJ"; + break; + + case XDLC_SREJ: + frame_type = "SREJ"; + break; + } + if (is_extended) { + sprintf(info, "S%s, func = %s, N(R) = %u", frame_type, + ((control & XDLC_P_F_EXT) ? + (is_response ? " F" : " P") : + ""), + (control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT); + } else { + sprintf(info, "S%s, func = %s, N(R) = %u", frame_type, + ((control & XDLC_P_F) ? + (is_response ? " F" : " P") : + ""), + (control & XDLC_N_R_MASK) >> XDLC_N_R_SHIFT); + } + if (check_col(fd, COL_INFO)) + col_add_str(fd, COL_INFO, info); + if (xdlc_tree) { + if (is_extended) { + tc = proto_tree_add_item_format(xdlc_tree, hf_xdlc_control, + offset, 2, + frame_type, + "Control field: %s (0x%04X)", info, control); + control_tree = proto_item_add_subtree(tc, ETT_XDLC_CONTROL); + /* XXX - make it shift the value appropriately! */ + proto_tree_add_text(control_tree, offset, 2, + decode_numeric_bitfield(control, XDLC_N_R_EXT_MASK, 2*8, + "N(R) = %u")); + if (control & XDLC_P_F_EXT) { + proto_tree_add_text(control_tree, offset, 2, + decode_boolean_bitfield(control, XDLC_P_F_EXT, 2*8, + (is_response ? "Final" : "Poll"), NULL)); + } + proto_tree_add_text(control_tree, offset, 2, + decode_enumerated_bitfield(control, XDLC_S_FTYPE_MASK, 2*8, + stype_vals, "Supervisory frame - %s")); + /* This will always say it's a supervisory frame */ + proto_tree_add_text(control_tree, offset, 2, + decode_boolean_bitfield(control, 0x03, 2*8, + "Supervisory frame", NULL)); + } else { + tc = proto_tree_add_item_format(xdlc_tree, hf_xdlc_control, + offset, 1, + frame_type, + "Control field: %s (0x%02X)", info, control); + control_tree = proto_item_add_subtree(tc, ETT_XDLC_CONTROL); + /* XXX - make it shift the value appropriately! */ + proto_tree_add_text(control_tree, offset, 1, + decode_numeric_bitfield(control, XDLC_N_R_MASK, 1*8, + "N(R) = %u")); + if (control & XDLC_P_F) { + proto_tree_add_text(control_tree, offset, 1, + decode_boolean_bitfield(control, XDLC_P_F, 1*8, + (is_response ? "Final" : "Poll"), NULL)); + } + proto_tree_add_text(control_tree, offset, 1, + decode_enumerated_bitfield(control, XDLC_S_FTYPE_MASK, 1*8, + stype_vals, "%s")); + /* This will always say it's a supervisory frame */ + proto_tree_add_text(control_tree, offset, 1, + decode_boolean_bitfield(control, 0x03, 1*8, + "Supervisory frame", NULL)); + } + } + return XDLC_S; + + case XDLC_U: + /* + * Unnumbered frame. + * + * XXX - is this two octets, with a P/F bit, in HDLC extended + * operation? It's one octet in LLC, even though the control + * field of I and S frames is a 2-byte extended-operation field + * in LLC. Given that there are no sequence numbers in the + * control field of a U frame, there doesn't appear to be any + * need for it to be 2 bytes in extended operation. + */ + control = pd[offset]; + modifier = match_strval(control & XDLC_U_MODIFIER_MASK, + modifier_short_vals); + if (modifier == NULL) + modifier = "Unknown"; + sprintf(info, "U%s, func = %s", + ((control & XDLC_P_F) ? " P" : ""), modifier); + if (check_col(fd, COL_INFO)) + col_add_str(fd, COL_INFO, info); + if (xdlc_tree) { + tc = proto_tree_add_item_format(xdlc_tree, hf_xdlc_control, + offset, 1, + frame_type, + "Control field: %s (0x%02X)", info, control); + control_tree = proto_item_add_subtree(tc, ETT_XDLC_CONTROL); + if (control & XDLC_P_F) { + proto_tree_add_text(control_tree, offset, 2, + decode_boolean_bitfield(control, XDLC_P_F, 1*8, + "Poll", NULL)); + } + proto_tree_add_text(control_tree, offset, 1, + decode_enumerated_bitfield(control, XDLC_U_MODIFIER_MASK, 1*8, + modifier_vals, "%s")); + /* This will always say it's an unnumbered frame */ + proto_tree_add_text(control_tree, offset, 1, + decode_boolean_bitfield(control, 0x03, 1*8, + "Unnumbered frame", NULL)); + } + return XDLC_U; + + default: + /* + * Information frame. + */ + control = pd[offset]; + if (is_extended) { + sprintf(info, "I%s, N(R) = %u, N(S) = %u", + ((control & XDLC_P_F_EXT) ? " P" : ""), + (control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT, + (control & XDLC_N_S_EXT_MASK) >> XDLC_N_S_EXT_SHIFT); + } else { + sprintf(info, "I%s, N(R) = %u, N(S) = %u", + ((control & XDLC_P_F) ? " P" : ""), + (control & XDLC_N_R_MASK) >> XDLC_N_R_SHIFT, + (control & XDLC_N_S_MASK) >> XDLC_N_S_SHIFT); + } + if (check_col(fd, COL_INFO)) + col_add_str(fd, COL_INFO, info); + if (xdlc_tree) { + tc = proto_tree_add_item_format(xdlc_tree, hf_xdlc_control, + offset, 2, + frame_type, + "Control field: %s (0x%04X)", info, control); + control_tree = proto_item_add_subtree(tc, ETT_XDLC_CONTROL); + if (is_extended) { + /* XXX - make it shift the value appropriately! */ + proto_tree_add_text(control_tree, offset, 2, + decode_numeric_bitfield(control, XDLC_N_R_EXT_MASK, 2*8, + "N(R) = %u")); + /* XXX - make it shift the value appropriately! */ + proto_tree_add_text(control_tree, offset, 2, + decode_numeric_bitfield(control, XDLC_N_S_EXT_MASK, 2*8, + "N(S) = %u")); + if (control & XDLC_P_F_EXT) { + proto_tree_add_text(control_tree, offset, 2, + decode_boolean_bitfield(control, XDLC_P_F_EXT, 2*8, + "Poll", NULL)); + } + /* This will always say it's an information frame */ + proto_tree_add_text(control_tree, offset, 2, + decode_boolean_bitfield(control, 0x01, 2*8, + NULL, "Information frame")); + } else { + /* XXX - make it shift the value appropriately! */ + proto_tree_add_text(control_tree, offset, 1, + decode_numeric_bitfield(control, XDLC_N_R_MASK, 1*8, + "N(R) = %u")); + /* XXX - make it shift the value appropriately! */ + proto_tree_add_text(control_tree, offset, 1, + decode_numeric_bitfield(control, XDLC_N_S_MASK, 1*8, + "N(S) = %u")); + if (control & XDLC_P_F) { + proto_tree_add_text(control_tree, offset, 1, + decode_boolean_bitfield(control, XDLC_P_F, 1*8, + "Poll", NULL)); + } + /* This will always say it's an information frame */ + proto_tree_add_text(control_tree, offset, 1, + decode_boolean_bitfield(control, 0x01, 1*8, + NULL, "Information frame")); + } + } + return XDLC_I; + } + } diff -c -N ../ethereal.vanilla/xdlc.h ./xdlc.h *** ../ethereal.vanilla/xdlc.h Wed Dec 31 16:00:00 1969 --- ./xdlc.h Mon Aug 2 23:06:13 1999 *************** *** 0 **** --- 1,36 ---- + /* xdlc.h + * Define *DLC frame types, and routine to dissect the control field of + * a *DLC frame. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@xxxxxxxxxx> + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + /* + * Low-order bits of first (extended) or only (basic) octet of control + * field, specifying the frame type. + */ + #define XDLC_I 0x00 /* Information frames */ + #define XDLC_S 0x01 /* Supervisory frames */ + #define XDLC_U 0x03 /* Unnumbered frames */ + + int dissect_xdlc_control(const u_char *pd, int offset, frame_data *fd, + proto_tree *xdlc_tree, int hf_xdlc_control, int is_response, int extended);
- Follow-Ups:
- Re: [ethereal-dev] LAPB/X.25 patch
- From: Olivier Abad
- Re: [ethereal-dev] LAPB/X.25 patch
- References:
- Re: [ethereal-dev] LAPB/X.25 patch
- From: Guy Harris
- Re: [ethereal-dev] LAPB/X.25 patch
- From: Olivier Abad
- Re: [ethereal-dev] LAPB/X.25 patch
- From: Guy Harris
- Re: [ethereal-dev] LAPB/X.25 patch
- From: Richard Sharpe
- Re: [ethereal-dev] LAPB/X.25 patch
- Prev by Date: Re: [ethereal-dev] LAPB/X.25 patch
- Next by Date: Re: [ethereal-dev] -Wall fixes for FreeBSD
- Previous by thread: Re: [ethereal-dev] LAPB/X.25 patch
- Next by thread: Re: [ethereal-dev] LAPB/X.25 patch
- Index(es):