2 * Routines for ppp packet disassembly
4 * $Id: packet-ppp.c,v 1.28 2000/02/15 21:02:51 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-atalk.h"
38 #include "packet-ip.h"
39 #include "packet-ipv6.h"
40 #include "packet-ipx.h"
41 #include "packet-vines.h"
43 static int proto_ppp = -1;
45 static gint ett_ppp = -1;
46 static gint ett_ipcp = -1;
47 static gint ett_ipcp_options = -1;
48 static gint ett_ipcp_ipaddrs_opt = -1;
49 static gint ett_ipcp_compressprot_opt = -1;
50 static gint ett_lcp = -1;
51 static gint ett_lcp_options = -1;
52 static gint ett_lcp_mru_opt = -1;
53 static gint ett_lcp_async_map_opt = -1;
54 static gint ett_lcp_authprot_opt = -1;
55 static gint ett_lcp_qualprot_opt = -1;
56 static gint ett_lcp_magicnum_opt = -1;
57 static gint ett_lcp_fcs_alternatives_opt = -1;
58 static gint ett_lcp_numbered_mode_opt = -1;
59 static gint ett_lcp_callback_opt = -1;
60 static gint ett_lcp_multilink_ep_disc_opt = -1;
61 static gint ett_lcp_internationalization_opt = -1;
63 static int proto_mp = -1;
64 static int hf_mp_frag_first = -1;
65 static int hf_mp_frag_last = -1;
66 static int hf_mp_sequence_num = -1;
68 static int ett_mp = -1;
69 static int ett_mp_flags = -1;
71 /* PPP structs and definitions */
73 typedef struct _e_ppphdr {
80 /* Protocol types, from Linux "ppp_defs.h" and
82 http://www.isi.edu/in-notes/iana/assignments/ppp-numbers
85 #define PPP_IP 0x21 /* Internet Protocol */
86 #define PPP_AT 0x29 /* AppleTalk Protocol */
87 #define PPP_IPX 0x2b /* IPX protocol */
88 #define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
89 #define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
90 #define PPP_VINES 0x35 /* Banyan Vines */
91 #define PPP_MP 0x3d /* Multilink PPP */
92 #define PPP_IPV6 0x57 /* Internet Protocol Version 6 */
93 #define PPP_COMP 0xfd /* compressed packet */
94 #define PPP_IPCP 0x8021 /* IP Control Protocol */
95 #define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
96 #define PPP_IPXCP 0x802b /* IPX Control Protocol */
97 #define PPP_CCP 0x80fd /* Compression Control Protocol */
98 #define PPP_LCP 0xc021 /* Link Control Protocol */
99 #define PPP_PAP 0xc023 /* Password Authentication Protocol */
100 #define PPP_LQR 0xc025 /* Link Quality Report protocol */
101 #define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
102 #define PPP_CBCP 0xc029 /* Callback Control Protocol */
104 static const value_string ppp_vals[] = {
106 {PPP_AT, "Appletalk" },
107 {PPP_IPX, "Netware IPX/SPX"},
108 {PPP_VJC_COMP, "VJ compressed TCP"},
109 {PPP_VJC_UNCOMP,"VJ uncompressed TCP"},
110 {PPP_VINES, "Vines" },
111 {PPP_MP, "Multilink"},
113 {PPP_COMP, "compressed packet" },
114 {PPP_IPCP, "IP Control Protocol" },
115 {PPP_ATCP, "AppleTalk Control Protocol" },
116 {PPP_IPXCP, "IPX Control Protocol" },
117 {PPP_CCP, "Compression Control Protocol" },
118 {PPP_LCP, "Link Control Protocol" },
119 {PPP_PAP, "Password Authentication Protocol" },
120 {PPP_LQR, "Link Quality Report protocol" },
121 {PPP_CHAP, "Cryptographic Handshake Auth. Protocol" },
122 {PPP_CBCP, "Callback Control Protocol" },
126 /* CP (LCP, IPCP, etc.) codes.
129 #define CONFREQ 1 /* Configuration Request */
130 #define CONFACK 2 /* Configuration Ack */
131 #define CONFNAK 3 /* Configuration Nak */
132 #define CONFREJ 4 /* Configuration Reject */
133 #define TERMREQ 5 /* Termination Request */
134 #define TERMACK 6 /* Termination Ack */
135 #define CODEREJ 7 /* Code Reject */
137 static const value_string cp_vals[] = {
138 {CONFREQ, "Configuration Request" },
139 {CONFACK, "Configuration Ack" },
140 {CONFNAK, "Configuration Nak" },
141 {CONFREJ, "Configuration Reject" },
142 {TERMREQ, "Termination Request" },
143 {TERMACK, "Termination Ack" },
144 {CODEREJ, "Code Reject" },
148 * LCP-specific packet types.
150 #define PROTREJ 8 /* Protocol Reject */
151 #define ECHOREQ 9 /* Echo Request */
152 #define ECHOREP 10 /* Echo Reply */
153 #define DISCREQ 11 /* Discard Request */
154 #define IDENT 12 /* Identification */
155 #define TIMEREMAIN 13 /* Time remaining */
157 #define CBCP_OPT 6 /* Use callback control protocol */
159 static const value_string lcp_vals[] = {
160 {CONFREQ, "Configuration Request" },
161 {CONFACK, "Configuration Ack" },
162 {CONFNAK, "Configuration Nak" },
163 {CONFREJ, "Configuration Reject" },
164 {TERMREQ, "Termination Request" },
165 {TERMACK, "Termination Ack" },
166 {CODEREJ, "Code Reject" },
167 {PROTREJ, "Protocol Reject" },
168 {ECHOREQ, "Echo Request" },
169 {ECHOREP, "Echo Reply" },
170 {DISCREQ, "Discard Request" },
171 {IDENT, "Identification" },
172 {TIMEREMAIN, "Time Remaining" },
179 #define CI_MRU 1 /* Maximum Receive Unit */
180 #define CI_ASYNCMAP 2 /* Async Control Character Map */
181 #define CI_AUTHTYPE 3 /* Authentication Type */
182 #define CI_QUALITY 4 /* Quality Protocol */
183 #define CI_MAGICNUMBER 5 /* Magic Number */
184 #define CI_PCOMPRESSION 7 /* Protocol Field Compression */
185 #define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
186 #define CI_FCS_ALTERNATIVES 9 /* FCS Alternatives (RFC 1570) */
187 #define CI_SELF_DESCRIBING_PAD 10 /* Self-Describing Pad (RFC 1570) */
188 #define CI_NUMBERED_MODE 11 /* Numbered Mode (RFC 1663) */
189 #define CI_CALLBACK 13 /* Callback (RFC 1570) */
190 #define CI_COMPOUND_FRAMES 15 /* Compound frames (RFC 1570) */
191 #define CI_MULTILINK_MRRU 17 /* Multilink MRRU (RFC 1717) */
192 #define CI_MULTILINK_SSNH 18 /* Multilink Short Sequence Number
194 #define CI_MULTILINK_EP_DISC 19 /* Multilink Endpoint Discriminator
196 #define CI_DCE_IDENTIFIER 21 /* DCE Identifier */
197 #define CI_MULTILINK_PLUS_PROC 22 /* Multilink Plus Procedure */
198 #define CI_LINK_DISC_FOR_BACP 23 /* Link Discriminator for BACP
200 #define CI_LCP_AUTHENTICATION 24 /* LCP Authentication Option */
201 #define CI_COBS 25 /* Consistent Overhead Byte
203 #define CI_PREFIX_ELISION 26 /* Prefix elision */
204 #define CI_MULTILINK_HDR_FMT 27 /* Multilink header format */
205 #define CI_INTERNATIONALIZATION 28 /* Internationalization (RFC 2484) */
206 #define CI_SDL_ON_SONET_SDH 29 /* Simple Data Link on SONET/SDH */
208 static void dissect_lcp_mru_opt(const ip_tcp_opt *optp, const u_char *opd,
209 int offset, guint length, proto_tree *tree);
210 static void dissect_lcp_async_map_opt(const ip_tcp_opt *optp, const u_char *opd,
211 int offset, guint length, proto_tree *tree);
212 static void dissect_lcp_protocol_opt(const ip_tcp_opt *optp, const u_char *opd,
213 int offset, guint length, proto_tree *tree);
214 static void dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp,
215 const u_char *opd, int offset, guint length,
217 static void dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp,
218 const u_char *opd, int offset, guint length,
220 static void dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp,
221 const u_char *opd, int offset, guint length,
223 static void dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp,
224 const u_char *opd, int offset, guint length,
226 static void dissect_lcp_callback_opt(const ip_tcp_opt *optp, const u_char *opd,
227 int offset, guint length, proto_tree *tree);
228 static void dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp,
229 const u_char *opd, int offset, guint length,
231 static void dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp,
232 const u_char *opd, int offset, guint length,
234 static void dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp,
235 const u_char *opd, int offset, guint length,
237 static void dissect_lcp_internationalization_opt(const ip_tcp_opt *optp,
238 const u_char *opd, int offset, guint length,
240 static void dissect_mp(const u_char *pd, int offset, frame_data *fd,
241 proto_tree *tree, proto_tree *fh_tree);
243 static const ip_tcp_opt lcp_opts[] = {
246 "Maximum Receive Unit",
254 "Async Control Character Map",
255 &ett_lcp_async_map_opt,
258 dissect_lcp_async_map_opt
262 "Authentication protocol",
263 &ett_lcp_authprot_opt,
266 dissect_lcp_protocol_opt
271 &ett_lcp_qualprot_opt,
274 dissect_lcp_protocol_opt
279 &ett_lcp_magicnum_opt,
282 dissect_lcp_magicnumber_opt
286 "Protocol field compression",
294 "Address/control field compression",
303 &ett_lcp_fcs_alternatives_opt,
306 dissect_lcp_fcs_alternatives_opt
309 CI_SELF_DESCRIBING_PAD,
314 dissect_lcp_self_describing_pad_opt
319 &ett_lcp_numbered_mode_opt,
322 dissect_lcp_numbered_mode_opt
327 &ett_lcp_callback_opt,
330 dissect_lcp_callback_opt,
346 dissect_lcp_multilink_mrru_opt
350 "Use short sequence number headers",
357 CI_MULTILINK_EP_DISC,
358 "Multilink endpoint discriminator",
359 &ett_lcp_multilink_ep_disc_opt,
362 dissect_lcp_multilink_ep_disc_opt,
373 CI_MULTILINK_PLUS_PROC,
374 "Multilink Plus Procedure",
381 CI_LINK_DISC_FOR_BACP,
386 dissect_lcp_bap_link_discriminator_opt
389 CI_LCP_AUTHENTICATION,
390 "LCP authentication",
398 "Consistent Overhead Byte Stuffing",
413 CI_MULTILINK_HDR_FMT,
414 "Multilink header format",
421 CI_INTERNATIONALIZATION,
422 "Internationalization",
423 &ett_lcp_internationalization_opt,
426 dissect_lcp_internationalization_opt
430 "Simple data link on SONET/SDH",
438 #define N_LCP_OPTS (sizeof lcp_opts / sizeof lcp_opts[0])
443 #define CI_ADDRS 1 /* IP Addresses (deprecated) (RFC 1172) */
444 #define CI_COMPRESSTYPE 2 /* Compression Type (RFC 1332) */
445 #define CI_ADDR 3 /* IP Address (RFC 1332) */
446 #define CI_MOBILE_IPv4 4 /* Mobile IPv4 (RFC 2290) */
447 #define CI_MS_DNS1 129 /* Primary DNS value (RFC 1877) */
448 #define CI_MS_WINS1 130 /* Primary WINS value (RFC 1877) */
449 #define CI_MS_DNS2 131 /* Secondary DNS value (RFC 1877) */
450 #define CI_MS_WINS2 132 /* Secondary WINS value (RFC 1877) */
452 static void dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, const u_char *opd,
453 int offset, guint length, proto_tree *tree);
454 static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, const u_char *opd,
455 int offset, guint length, proto_tree *tree);
457 static const ip_tcp_opt ipcp_opts[] = {
460 "IP addresses (deprecated)",
461 &ett_ipcp_ipaddrs_opt,
464 dissect_ipcp_addrs_opt
468 "IP compression protocol",
469 &ett_ipcp_compressprot_opt,
472 dissect_lcp_protocol_opt
480 dissect_ipcp_addr_opt
484 "Mobile node's home IP address",
488 dissect_ipcp_addr_opt
492 "Primary DNS server IP address",
496 dissect_ipcp_addr_opt
500 "Primary WINS server IP address",
504 dissect_ipcp_addr_opt
508 "Secondary DNS server IP address",
512 dissect_ipcp_addr_opt
516 "Secondary WINS server IP address",
520 dissect_ipcp_addr_opt
524 #define N_IPCP_OPTS (sizeof ipcp_opts / sizeof ipcp_opts[0])
527 capture_ppp( const u_char *pd, packet_counts *ld ) {
528 switch (pntohs(&pd[2])) {
530 capture_ip(pd, 4, ld);
533 capture_ipx(pd, 4, ld);
536 capture_ipx(pd, 4, ld);
545 dissect_lcp_mru_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, "MRU: %u", pntohs(opd));
552 dissect_lcp_async_map_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
553 guint length, proto_tree *tree)
555 proto_tree_add_text(tree, offset, length, "Async characters to map: 0x%08x",
560 dissect_lcp_protocol_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
561 guint length, proto_tree *tree)
565 proto_tree *field_tree = NULL;
567 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
568 optp->name, length, plurality(length, "", "s"));
569 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
572 protocol = pntohs(opd);
573 proto_tree_add_text(field_tree, offset, 2, "%s: %s (0x%02x)", optp->name,
574 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
579 proto_tree_add_text(field_tree, offset, length, "Data (%d byte%s)", length,
580 plurality(length, "", "s"));
584 dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp, const u_char *opd,
585 int offset, guint length, proto_tree *tree)
587 proto_tree_add_text(tree, offset, length, "Magic number: 0x%08x",
592 dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp, const u_char *opd,
593 int offset, guint length, proto_tree *tree)
596 proto_tree *field_tree = NULL;
600 tf = proto_tree_add_text(tree, offset, length, "%s: 0x%02x",
601 optp->name, alternatives);
602 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
604 if (alternatives & 0x1)
605 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
606 decode_boolean_bitfield(alternatives, 0x1, 8, "Null FCS", NULL));
607 if (alternatives & 0x2)
608 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
609 decode_boolean_bitfield(alternatives, 0x2, 8, "CCITT 16-bit FCS", NULL));
610 if (alternatives & 0x4)
611 proto_tree_add_text(field_tree, offset + 2, 1, "%s",
612 decode_boolean_bitfield(alternatives, 0x4, 8, "CCITT 32-bit FCS", NULL));
616 dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp, const u_char *opd,
617 int offset, guint length, proto_tree *tree)
619 proto_tree_add_text(tree, offset, length,
620 "Maximum octets of self-describing padding: %u",
625 dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp, const u_char *opd,
626 int offset, guint length, proto_tree *tree)
629 proto_tree *field_tree = NULL;
631 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
632 optp->name, length, plurality(length, "", "s"));
633 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
636 proto_tree_add_text(field_tree, offset, 1, "Window: %u", *opd);
641 proto_tree_add_text(field_tree, offset, length, "Address (%d byte%s)",
642 length, plurality(length, "", "s"));
645 static const value_string callback_op_vals[] = {
646 {0, "Location is determined by user authentication" },
647 {1, "Message is dialing string" },
648 {2, "Message is location identifier" },
649 {3, "Message is E.164" },
650 {4, "Message is distinguished name" },
655 dissect_lcp_callback_opt(const ip_tcp_opt *optp, const u_char *opd, int offset,
656 guint length, proto_tree *tree)
659 proto_tree *field_tree = NULL;
661 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
662 optp->name, length, plurality(length, "", "s"));
663 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
666 proto_tree_add_text(field_tree, offset, 1, "Operation: %s (0x%02x)",
667 val_to_str(*opd, callback_op_vals, "Unknown"),
673 proto_tree_add_text(field_tree, offset, length, "Message (%d byte%s)",
674 length, plurality(length, "", "s"));
678 dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp, const u_char *opd,
679 int offset, guint length, proto_tree *tree)
681 proto_tree_add_text(tree, offset, length, "Multilink MRRU: %u",
686 #define CLASS_LOCAL 1
688 #define CLASS_IEEE_802_1 3
689 #define CLASS_PPP_MAGIC_NUMBER 4
690 #define CLASS_PSDN_DIRECTORY_NUMBER 5
692 static const value_string multilink_ep_disc_class_vals[] = {
693 {CLASS_NULL, "Null" },
694 {CLASS_LOCAL, "Locally assigned address" },
695 {CLASS_IP, "IP address" },
696 {CLASS_IEEE_802_1, "IEEE 802.1 globally assigned MAC address" },
697 {CLASS_PPP_MAGIC_NUMBER, "PPP magic-number block" },
698 {CLASS_PSDN_DIRECTORY_NUMBER, "Public switched network directory number" },
703 dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp, const u_char *opd,
704 int offset, guint length, proto_tree *tree)
707 proto_tree *field_tree = NULL;
708 guint8 ep_disc_class;
710 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
711 optp->name, length, plurality(length, "", "s"));
712 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
715 ep_disc_class = *opd;
716 proto_tree_add_text(field_tree, offset, 1, "Class: %s (%u)",
717 val_to_str(ep_disc_class, multilink_ep_disc_class_vals, "Unknown"),
723 switch (ep_disc_class) {
726 proto_tree_add_text(field_tree, offset, length,
727 "Address (%d byte%s), should have been empty",
728 length, plurality(length, "", "s"));
733 proto_tree_add_text(field_tree, offset, length,
734 "Address (%d byte%s), should have been <20",
735 length, plurality(length, "", "s"));
737 proto_tree_add_text(field_tree, offset, length,
738 "Address (%d byte%s)",
739 length, plurality(length, "", "s"));
745 proto_tree_add_text(field_tree, offset, length,
746 "Address (%d byte%s), should have been 4",
747 length, plurality(length, "", "s"));
749 proto_tree_add_text(field_tree, offset, length,
750 "Address: %s", ip_to_str(opd));
754 case CLASS_IEEE_802_1:
756 proto_tree_add_text(field_tree, offset, length,
757 "Address (%d byte%s), should have been 6",
758 length, plurality(length, "", "s"));
760 proto_tree_add_text(field_tree, offset, length,
761 "Address: %s", ether_to_str(opd));
765 case CLASS_PPP_MAGIC_NUMBER:
766 /* XXX - dissect as 32-bit magic numbers */
768 proto_tree_add_text(field_tree, offset, length,
769 "Address (%d byte%s), should have been <20",
770 length, plurality(length, "", "s"));
772 proto_tree_add_text(field_tree, offset, length,
773 "Address (%d byte%s)",
774 length, plurality(length, "", "s"));
778 case CLASS_PSDN_DIRECTORY_NUMBER:
780 proto_tree_add_text(field_tree, offset, length,
781 "Address (%d byte%s), should have been <20",
782 length, plurality(length, "", "s"));
784 proto_tree_add_text(field_tree, offset, length,
785 "Address (%d byte%s)",
786 length, plurality(length, "", "s"));
791 proto_tree_add_text(field_tree, offset, length,
792 "Address (%d byte%s)",
793 length, plurality(length, "", "s"));
800 dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp, const u_char *opd,
801 int offset, guint length, proto_tree *tree)
803 proto_tree_add_text(tree, offset, length,
804 "Link discriminator for BAP: 0x%04x",
808 /* Character set numbers from the IANA charset registry. */
809 static const value_string charset_num_vals[] = {
815 dissect_lcp_internationalization_opt(const ip_tcp_opt *optp, const u_char *opd,
816 int offset, guint length, proto_tree *tree)
819 proto_tree *field_tree = NULL;
821 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
822 optp->name, length, plurality(length, "", "s"));
823 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
826 proto_tree_add_text(field_tree, offset, 4, "Character set: %s (0x%04x)",
827 val_to_str(pntohl(opd), charset_num_vals, "Unknown"),
833 /* XXX - should be displayed as an ASCII string */
834 proto_tree_add_text(field_tree, offset, length, "Language tag (%d byte%s)",
835 length, plurality(length, "", "s"));
840 dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, const u_char *opd,
841 int offset, guint length, proto_tree *tree)
844 proto_tree *field_tree = NULL;
846 tf = proto_tree_add_text(tree, offset, length, "%s: %u byte%s",
847 optp->name, length, plurality(length, "", "s"));
848 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
851 proto_tree_add_text(field_tree, offset, 4,
852 "Source IP address: %s", ip_to_str(opd));
856 proto_tree_add_text(field_tree, offset, 4,
857 "Destination IP address: %s", ip_to_str(opd));
860 static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, const u_char *opd,
861 int offset, guint length, proto_tree *tree)
863 proto_tree_add_text(tree, offset, length, "%s: %s", optp->name,
864 ip_to_str((guint8 *)opd));
868 dissect_cp( const u_char *pd, int offset, const char *proto_short_name,
869 const char *proto_long_name, int proto_subtree_index,
870 const value_string *proto_vals, int options_subtree_index,
871 const ip_tcp_opt *opts, int nopts, frame_data *fd, proto_tree *tree ) {
873 proto_tree *fh_tree = NULL;
875 proto_tree *field_tree;
884 length = pntohs(&pd[2+offset]);
886 if(check_col(fd, COL_INFO))
887 col_add_fstr(fd, COL_INFO, "%sCP %s", proto_short_name,
888 val_to_str(code, proto_vals, "Unknown"));
891 ti = proto_tree_add_text(tree, 0+offset, 4, "%s Control Protocol",
893 fh_tree = proto_item_add_subtree(ti, proto_subtree_index);
894 proto_tree_add_text(fh_tree, 0+offset, 1, "Code: %s (0x%02x)",
895 val_to_str(code, proto_vals, "Unknown"), code);
896 proto_tree_add_text(fh_tree, 1+offset, 1, "Identifier: 0x%02x",
898 proto_tree_add_text(fh_tree, 2+offset, 2, "Length: %u",
911 tf = proto_tree_add_text(fh_tree, offset, length,
912 "Options: (%d byte%s)", length, plurality(length, "", "s"));
913 field_tree = proto_item_add_subtree(tf, options_subtree_index);
914 dissect_ip_tcp_options(&pd[offset], offset, length, opts, nopts,
925 proto_tree_add_text(fh_tree, offset, 4, "Magic number: 0x%08x",
926 pntohl(&pd[offset]));
930 proto_tree_add_text(fh_tree, offset, length, "Message (%d byte%s)",
931 length, plurality(length, "", "s"));
937 proto_tree_add_text(fh_tree, offset, 4, "Magic number: 0x%08x",
938 pntohl(&pd[offset]));
941 proto_tree_add_text(fh_tree, offset, 4, "Seconds remaining: %u",
942 pntohl(&pd[offset]));
946 proto_tree_add_text(fh_tree, offset, length, "Message (%d byte%s)",
947 length, plurality(length, "", "s"));
953 protocol = pntohs(&pd[offset]);
954 proto_tree_add_text(fh_tree, offset, 2, "Rejected protocol: %s (0x%04x)",
955 val_to_str(protocol, ppp_vals, "Unknown"), protocol);
959 proto_tree_add_text(fh_tree, offset, length, "Rejected packet (%d byte%s)",
960 length, plurality(length, "", "s"));
961 /* XXX - should be dissected as a PPP packet */
966 /* decode the rejected LCP packet here. */
968 proto_tree_add_text(fh_tree, offset, length, "Rejected packet (%d byte%s)",
969 length, plurality(length, "", "s"));
975 proto_tree_add_text(fh_tree, offset, length, "Data (%d byte%s)",
976 length, plurality(length, "", "s"));
981 proto_tree_add_text(fh_tree, offset, length, "Stuff (%d byte%s)",
982 length, plurality(length, "", "s"));
987 /* Protocol field compression */
991 dissect_ppp_stuff( const u_char *pd, int offset, frame_data *fd,
992 proto_tree *tree, proto_tree *fh_tree ) {
996 if (pd[offset] & PFC_BIT) {
997 ppp_prot = pd[offset];
1000 ppp_prot = pntohs(&pd[offset]);
1005 proto_tree_add_text(fh_tree, offset, proto_len, "Protocol: %s (0x%04x)",
1006 val_to_str(ppp_prot, ppp_vals, "Unknown"), ppp_prot);
1008 offset += proto_len;
1012 dissect_ip(pd, offset, fd, tree);
1015 dissect_ddp(pd, offset, fd, tree);
1018 dissect_ipx(pd, offset, fd, tree);
1021 dissect_vines(pd, offset, fd, tree);
1024 dissect_mp(pd, offset, fd, tree, fh_tree);
1027 dissect_ipv6(pd, offset, fd, tree);
1030 dissect_cp(pd, offset, "L", "Link", ett_lcp, lcp_vals, ett_lcp_options,
1031 lcp_opts, N_LCP_OPTS, fd, tree);
1034 dissect_cp(pd, offset, "IP", "IP", ett_ipcp, cp_vals, ett_ipcp_options,
1035 ipcp_opts, N_IPCP_OPTS, fd, tree);
1038 if (check_col(fd, COL_INFO))
1039 col_add_fstr(fd, COL_INFO, "PPP %s (0x%04x)",
1040 val_to_str(ppp_prot, ppp_vals, "Unknown"), ppp_prot);
1041 dissect_data(pd, offset, fd, tree);
1046 #define MP_FRAG_MASK 0xC0
1047 #define MP_FRAG(bits) ((bits) & MP_FRAG_MASK)
1048 #define MP_FRAG_FIRST 0x80
1049 #define MP_FRAG_LAST 0x40
1050 #define MP_FRAG_RESERVED 0x3f
1052 /* According to RFC 1717, the length the MP header isn't indicated anywhere
1053 in the header itself. It starts out at four bytes and can be
1054 negotiated down to two using LCP. We currently assume that all
1055 headers are four bytes. - gcc
1058 dissect_mp(const u_char *pd, int offset, frame_data *fd,
1059 proto_tree *tree, proto_tree *fh_tree)
1061 proto_tree *ti, *mp_tree, *hdr_tree;
1068 first = flags && MP_FRAG_FIRST;
1069 last = flags && MP_FRAG_LAST;
1070 seq = pd[offset+1] << 16 | pd[offset+2] << 8 | pd[offset+3];
1072 if (check_col(fd, COL_INFO))
1073 col_add_fstr(fd, COL_INFO, "PPP Multilink");
1078 strcpy(flag_str, "First");
1081 strcpy(flag_str, "Last");
1083 case MP_FRAG_FIRST|MP_FRAG_LAST:
1084 strcpy(flag_str, "First, Last");
1087 strcpy(flag_str, "Unknown");
1090 ti = proto_tree_add_item(tree, proto_mp, offset, 4, NULL);
1091 mp_tree = proto_item_add_subtree(ti, ett_mp);
1092 ti = proto_tree_add_text(mp_tree, offset, 1, "Fragment: 0x%2X (%s)",
1094 hdr_tree = proto_item_add_subtree(ti, ett_mp_flags);
1095 proto_tree_add_item_format(hdr_tree, hf_mp_frag_first, offset, 1, first,
1096 "%s", decode_boolean_bitfield(flags, MP_FRAG_FIRST, sizeof(flags) * 8,
1097 "first", "not first"));
1098 proto_tree_add_item_format(hdr_tree, hf_mp_frag_last, offset, 1, last,
1099 "%s", decode_boolean_bitfield(flags, MP_FRAG_LAST, sizeof(flags) * 8,
1100 "last", "not last"));
1101 proto_tree_add_text(hdr_tree, offset, 1, "%s",
1102 decode_boolean_bitfield(flags, MP_FRAG_RESERVED, sizeof(flags) * 8,
1103 "reserved", "reserved"));
1104 proto_tree_add_item(mp_tree, hf_mp_sequence_num, offset + 1, 3, seq);
1109 if (IS_DATA_IN_FRAME(offset)) {
1111 ti = proto_tree_add_item(tree, proto_ppp, offset, 1, NULL);
1112 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1114 dissect_ppp_stuff(pd, offset, fd, tree, fh_tree);
1119 dissect_payload_ppp( const u_char *pd, int offset, frame_data *fd, proto_tree *tree ) {
1121 proto_tree *fh_tree = NULL;
1123 /* populate a tree in the second pane with the status of the link
1126 ti = proto_tree_add_item(tree, proto_ppp, 0+offset, 2, NULL);
1127 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1130 dissect_ppp_stuff(pd, offset, fd, tree, fh_tree);
1134 dissect_ppp( const u_char *pd, frame_data *fd, proto_tree *tree ) {
1137 proto_tree *fh_tree = NULL;
1139 ph.ppp_addr = pd[0];
1141 ph.ppp_prot = pntohs(&pd[2]);
1143 /* load the top pane info. This should be overwritten by
1144 the next protocol in the stack */
1146 if(check_col(fd, COL_RES_DL_SRC))
1147 col_add_str(fd, COL_RES_DL_SRC, "N/A" );
1148 if(check_col(fd, COL_RES_DL_DST))
1149 col_add_str(fd, COL_RES_DL_DST, "N/A" );
1150 if(check_col(fd, COL_PROTOCOL))
1151 col_add_str(fd, COL_PROTOCOL, "PPP" );
1153 /* populate a tree in the second pane with the status of the link
1156 ti = proto_tree_add_item(tree, proto_ppp, 0, 4, NULL);
1157 fh_tree = proto_item_add_subtree(ti, ett_ppp);
1158 proto_tree_add_text(fh_tree, 0, 1, "Address: %02x", ph.ppp_addr);
1159 proto_tree_add_text(fh_tree, 1, 1, "Control: %02x", ph.ppp_ctl);
1162 if (!dissect_ppp_stuff(pd, 2, fd, tree, fh_tree)) {
1163 if (check_col(fd, COL_PROTOCOL))
1164 col_add_fstr(fd, COL_PROTOCOL, "0x%04x", ph.ppp_prot);
1169 proto_register_ppp(void)
1171 /* static hf_register_info hf[] = {
1173 { "Name", "ppp.abbreviation", TYPE, VALS_POINTER }},
1175 static gint *ett[] = {
1179 &ett_ipcp_ipaddrs_opt,
1180 &ett_ipcp_compressprot_opt,
1184 &ett_lcp_async_map_opt,
1185 &ett_lcp_authprot_opt,
1186 &ett_lcp_qualprot_opt,
1187 &ett_lcp_magicnum_opt,
1188 &ett_lcp_fcs_alternatives_opt,
1189 &ett_lcp_numbered_mode_opt,
1190 &ett_lcp_callback_opt,
1191 &ett_lcp_multilink_ep_disc_opt,
1192 &ett_lcp_internationalization_opt,
1195 proto_ppp = proto_register_protocol("Point-to-Point Protocol", "ppp");
1196 /* proto_register_field_array(proto_ppp, hf, array_length(hf));*/
1197 proto_register_subtree_array(ett, array_length(ett));
1201 proto_register_mp(void)
1203 static hf_register_info hf[] = {
1204 { &hf_mp_frag_first,
1205 { "First fragment", "mp.first", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1209 { "Last fragment", "mp.last", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1212 { &hf_mp_sequence_num,
1213 { "Sequence number", "mp.seq", FT_UINT24, BASE_DEC, NULL, 0x0,
1216 static gint *ett[] = {
1221 proto_mp = proto_register_protocol("PPP Multilink Protocol", "mp");
1222 proto_register_field_array(proto_mp, hf, array_length(hf));
1223 proto_register_subtree_array(ett, array_length(ett));