2 * Routines for ppp packet disassembly
4 * $Id: packet-ppp.c,v 1.25 2000/01/23 08:55:35 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
9 * This file created and by Mike Hall <mlh@io.com>
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.
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.
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.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
37 #include "packet-ip.h"
39 static int proto_ppp = -1;
41 static gint ett_ppp = -1;
42 static gint ett_ipcp = -1;
43 static gint ett_ipcp_options = -1;
44 static gint ett_ipcp_ipaddrs_opt = -1;
45 static gint ett_ipcp_compressprot_opt = -1;
46 static gint ett_lcp = -1;
47 static gint ett_lcp_options = -1;
48 static gint ett_lcp_mru_opt = -1;
49 static gint ett_lcp_async_map_opt = -1;
50 static gint ett_lcp_authprot_opt = -1;
51 static gint ett_lcp_qualprot_opt = -1;
52 static gint ett_lcp_magicnum_opt = -1;
53 static gint ett_lcp_fcs_alternatives_opt = -1;
54 static gint ett_lcp_numbered_mode_opt = -1;
55 static gint ett_lcp_callback_opt = -1;
56 static gint ett_lcp_multilink_ep_disc_opt = -1;
57 static gint ett_lcp_internationalization_opt = -1;
59 static int proto_mp = -1;
60 static int hf_mp_frag_first = -1;
61 static int hf_mp_frag_last = -1;
62 static int hf_mp_sequence_num = -1;
64 static int ett_mp = -1;
65 static int ett_mp_flags = -1;
67 /* PPP structs and definitions */
69 typedef struct _e_ppphdr {
76 /* Protocol types, from Linux "ppp_defs.h" and
78 http://www.isi.edu/in-notes/iana/assignments/ppp-numbers
81 #define PPP_IP 0x21 /* Internet Protocol */
82 #define PPP_AT 0x29 /* AppleTalk Protocol */
83 #define PPP_IPX 0x2b /* IPX protocol */
84 #define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
85 #define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
86 #define PPP_VINES 0x35 /* Banyan Vines */
87 #define PPP_MP 0x3d /* Multilink PPP */
88 #define PPP_IPV6 0x57 /* Internet Protocol Version 6 */
89 #define PPP_COMP 0xfd /* compressed packet */
90 #define PPP_IPCP 0x8021 /* IP Control Protocol */
91 #define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
92 #define PPP_IPXCP 0x802b /* IPX Control Protocol */
93 #define PPP_CCP 0x80fd /* Compression Control Protocol */
94 #define PPP_LCP 0xc021 /* Link Control Protocol */
95 #define PPP_PAP 0xc023 /* Password Authentication Protocol */
96 #define PPP_LQR 0xc025 /* Link Quality Report protocol */
97 #define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
98 #define PPP_CBCP 0xc029 /* Callback Control Protocol */
100 static const value_string ppp_vals[] = {
102 {PPP_AT, "Appletalk" },
103 {PPP_IPX, "Netware IPX/SPX"},
104 {PPP_VJC_COMP, "VJ compressed TCP"},
105 {PPP_VJC_UNCOMP,"VJ uncompressed TCP"},
106 {PPP_VINES, "Vines" },
107 {PPP_MP, "Multilink"},
109 {PPP_COMP, "compressed packet" },
110 {PPP_IPCP, "IP Control Protocol" },
111 {PPP_ATCP, "AppleTalk Control Protocol" },
112 {PPP_IPXCP, "IPX Control Protocol" },
113 {PPP_CCP, "Compression Control Protocol" },
114 {PPP_LCP, "Link Control Protocol" },
115 {PPP_PAP, "Password Authentication Protocol" },
116 {PPP_LQR, "Link Quality Report protocol" },
117 {PPP_CHAP, "Cryptographic Handshake Auth. Protocol" },
118 {PPP_CBCP, "Callback Control Protocol" },
122 /* CP (LCP, IPCP, etc.) codes.
125 #define CONFREQ 1 /* Configuration Request */
126 #define CONFACK 2 /* Configuration Ack */
127 #define CONFNAK 3 /* Configuration Nak */
128 #define CONFREJ 4 /* Configuration Reject */
129 #define TERMREQ 5 /* Termination Request */
130 #define TERMACK 6 /* Termination Ack */
131 #define CODEREJ 7 /* Code Reject */
133 static const value_string cp_vals[] = {
134 {CONFREQ, "Configuration Request" },
135 {CONFACK, "Configuration Ack" },
136 {CONFNAK, "Configuration Nak" },
137 {CONFREJ, "Configuration Reject" },
138 {TERMREQ, "Termination Request" },
139 {TERMACK, "Termination Ack" },
140 {CODEREJ, "Code Reject" },
144 * LCP-specific packet types.
146 #define PROTREJ 8 /* Protocol Reject */
147 #define ECHOREQ 9 /* Echo Request */
148 #define ECHOREP 10 /* Echo Reply */
149 #define DISCREQ 11 /* Discard Request */
150 #define IDENT 12 /* Identification */
151 #define TIMEREMAIN 13 /* Time remaining */
153 #define CBCP_OPT 6 /* Use callback control protocol */
155 static const value_string lcp_vals[] = {
156 {CONFREQ, "Configuration Request" },
157 {CONFACK, "Configuration Ack" },
158 {CONFNAK, "Configuration Nak" },
159 {CONFREJ, "Configuration Reject" },
160 {TERMREQ, "Termination Request" },
161 {TERMACK, "Termination Ack" },
162 {CODEREJ, "Code Reject" },
163 {PROTREJ, "Protocol Reject" },
164 {ECHOREQ, "Echo Request" },
165 {ECHOREP, "Echo Reply" },
166 {DISCREQ, "Discard Request" },
167 {IDENT, "Identification" },
168 {TIMEREMAIN, "Time Remaining" },
175 #define CI_MRU 1 /* Maximum Receive Unit */
176 #define CI_ASYNCMAP 2 /* Async Control Character Map */
177 #define CI_AUTHTYPE 3 /* Authentication Type */
178 #define CI_QUALITY 4 /* Quality Protocol */
179 #define CI_MAGICNUMBER 5 /* Magic Number */
180 #define CI_PCOMPRESSION 7 /* Protocol Field Compression */
181 #define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
182 #define CI_FCS_ALTERNATIVES 9 /* FCS Alternatives (RFC 1570) */
183 #define CI_SELF_DESCRIBING_PAD 10 /* Self-Describing Pad (RFC 1570) */
184 #define CI_NUMBERED_MODE 11 /* Numbered Mode (RFC 1663) */
185 #define CI_CALLBACK 13 /* Callback (RFC 1570) */
186 #define CI_COMPOUND_FRAMES 15 /* Compound frames (RFC 1570) */
187 #define CI_MULTILINK_MRRU 17 /* Multilink MRRU (RFC 1717) */
188 #define CI_MULTILINK_SSNH 18 /* Multilink Short Sequence Number
190 #define CI_MULTILINK_EP_DISC 19 /* Multilink Endpoint Discriminator
192 #define CI_DCE_IDENTIFIER 21 /* DCE Identifier */
193 #define CI_MULTILINK_PLUS_PROC 22 /* Multilink Plus Procedure */
194 #define CI_LINK_DISC_FOR_BACP 23 /* Link Discriminator for BACP
196 #define CI_LCP_AUTHENTICATION 24 /* LCP Authentication Option */
197 #define CI_COBS 25 /* Consistent Overhead Byte
199 #define CI_PREFIX_ELISION 26 /* Prefix elision */
200 #define CI_MULTILINK_HDR_FMT 27 /* Multilink header format */
201 #define CI_INTERNATIONALIZATION 28 /* Internationalization (RFC 2484) */
202 #define CI_SDL_ON_SONET_SDH 29 /* Simple Data Link on SONET/SDH */
204 static void dissect_lcp_mru_opt(const ip_tcp_opt *optp, const u_char *opd,
205 int offset, guint length, proto_tree *tree);
206 static void dissect_lcp_async_map_opt(const ip_tcp_opt *optp, const u_char *opd,
207 int offset, guint length, proto_tree *tree);
208 static void dissect_lcp_protocol_opt(const ip_tcp_opt *optp, const u_char *opd,
209 int offset, guint length, proto_tree *tree);
210 static void dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp,
211 const u_char *opd, int offset, guint length,
213 static void dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp,
214 const u_char *opd, int offset, guint length,
216 static void dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp,
217 const u_char *opd, int offset, guint length,
219 static void dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp,
220 const u_char *opd, int offset, guint length,
222 static void dissect_lcp_callback_opt(const ip_tcp_opt *optp, const u_char *opd,
223 int offset, guint length, proto_tree *tree);
224 static void dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp,
225 const u_char *opd, int offset, guint length,
227 static void dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp,
228 const u_char *opd, int offset, guint length,
230 static void dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp,
231 const u_char *opd, int offset, guint length,
233 static void dissect_lcp_internationalization_opt(const ip_tcp_opt *optp,
234 const u_char *opd, int offset, guint length,
236 static void dissect_mp(const u_char *pd, int offset, frame_data *fd,
237 proto_tree *tree, proto_tree *fh_tree);
239 static const ip_tcp_opt lcp_opts[] = {
242 "Maximum Receive Unit",
250 "Async Control Character Map",
251 &ett_lcp_async_map_opt,
254 dissect_lcp_async_map_opt
258 "Authentication protocol",
259 &ett_lcp_authprot_opt,
262 dissect_lcp_protocol_opt
267 &ett_lcp_qualprot_opt,
270 dissect_lcp_protocol_opt
275 &ett_lcp_magicnum_opt,
278 dissect_lcp_magicnumber_opt
282 "Protocol field compression",
290 "Address/control field compression",
299 &ett_lcp_fcs_alternatives_opt,
302 dissect_lcp_fcs_alternatives_opt
305 CI_SELF_DESCRIBING_PAD,
310 dissect_lcp_self_describing_pad_opt
315 &ett_lcp_numbered_mode_opt,
318 dissect_lcp_numbered_mode_opt
323 &ett_lcp_callback_opt,
326 dissect_lcp_callback_opt,
342 dissect_lcp_multilink_mrru_opt
346 "Use short sequence number headers",
353 CI_MULTILINK_EP_DISC,
354 "Multilink endpoint discriminator",
355 &ett_lcp_multilink_ep_disc_opt,
358 dissect_lcp_multilink_ep_disc_opt,
369 CI_MULTILINK_PLUS_PROC,
370 "Multilink Plus Procedure",
377 CI_LINK_DISC_FOR_BACP,
382 dissect_lcp_bap_link_discriminator_opt
385 CI_LCP_AUTHENTICATION,
386 "LCP authentication",
394 "Consistent Overhead Byte Stuffing",
409 CI_MULTILINK_HDR_FMT,
410 "Multilink header format",
417 CI_INTERNATIONALIZATION,
418 "Internationalization",
419 &ett_lcp_internationalization_opt,
422 dissect_lcp_internationalization_opt
426 "Simple data link on SONET/SDH",
434 #define N_LCP_OPTS (sizeof lcp_opts / sizeof lcp_opts[0])
439 #define CI_ADDRS 1 /* IP Addresses (deprecated) (RFC 1172) */
440 #define CI_COMPRESSTYPE 2 /* Compression Type (RFC 1332) */
441 #define CI_ADDR 3 /* IP Address (RFC 1332) */
442 #define CI_MOBILE_IPv4 4 /* Mobile IPv4 (RFC 2290) */
443 #define CI_MS_DNS1 129 /* Primary DNS value (RFC 1877) */
444 #define CI_MS_WINS1 130 /* Primary WINS value (RFC 1877) */
445 #define CI_MS_DNS2 131 /* Secondary DNS value (RFC 1877) */
446 #define CI_MS_WINS2 132 /* Secondary WINS value (RFC 1877) */
448 static void dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, const u_char *opd,
449 int offset, guint length, proto_tree *tree);
450 static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, const u_char *opd,
451 int offset, guint length, proto_tree *tree);
453 static const ip_tcp_opt ipcp_opts[] = {
456 "IP addresses (deprecated)",
457 &ett_ipcp_ipaddrs_opt,
460 dissect_ipcp_addrs_opt
464 "IP compression protocol",
465 &ett_ipcp_compressprot_opt,
468 dissect_lcp_protocol_opt
476 dissect_ipcp_addr_opt
480 "Mobile node's home IP address",
484 dissect_ipcp_addr_opt
488 "Primary DNS server IP address",
492 dissect_ipcp_addr_opt
496 "Primary WINS server IP address",
500 dissect_ipcp_addr_opt
504 "Secondary DNS server IP address",
508 dissect_ipcp_addr_opt
512 "Secondary WINS server IP address",
516 dissect_ipcp_addr_opt
520 #define N_IPCP_OPTS (sizeof ipcp_opts / sizeof ipcp_opts[0])
523 capture_ppp( const u_char *pd, packet_counts *ld ) {
524 switch (pntohs(&pd[2])) {
526 capture_ip(pd, 4, ld);
529 capture_ipx(pd, 4, ld);
532 capture_ipx(pd, 4, ld);
541 dissect_lcp_mru_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
542 guint length, proto_tree *tree)
544 proto_tree_add_text(tree, offset, length, "MRU: %u", pntohs(opd));
548 dissect_lcp_async_map_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
549 guint length, proto_tree *tree)
551 proto_tree_add_text(tree, offset, length, "Async characters to map: 0x%08x",
556 dissect_lcp_protocol_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
557 guint length, proto_tree *tree)
561 proto_tree *field_tree = NULL;
563 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
564 optp->name, length, plurality(length, "", "s"));
565 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
568 protocol = pntohs(opd);
569 proto_tree_add_text(field_tree, offset, 2, "%s: %s (0x%02x)", optp->name,
570 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
575 proto_tree_add_text(field_tree, offset, length, "Data (%d byte%s)", length,
576 plurality(length, "", "s"));
580 dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp, const u_char *opd,
581 int offset, guint length, proto_tree *tree)
583 proto_tree_add_text(tree, offset, length, "Magic number: 0x%08x",
588 dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp, const u_char *opd,
589 int offset, guint length, proto_tree *tree)
592 proto_tree *field_tree = NULL;
596 tf = proto_tree_add_text(tree, offset, length, "%s: 0x%02x",
597 optp->name, alternatives);
598 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
600 if (alternatives & 0x1)
601 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
602 decode_boolean_bitfield(alternatives, 0x1, 8, "Null FCS", NULL));
603 if (alternatives & 0x2)
604 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
605 decode_boolean_bitfield(alternatives, 0x2, 8, "CCITT 16-bit FCS", NULL));
606 if (alternatives & 0x4)
607 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
608 decode_boolean_bitfield(alternatives, 0x4, 8, "CCITT 32-bit FCS", NULL));
612 dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp, const u_char *opd,
613 int offset, guint length, proto_tree *tree)
615 proto_tree_add_text(tree, offset, length,
616 "Maximum octets of self-describing padding: %u",
621 dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp, const u_char *opd,
622 int offset, guint length, proto_tree *tree)
625 proto_tree *field_tree = NULL;
627 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
628 optp->name, length, plurality(length, "", "s"));
629 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
632 proto_tree_add_text(field_tree, offset, 1, "Window: %u", *opd);
637 proto_tree_add_text(field_tree, offset, length, "Address (%d byte%s)",
638 length, plurality(length, "", "s"));
641 static const value_string callback_op_vals[] = {
642 {0, "Location is determined by user authentication" },
643 {1, "Message is dialing string" },
644 {2, "Message is location identifier" },
645 {3, "Message is E.164" },
646 {4, "Message is distinguished name" },
651 dissect_lcp_callback_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
652 guint length, proto_tree *tree)
655 proto_tree *field_tree = NULL;
657 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
658 optp->name, length, plurality(length, "", "s"));
659 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
662 proto_tree_add_text(field_tree, offset, 1, "Operation: %s (0x%02x)",
663 val_to_str(*opd, callback_op_vals, "Unknown"),
669 proto_tree_add_text(field_tree, offset, length, "Message (%d byte%s)",
670 length, plurality(length, "", "s"));
674 dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp, const u_char *opd,
675 int offset, guint length, proto_tree *tree)
677 proto_tree_add_text(tree, offset, length, "Multilink MRRU: %u",
682 #define CLASS_LOCAL 1
684 #define CLASS_IEEE_802_1 3
685 #define CLASS_PPP_MAGIC_NUMBER 4
686 #define CLASS_PSDN_DIRECTORY_NUMBER 5
688 static const value_string multilink_ep_disc_class_vals[] = {
689 {CLASS_NULL, "Null" },
690 {CLASS_LOCAL, "Locally assigned address" },
691 {CLASS_IP, "IP address" },
692 {CLASS_IEEE_802_1, "IEEE 802.1 globally assigned MAC address" },
693 {CLASS_PPP_MAGIC_NUMBER, "PPP magic-number block" },
694 {CLASS_PSDN_DIRECTORY_NUMBER, "Public switched network directory number" },
699 dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp, const u_char *opd,
700 int offset, guint length, proto_tree *tree)
703 proto_tree *field_tree = NULL;
704 guint8 ep_disc_class;
706 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
707 optp->name, length, plurality(length, "", "s"));
708 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
711 ep_disc_class = *opd;
712 proto_tree_add_text(field_tree, offset, 1, "Class: %s (%u)",
713 val_to_str(ep_disc_class, multilink_ep_disc_class_vals, "Unknown"),
719 switch (ep_disc_class) {
722 proto_tree_add_text(field_tree, offset, length,
723 "Address (%d byte%s), should have been empty",
724 length, plurality(length, "", "s"));
729 proto_tree_add_text(field_tree, offset, length,
730 "Address (%d byte%s), should have been <20",
731 length, plurality(length, "", "s"));
733 proto_tree_add_text(field_tree, offset, length,
734 "Address (%d byte%s)",
735 length, plurality(length, "", "s"));
741 proto_tree_add_text(field_tree, offset, length,
742 "Address (%d byte%s), should have been 4",
743 length, plurality(length, "", "s"));
745 proto_tree_add_text(field_tree, offset, length,
746 "Address: %s", ip_to_str(opd));
750 case CLASS_IEEE_802_1:
752 proto_tree_add_text(field_tree, offset, length,
753 "Address (%d byte%s), should have been 6",
754 length, plurality(length, "", "s"));
756 proto_tree_add_text(field_tree, offset, length,
757 "Address: %s", ether_to_str(opd));
761 case CLASS_PPP_MAGIC_NUMBER:
762 /* XXX - dissect as 32-bit magic numbers */
764 proto_tree_add_text(field_tree, offset, length,
765 "Address (%d byte%s), should have been <20",
766 length, plurality(length, "", "s"));
768 proto_tree_add_text(field_tree, offset, length,
769 "Address (%d byte%s)",
770 length, plurality(length, "", "s"));
774 case CLASS_PSDN_DIRECTORY_NUMBER:
776 proto_tree_add_text(field_tree, offset, length,
777 "Address (%d byte%s), should have been <20",
778 length, plurality(length, "", "s"));
780 proto_tree_add_text(field_tree, offset, length,
781 "Address (%d byte%s)",
782 length, plurality(length, "", "s"));
787 proto_tree_add_text(field_tree, offset, length,
788 "Address (%d byte%s)",
789 length, plurality(length, "", "s"));
796 dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp, const u_char *opd,
797 int offset, guint length, proto_tree *tree)
799 proto_tree_add_text(tree, offset, length,
800 "Link discriminator for BAP: 0x%04x",
804 /* Character set numbers from the IANA charset registry. */
805 static const value_string charset_num_vals[] = {
811 dissect_lcp_internationalization_opt(const ip_tcp_opt *optp, const u_char *opd,
812 int offset, guint length, proto_tree *tree)
815 proto_tree *field_tree = NULL;
817 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
818 optp->name, length, plurality(length, "", "s"));
819 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
822 proto_tree_add_text(field_tree, offset, 4, "Character set: %s (0x%04x)",
823 val_to_str(pntohl(opd), charset_num_vals, "Unknown"),
829 /* XXX - should be displayed as an ASCII string */
830 proto_tree_add_text(field_tree, offset, length, "Language tag (%d byte%s)",
831 length, plurality(length, "", "s"));
836 dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, const u_char *opd,
837 int offset, guint length, proto_tree *tree)
840 proto_tree *field_tree = NULL;
842 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
843 optp->name, length, plurality(length, "", "s"));
844 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
847 proto_tree_add_text(field_tree, offset, 4,
848 "Source IP address: %s", ip_to_str(opd));
852 proto_tree_add_text(field_tree, offset, 4,
853 "Destination IP address: %s", ip_to_str(opd));
856 static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, const u_char *opd,
857 int offset, guint length, proto_tree *tree)
859 proto_tree_add_text(tree, offset, length, "%s: %s", optp->name,
860 ip_to_str((guint8 *)opd));
864 dissect_cp( const u_char *pd, int offset, const char *proto_short_name,
865 const char *proto_long_name, int proto_subtree_index,
866 const value_string *proto_vals, int options_subtree_index,
867 const ip_tcp_opt *opts, int nopts, frame_data *fd, proto_tree *tree ) {
869 proto_tree *fh_tree = NULL;
871 proto_tree *field_tree;
880 length = pntohs(&pd[2+offset]);
882 if(check_col(fd, COL_INFO))
883 col_add_fstr(fd, COL_INFO, "%sCP %s", proto_short_name,
884 val_to_str(code, proto_vals, "Unknown"));
887 ti = proto_tree_add_text(tree, 0+offset, 4, "%s Control Protocol",
889 fh_tree = proto_item_add_subtree(ti, proto_subtree_index);
890 proto_tree_add_text(fh_tree, 0+offset, 1, "Code: %s (0x%02x)",
891 val_to_str(code, proto_vals, "Unknown"), code);
892 proto_tree_add_text(fh_tree, 1+offset, 1, "Identifier: 0x%02x",
894 proto_tree_add_text(fh_tree, 2+offset, 2, "Length: %u",
907 tf = proto_tree_add_text(fh_tree, offset, length,
908 "Options: (%d byte%s)", length, plurality(length, "", "s"));
909 field_tree = proto_item_add_subtree(tf, options_subtree_index);
910 dissect_ip_tcp_options(&pd[offset], offset, length, opts, nopts,
921 proto_tree_add_text(fh_tree, offset, 4, "Magic number: 0x%08x",
922 pntohl(&pd[offset]));
926 proto_tree_add_text(fh_tree, offset, length, "Message (%d byte%s)",
927 length, plurality(length, "", "s"));
933 proto_tree_add_text(fh_tree, offset, 4, "Magic number: 0x%08x",
934 pntohl(&pd[offset]));
937 proto_tree_add_text(fh_tree, offset, 4, "Seconds remaining: %u",
938 pntohl(&pd[offset]));
942 proto_tree_add_text(fh_tree, offset, length, "Message (%d byte%s)",
943 length, plurality(length, "", "s"));
949 protocol = pntohs(&pd[offset]);
950 proto_tree_add_text(fh_tree, offset, 2, "Rejected protocol: %s (0x%04x)",
951 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
955 proto_tree_add_text(fh_tree, offset, length, "Rejected packet (%d byte%s)",
956 length, plurality(length, "", "s"));
957 /* XXX - should be dissected as a PPP packet */
962 /* decode the rejected LCP packet here. */
964 proto_tree_add_text(fh_tree, offset, length, "Rejected packet (%d byte%s)",
965 length, plurality(length, "", "s"));
971 proto_tree_add_text(fh_tree, offset, length, "Data (%d byte%s)",
972 length, plurality(length, "", "s"));
977 proto_tree_add_text(fh_tree, offset, length, "Stuff (%d byte%s)",
978 length, plurality(length, "", "s"));
983 /* Protocol field compression */
987 dissect_ppp_stuff( const u_char *pd, int offset, frame_data *fd,
988 proto_tree *tree, proto_tree *fh_tree ) {
992 if (pd[offset] & PFC_BIT) {
993 ppp_prot = pd[offset];
996 ppp_prot = pntohs(&pd[offset]);
1001 proto_tree_add_text(fh_tree, offset, proto_len, "Protocol: %s (0x%04x)",
1002 val_to_str(ppp_prot, ppp_vals, "Unknown"), ppp_prot);
1004 offset += proto_len;
1008 dissect_ip(pd, offset, fd, tree);
1011 dissect_ddp(pd, offset, fd, tree);
1014 dissect_ipx(pd, offset, fd, tree);
1017 dissect_vines(pd, offset, fd, tree);
1020 dissect_mp(pd, offset, fd, tree, fh_tree);
1023 dissect_ipv6(pd, offset, fd, tree);
1026 dissect_cp(pd, offset, "L", "Link", ett_lcp, lcp_vals, ett_lcp_options,
1027 lcp_opts, N_LCP_OPTS, fd, tree);
1030 dissect_cp(pd, offset, "IP", "IP", ett_ipcp, cp_vals, ett_ipcp_options,
1031 ipcp_opts, N_IPCP_OPTS, fd, tree);
1034 if (check_col(fd, COL_INFO))
1035 col_add_fstr(fd, COL_INFO, "PPP %s (0x%04x)",
1036 val_to_str(ppp_prot, ppp_vals, "Unknown"), ppp_prot);
1037 dissect_data(pd, offset, fd, tree);
1042 #define MP_FRAG_MASK 0xC0
1043 #define MP_FRAG(bits) ((bits) & MP_FRAG_MASK)
1044 #define MP_FRAG_FIRST 0x80
1045 #define MP_FRAG_LAST 0x40
1046 #define MP_FRAG_RESERVED 0x3f
1048 /* According to RFC 1717, the length the MP header isn't indicated anywhere
1049 in the header itself. It starts out at four bytes and can be
1050 negotiated down to two using LCP. We currently assume that all
1051 headers are four bytes. - gcc
1054 dissect_mp(const u_char *pd, int offset, frame_data *fd,
1055 proto_tree *tree, proto_tree *fh_tree)
1057 proto_tree *ti, *mp_tree, *hdr_tree;
1064 first = flags && MP_FRAG_FIRST;
1065 last = flags && MP_FRAG_LAST;
1066 memcpy(&seq, &pd[offset + 1], 3);
1068 if (check_col(fd, COL_INFO))
1069 col_add_fstr(fd, COL_INFO, "PPP Multilink");
1074 strcpy(flag_str, "First");
1077 strcpy(flag_str, "Last");
1079 case MP_FRAG_FIRST|MP_FRAG_LAST:
1080 strcpy(flag_str, "First, Last");
1083 strcpy(flag_str, "Unknown");
1086 ti = proto_tree_add_item(tree, proto_mp, offset, 4, NULL);
1087 mp_tree = proto_item_add_subtree(ti, ett_mp);
1088 ti = proto_tree_add_text(mp_tree, offset, 1, "Fragment: 0x%2X (%s)",
1090 hdr_tree = proto_item_add_subtree(ti, ett_mp_flags);
1091 proto_tree_add_item_format(hdr_tree, hf_mp_frag_first, offset, 1, first,
1092 "%s", decode_boolean_bitfield(flags, MP_FRAG_FIRST, sizeof(flags) * 8,
1093 "first", "not first"));
1094 proto_tree_add_item_format(hdr_tree, hf_mp_frag_last, offset, 1, last,
1095 "%s", decode_boolean_bitfield(flags, MP_FRAG_LAST, sizeof(flags) * 8,
1096 "last", "not last"));
1097 proto_tree_add_text(hdr_tree, offset, 1, "%s",
1098 decode_boolean_bitfield(flags, MP_FRAG_RESERVED, sizeof(flags) * 8,
1099 "reserved", "reserved"));
1100 proto_tree_add_item_format(mp_tree, hf_mp_sequence_num,
1101 offset + 1, 3, seq, "Sequence: %lu", seq);
1106 if (fd->cap_len > offset) {
1108 ti = proto_tree_add_item(tree, proto_ppp, offset, 1, NULL);
1109 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1111 dissect_ppp_stuff(pd, offset, fd, tree, fh_tree);
1116 dissect_payload_ppp( const u_char *pd, int offset, frame_data *fd, proto_tree *tree ) {
1118 proto_tree *fh_tree = NULL;
1120 /* populate a tree in the second pane with the status of the link
1123 ti = proto_tree_add_item(tree, proto_ppp, 0+offset, 2, NULL);
1124 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1127 dissect_ppp_stuff(pd, offset, fd, tree, fh_tree);
1131 dissect_ppp( const u_char *pd, frame_data *fd, proto_tree *tree ) {
1134 proto_tree *fh_tree = NULL;
1136 ph.ppp_addr = pd[0];
1138 ph.ppp_prot = pntohs(&pd[2]);
1140 /* load the top pane info. This should be overwritten by
1141 the next protocol in the stack */
1143 if(check_col(fd, COL_RES_DL_SRC))
1144 col_add_str(fd, COL_RES_DL_SRC, "N/A" );
1145 if(check_col(fd, COL_RES_DL_DST))
1146 col_add_str(fd, COL_RES_DL_DST, "N/A" );
1147 if(check_col(fd, COL_PROTOCOL))
1148 col_add_str(fd, COL_PROTOCOL, "PPP" );
1150 /* populate a tree in the second pane with the status of the link
1153 ti = proto_tree_add_item(tree, proto_ppp, 0, 4, NULL);
1154 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1155 proto_tree_add_text(fh_tree, 0, 1, "Address: %02x", ph.ppp_addr);
1156 proto_tree_add_text(fh_tree, 1, 1, "Control: %02x", ph.ppp_ctl);
1159 if (!dissect_ppp_stuff(pd, 2, fd, tree, fh_tree)) {
1160 if (check_col(fd, COL_PROTOCOL))
1161 col_add_fstr(fd, COL_PROTOCOL, "0x%04x", ph.ppp_prot);
1166 proto_register_ppp(void)
1168 /* static hf_register_info hf[] = {
1170 { "Name", "ppp.abbreviation", TYPE, VALS_POINTER }},
1172 static gint *ett[] = {
1176 &ett_ipcp_ipaddrs_opt,
1177 &ett_ipcp_compressprot_opt,
1181 &ett_lcp_async_map_opt,
1182 &ett_lcp_authprot_opt,
1183 &ett_lcp_qualprot_opt,
1184 &ett_lcp_magicnum_opt,
1185 &ett_lcp_fcs_alternatives_opt,
1186 &ett_lcp_numbered_mode_opt,
1187 &ett_lcp_callback_opt,
1188 &ett_lcp_multilink_ep_disc_opt,
1189 &ett_lcp_internationalization_opt,
1192 proto_ppp = proto_register_protocol("Point-to-Point Protocol", "ppp");
1193 /* proto_register_field_array(proto_ppp, hf, array_length(hf));*/
1194 proto_register_subtree_array(ett, array_length(ett));
1198 proto_register_mp(void)
1200 static hf_register_info hf[] = {
1201 { &hf_mp_frag_first,
1202 { "First fragment", "mp.first", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1206 { "Last fragment", "mp.last", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1209 { &hf_mp_sequence_num,
1210 { "Sequence number", "mp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
1213 static gint *ett[] = {
1218 proto_mp = proto_register_protocol("PPP Multilink Protocol", "mp");
1219 proto_register_field_array(proto_mp, hf, array_length(hf));
1220 proto_register_subtree_array(ett, array_length(ett));