2 * Routines for ppp packet disassembly
4 * $Id: packet-ppp.c,v 1.23 1999/11/30 23:56:36 gram 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, guint32 cap_len, packet_counts *ld ) {
524 switch (pntohs(&pd[2])) {
526 capture_ip(pd, 4, cap_len, ld);
529 capture_ipx(pd, 4, cap_len, ld);
538 dissect_lcp_mru_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
539 guint length, proto_tree *tree)
541 proto_tree_add_text(tree, offset, length, "MRU: %u", pntohs(opd));
545 dissect_lcp_async_map_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
546 guint length, proto_tree *tree)
548 proto_tree_add_text(tree, offset, length, "Async characters to map: 0x%08x",
553 dissect_lcp_protocol_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
554 guint length, proto_tree *tree)
558 proto_tree *field_tree = NULL;
560 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
561 optp->name, length, plurality(length, "", "s"));
562 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
565 protocol = pntohs(opd);
566 proto_tree_add_text(field_tree, offset, 2, "%s: %s (0x%02x)", optp->name,
567 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
572 proto_tree_add_text(field_tree, offset, length, "Data (%d byte%s)", length,
573 plurality(length, "", "s"));
577 dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp, const u_char *opd,
578 int offset, guint length, proto_tree *tree)
580 proto_tree_add_text(tree, offset, length, "Magic number: 0x%08x",
585 dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp, const u_char *opd,
586 int offset, guint length, proto_tree *tree)
589 proto_tree *field_tree = NULL;
593 tf = proto_tree_add_text(tree, offset, length, "%s: 0x%02x",
594 optp->name, alternatives);
595 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
597 if (alternatives & 0x1)
598 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
599 decode_boolean_bitfield(alternatives, 0x1, 8, "Null FCS", NULL));
600 if (alternatives & 0x2)
601 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
602 decode_boolean_bitfield(alternatives, 0x2, 8, "CCITT 16-bit FCS", NULL));
603 if (alternatives & 0x4)
604 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
605 decode_boolean_bitfield(alternatives, 0x4, 8, "CCITT 32-bit FCS", NULL));
609 dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp, const u_char *opd,
610 int offset, guint length, proto_tree *tree)
612 proto_tree_add_text(tree, offset, length,
613 "Maximum octets of self-describing padding: %u",
618 dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp, const u_char *opd,
619 int offset, guint length, proto_tree *tree)
622 proto_tree *field_tree = NULL;
624 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
625 optp->name, length, plurality(length, "", "s"));
626 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
629 proto_tree_add_text(field_tree, offset, 1, "Window: %u", *opd);
634 proto_tree_add_text(field_tree, offset, length, "Address (%d byte%s)",
635 length, plurality(length, "", "s"));
638 static const value_string callback_op_vals[] = {
639 {0, "Location is determined by user authentication" },
640 {1, "Message is dialing string" },
641 {2, "Message is location identifier" },
642 {3, "Message is E.164" },
643 {4, "Message is distinguished name" },
648 dissect_lcp_callback_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
649 guint length, proto_tree *tree)
652 proto_tree *field_tree = NULL;
654 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
655 optp->name, length, plurality(length, "", "s"));
656 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
659 proto_tree_add_text(field_tree, offset, 1, "Operation: %s (0x%02x)",
660 val_to_str(*opd, callback_op_vals, "Unknown"),
666 proto_tree_add_text(field_tree, offset, length, "Message (%d byte%s)",
667 length, plurality(length, "", "s"));
671 dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp, const u_char *opd,
672 int offset, guint length, proto_tree *tree)
674 proto_tree_add_text(tree, offset, length, "Multilink MRRU: %u",
679 #define CLASS_LOCAL 1
681 #define CLASS_IEEE_802_1 3
682 #define CLASS_PPP_MAGIC_NUMBER 4
683 #define CLASS_PSDN_DIRECTORY_NUMBER 5
685 static const value_string multilink_ep_disc_class_vals[] = {
686 {CLASS_NULL, "Null" },
687 {CLASS_LOCAL, "Locally assigned address" },
688 {CLASS_IP, "IP address" },
689 {CLASS_IEEE_802_1, "IEEE 802.1 globally assigned MAC address" },
690 {CLASS_PPP_MAGIC_NUMBER, "PPP magic-number block" },
691 {CLASS_PSDN_DIRECTORY_NUMBER, "Public switched network directory number" },
696 dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp, const u_char *opd,
697 int offset, guint length, proto_tree *tree)
700 proto_tree *field_tree = NULL;
701 guint8 ep_disc_class;
703 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
704 optp->name, length, plurality(length, "", "s"));
705 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
708 ep_disc_class = *opd;
709 proto_tree_add_text(field_tree, offset, 1, "Class: %s (%u)",
710 val_to_str(ep_disc_class, multilink_ep_disc_class_vals, "Unknown"),
716 switch (ep_disc_class) {
719 proto_tree_add_text(field_tree, offset, length,
720 "Address (%d byte%s), should have been empty",
721 length, plurality(length, "", "s"));
726 proto_tree_add_text(field_tree, offset, length,
727 "Address (%d byte%s), should have been <20",
728 length, plurality(length, "", "s"));
730 proto_tree_add_text(field_tree, offset, length,
731 "Address (%d byte%s)",
732 length, plurality(length, "", "s"));
738 proto_tree_add_text(field_tree, offset, length,
739 "Address (%d byte%s), should have been 4",
740 length, plurality(length, "", "s"));
742 proto_tree_add_text(field_tree, offset, length,
743 "Address: %s", ip_to_str(opd));
747 case CLASS_IEEE_802_1:
749 proto_tree_add_text(field_tree, offset, length,
750 "Address (%d byte%s), should have been 6",
751 length, plurality(length, "", "s"));
753 proto_tree_add_text(field_tree, offset, length,
754 "Address: %s", ether_to_str(opd));
758 case CLASS_PPP_MAGIC_NUMBER:
759 /* XXX - dissect as 32-bit magic numbers */
761 proto_tree_add_text(field_tree, offset, length,
762 "Address (%d byte%s), should have been <20",
763 length, plurality(length, "", "s"));
765 proto_tree_add_text(field_tree, offset, length,
766 "Address (%d byte%s)",
767 length, plurality(length, "", "s"));
771 case CLASS_PSDN_DIRECTORY_NUMBER:
773 proto_tree_add_text(field_tree, offset, length,
774 "Address (%d byte%s), should have been <20",
775 length, plurality(length, "", "s"));
777 proto_tree_add_text(field_tree, offset, length,
778 "Address (%d byte%s)",
779 length, plurality(length, "", "s"));
784 proto_tree_add_text(field_tree, offset, length,
785 "Address (%d byte%s)",
786 length, plurality(length, "", "s"));
793 dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp, const u_char *opd,
794 int offset, guint length, proto_tree *tree)
796 proto_tree_add_text(tree, offset, length,
797 "Link discriminator for BAP: 0x%04x",
801 /* Character set numbers from the IANA charset registry. */
802 static const value_string charset_num_vals[] = {
808 dissect_lcp_internationalization_opt(const ip_tcp_opt *optp, const u_char *opd,
809 int offset, guint length, proto_tree *tree)
812 proto_tree *field_tree = NULL;
814 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
815 optp->name, length, plurality(length, "", "s"));
816 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
819 proto_tree_add_text(field_tree, offset, 4, "Character set: %s (0x%04x)",
820 val_to_str(pntohl(opd), charset_num_vals, "Unknown"),
826 /* XXX - should be displayed as an ASCII string */
827 proto_tree_add_text(field_tree, offset, length, "Language tag (%d byte%s)",
828 length, plurality(length, "", "s"));
833 dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, const u_char *opd,
834 int offset, guint length, proto_tree *tree)
837 proto_tree *field_tree = NULL;
839 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
840 optp->name, length, plurality(length, "", "s"));
841 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
844 proto_tree_add_text(field_tree, offset, 4,
845 "Source IP address: %s", ip_to_str(opd));
849 proto_tree_add_text(field_tree, offset, 4,
850 "Destination IP address: %s", ip_to_str(opd));
853 static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, const u_char *opd,
854 int offset, guint length, proto_tree *tree)
856 proto_tree_add_text(tree, offset, length, "%s: %s", optp->name,
857 ip_to_str((guint8 *)opd));
861 dissect_cp( const u_char *pd, int offset, const char *proto_short_name,
862 const char *proto_long_name, int proto_subtree_index,
863 const value_string *proto_vals, int options_subtree_index,
864 const ip_tcp_opt *opts, int nopts, frame_data *fd, proto_tree *tree ) {
866 proto_tree *fh_tree = NULL;
868 proto_tree *field_tree;
877 length = pntohs(&pd[2+offset]);
879 if(check_col(fd, COL_INFO))
880 col_add_fstr(fd, COL_INFO, "%sCP %s", proto_short_name,
881 val_to_str(code, proto_vals, "Unknown"));
884 ti = proto_tree_add_text(tree, 0+offset, 4, "%s Control Protocol",
886 fh_tree = proto_item_add_subtree(ti, proto_subtree_index);
887 proto_tree_add_text(fh_tree, 0+offset, 1, "Code: %s (0x%02x)",
888 val_to_str(code, proto_vals, "Unknown"), code);
889 proto_tree_add_text(fh_tree, 1+offset, 1, "Identifier: 0x%02x",
891 proto_tree_add_text(fh_tree, 2+offset, 2, "Length: %u",
904 tf = proto_tree_add_text(fh_tree, offset, length,
905 "Options: (%d byte%s)", length, plurality(length, "", "s"));
906 field_tree = proto_item_add_subtree(tf, options_subtree_index);
907 dissect_ip_tcp_options(&pd[offset], offset, length, opts, nopts,
918 proto_tree_add_text(fh_tree, offset, 4, "Magic number: 0x%08x",
919 pntohl(&pd[offset]));
923 proto_tree_add_text(fh_tree, offset, length, "Message (%d byte%s)",
924 length, plurality(length, "", "s"));
930 proto_tree_add_text(fh_tree, offset, 4, "Magic number: 0x%08x",
931 pntohl(&pd[offset]));
934 proto_tree_add_text(fh_tree, offset, 4, "Seconds remaining: %u",
935 pntohl(&pd[offset]));
939 proto_tree_add_text(fh_tree, offset, length, "Message (%d byte%s)",
940 length, plurality(length, "", "s"));
946 protocol = pntohs(&pd[offset]);
947 proto_tree_add_text(fh_tree, offset, 2, "Rejected protocol: %s (0x%04x)",
948 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
952 proto_tree_add_text(fh_tree, offset, length, "Rejected packet (%d byte%s)",
953 length, plurality(length, "", "s"));
954 /* XXX - should be dissected as a PPP packet */
959 /* decode the rejected LCP packet here. */
961 proto_tree_add_text(fh_tree, offset, length, "Rejected packet (%d byte%s)",
962 length, plurality(length, "", "s"));
968 proto_tree_add_text(fh_tree, offset, length, "Data (%d byte%s)",
969 length, plurality(length, "", "s"));
974 proto_tree_add_text(fh_tree, offset, length, "Stuff (%d byte%s)",
975 length, plurality(length, "", "s"));
980 /* Protocol field compression */
984 dissect_ppp_stuff( const u_char *pd, int offset, frame_data *fd,
985 proto_tree *tree, proto_tree *fh_tree ) {
989 if (pd[offset] & PFC_BIT) {
990 ppp_prot = pd[offset];
993 ppp_prot = pntohs(&pd[offset]);
998 proto_tree_add_text(fh_tree, offset, proto_len, "Protocol: %s (0x%04x)",
999 val_to_str(ppp_prot, ppp_vals, "Unknown"), ppp_prot);
1001 offset += proto_len;
1005 dissect_ip(pd, offset, fd, tree);
1008 dissect_ddp(pd, offset, fd, tree);
1011 dissect_ipx(pd, offset, fd, tree);
1014 dissect_vines(pd, offset, fd, tree);
1017 dissect_mp(pd, offset, fd, tree, fh_tree);
1020 dissect_ipv6(pd, offset, fd, tree);
1023 dissect_cp(pd, offset, "L", "Link", ett_lcp, lcp_vals, ett_lcp_options,
1024 lcp_opts, N_LCP_OPTS, fd, tree);
1027 dissect_cp(pd, offset, "IP", "IP", ett_ipcp, cp_vals, ett_ipcp_options,
1028 ipcp_opts, N_IPCP_OPTS, fd, tree);
1031 if (check_col(fd, COL_INFO))
1032 col_add_fstr(fd, COL_INFO, "PPP %s (0x%04x)",
1033 val_to_str(ppp_prot, ppp_vals, "Unknown"), ppp_prot);
1034 dissect_data(pd, offset, fd, tree);
1039 #define MP_FRAG_MASK 0xC0
1040 #define MP_FRAG(bits) ((bits) & MP_FRAG_MASK)
1041 #define MP_FRAG_FIRST 0x80
1042 #define MP_FRAG_LAST 0x40
1043 #define MP_FRAG_RESERVED 0x3f
1045 /* According to RFC 1717, the length the MP header isn't indicated anywhere
1046 in the header itself. It starts out at four bytes and can be
1047 negotiated down to two using LCP. We currently assume that all
1048 headers are four bytes. - gcc
1051 dissect_mp(const u_char *pd, int offset, frame_data *fd,
1052 proto_tree *tree, proto_tree *fh_tree)
1054 proto_tree *ti, *mp_tree, *hdr_tree;
1061 first = flags && MP_FRAG_FIRST;
1062 last = flags && MP_FRAG_LAST;
1063 memcpy(&seq, &pd[offset + 1], 3);
1065 if (check_col(fd, COL_INFO))
1066 col_add_fstr(fd, COL_INFO, "PPP Multilink");
1071 strcpy(flag_str, "First");
1074 strcpy(flag_str, "Last");
1076 case MP_FRAG_FIRST|MP_FRAG_LAST:
1077 strcpy(flag_str, "First, Last");
1080 strcpy(flag_str, "Unknown");
1083 ti = proto_tree_add_item(tree, proto_mp, offset, 4, NULL);
1084 mp_tree = proto_item_add_subtree(ti, ett_mp);
1085 ti = proto_tree_add_text(mp_tree, offset, 1, "Fragment: 0x%2X (%s)",
1087 hdr_tree = proto_item_add_subtree(ti, ett_mp_flags);
1088 proto_tree_add_item_format(hdr_tree, hf_mp_frag_first, offset, 1, first,
1089 "%s", decode_boolean_bitfield(flags, MP_FRAG_FIRST, sizeof(flags) * 8,
1090 "first", "not first"));
1091 proto_tree_add_item_format(hdr_tree, hf_mp_frag_last, offset, 1, last,
1092 "%s", decode_boolean_bitfield(flags, MP_FRAG_LAST, sizeof(flags) * 8,
1093 "last", "not last"));
1094 proto_tree_add_text(hdr_tree, offset, 1, "%s",
1095 decode_boolean_bitfield(flags, MP_FRAG_RESERVED, sizeof(flags) * 8,
1096 "reserved", "reserved"));
1097 proto_tree_add_item_format(mp_tree, hf_mp_sequence_num,
1098 offset + 1, 3, seq, "Sequence: %lu", seq);
1103 if (fd->cap_len > offset) {
1105 ti = proto_tree_add_item(tree, proto_ppp, offset, 1, NULL);
1106 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1108 dissect_ppp_stuff(pd, offset, fd, tree, fh_tree);
1113 dissect_payload_ppp( const u_char *pd, int offset, frame_data *fd, proto_tree *tree ) {
1115 proto_tree *fh_tree = NULL;
1117 /* populate a tree in the second pane with the status of the link
1120 ti = proto_tree_add_item(tree, proto_ppp, 0+offset, 2, NULL);
1121 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1124 dissect_ppp_stuff(pd, offset, fd, tree, fh_tree);
1128 dissect_ppp( const u_char *pd, frame_data *fd, proto_tree *tree ) {
1131 proto_tree *fh_tree = NULL;
1133 ph.ppp_addr = pd[0];
1135 ph.ppp_prot = pntohs(&pd[2]);
1137 /* load the top pane info. This should be overwritten by
1138 the next protocol in the stack */
1140 if(check_col(fd, COL_RES_DL_SRC))
1141 col_add_str(fd, COL_RES_DL_SRC, "N/A" );
1142 if(check_col(fd, COL_RES_DL_DST))
1143 col_add_str(fd, COL_RES_DL_DST, "N/A" );
1144 if(check_col(fd, COL_PROTOCOL))
1145 col_add_str(fd, COL_PROTOCOL, "PPP" );
1147 /* populate a tree in the second pane with the status of the link
1150 ti = proto_tree_add_item(tree, proto_ppp, 0, 4, NULL);
1151 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1152 proto_tree_add_text(fh_tree, 0, 1, "Address: %02x", ph.ppp_addr);
1153 proto_tree_add_text(fh_tree, 1, 1, "Control: %02x", ph.ppp_ctl);
1156 if (!dissect_ppp_stuff(pd, 2, fd, tree, fh_tree)) {
1157 if (check_col(fd, COL_PROTOCOL))
1158 col_add_fstr(fd, COL_PROTOCOL, "0x%04x", ph.ppp_prot);
1163 proto_register_ppp(void)
1165 /* static hf_register_info hf[] = {
1167 { "Name", "ppp.abbreviation", TYPE, VALS_POINTER }},
1169 static gint *ett[] = {
1173 &ett_ipcp_ipaddrs_opt,
1174 &ett_ipcp_compressprot_opt,
1178 &ett_lcp_async_map_opt,
1179 &ett_lcp_authprot_opt,
1180 &ett_lcp_qualprot_opt,
1181 &ett_lcp_magicnum_opt,
1182 &ett_lcp_fcs_alternatives_opt,
1183 &ett_lcp_numbered_mode_opt,
1184 &ett_lcp_callback_opt,
1185 &ett_lcp_multilink_ep_disc_opt,
1186 &ett_lcp_internationalization_opt,
1189 proto_ppp = proto_register_protocol("Point-to-Point Protocol", "ppp");
1190 /* proto_register_field_array(proto_ppp, hf, array_length(hf));*/
1191 proto_register_subtree_array(ett, array_length(ett));
1195 proto_register_mp(void)
1197 static hf_register_info hf[] = {
1198 { &hf_mp_frag_first,
1199 { "First fragment", "mp.first", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1203 { "Last fragment", "mp.last", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1206 { &hf_mp_sequence_num,
1207 { "Sequence number", "mp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
1210 static gint *ett[] = {
1215 proto_mp = proto_register_protocol("PPP Multilink Protocol", "mp");
1216 proto_register_field_array(proto_mp, hf, array_length(hf));
1217 proto_register_subtree_array(ett, array_length(ett));