Add a comment.
[obnox/wireshark/wip.git] / packet-ppp.c
1 /* packet-ppp.c
2  * Routines for ppp packet disassembly
3  *
4  * $Id: packet-ppp.c,v 1.13 1999/07/29 05:47:01 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  *
9  * This file created and by Mike Hall <mlh@io.com>
10  * Copyright 1998
11  * 
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.
16  * 
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.
21  * 
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.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <glib.h>
36 #include "packet.h"
37
38 static int proto_ppp = -1;
39
40 /* PPP structs and definitions */
41
42 typedef struct _e_ppphdr {
43   guint8  ppp_addr;
44   guint8  ppp_ctl;
45   guint16 ppp_prot;
46 } e_ppphdr;
47
48
49 /* Protocol types, from Linux "ppp_defs.h" and
50
51         http://www.isi.edu/in-notes/iana/assignments/ppp-numbers
52
53  */
54 #define PPP_IP          0x21    /* Internet Protocol */
55 #define PPP_AT          0x29    /* AppleTalk Protocol */
56 #define PPP_IPX         0x2b    /* IPX protocol */
57 #define PPP_VJC_COMP    0x2d    /* VJ compressed TCP */
58 #define PPP_VJC_UNCOMP  0x2f    /* VJ uncompressed TCP */
59 #define PPP_VINES       0x35    /* Banyan Vines */
60 #define PPP_IPV6        0x57    /* Internet Protocol Version 6 */
61 #define PPP_COMP        0xfd    /* compressed packet */
62 #define PPP_IPCP        0x8021  /* IP Control Protocol */
63 #define PPP_ATCP        0x8029  /* AppleTalk Control Protocol */
64 #define PPP_IPXCP       0x802b  /* IPX Control Protocol */
65 #define PPP_CCP         0x80fd  /* Compression Control Protocol */
66 #define PPP_LCP         0xc021  /* Link Control Protocol */
67 #define PPP_PAP         0xc023  /* Password Authentication Protocol */
68 #define PPP_LQR         0xc025  /* Link Quality Report protocol */
69 #define PPP_CHAP        0xc223  /* Cryptographic Handshake Auth. Protocol */
70 #define PPP_CBCP        0xc029  /* Callback Control Protocol */
71
72
73 static const value_string ppp_vals[] = {
74         {PPP_IP,        "IP"             },
75         {PPP_AT,        "Appletalk"      },
76         {PPP_IPX,       "Netware IPX/SPX"},
77         {PPP_VJC_COMP,  "VJ compressed TCP"},
78         {PPP_VJC_UNCOMP,"VJ uncompressed TCP"}, 
79         {PPP_VINES,     "Vines"          },
80         {PPP_IPV6,      "IPv6"           },
81         {PPP_COMP,                "compressed packet" },
82         {PPP_IPCP,                "IP Control Protocol" },
83         {PPP_ATCP,                "AppleTalk Control Protocol" },
84         {PPP_IPXCP,         "IPX Control Protocol" },
85         {PPP_CCP,                   "Compression Control Protocol" },
86         {PPP_LCP,                   "Link Control Protocol" },
87         {PPP_PAP,                   "Password Authentication Protocol"  },
88         {PPP_LQR,                   "Link Quality Report protocol" },
89         {PPP_CHAP,                "Cryptographic Handshake Auth. Protocol" },
90         {PPP_CBCP,                "Callback Control Protocol" },
91         {0,             NULL            } };
92
93 /* CP (LCP, IPCP, etc.) codes.
94  * from pppd fsm.h 
95  */
96 #define CONFREQ   1 /* Configuration Request */
97 #define CONFACK   2 /* Configuration Ack */
98 #define CONFNAK   3 /* Configuration Nak */
99 #define CONFREJ   4 /* Configuration Reject */
100 #define TERMREQ   5 /* Termination Request */
101 #define TERMACK   6 /* Termination Ack */
102 #define CODEREJ   7 /* Code Reject */
103
104 static const value_string cp_vals[] = {
105         {CONFREQ,    "Configuration Request " },
106         {CONFACK,    "Configuration Ack " },
107         {CONFNAK,    "Configuration Nak " },
108         {CONFREJ,    "Configuration Reject " },
109         {TERMREQ,    "Termination Request " },
110         {TERMACK,    "Termination Ack " },
111         {CODEREJ,    "Code Reject " },
112         {0,             NULL            } };
113
114 /*
115  * LCP-specific packet types.
116  */
117 #define PROTREJ   8 /* Protocol Reject */
118 #define ECHOREQ   9 /* Echo Request */
119 #define ECHOREP   10  /* Echo Reply */
120 #define DISCREQ   11  /* Discard Request */
121 #define CBCP_OPT  6 /* Use callback control protocol */
122
123 static const value_string lcp_vals[] = {
124         {CONFREQ,    "Configuration Request " },
125         {CONFACK,    "Configuration Ack " },
126         {CONFNAK,    "Configuration Nak " },
127         {CONFREJ,    "Configuration Reject " },
128         {TERMREQ,    "Termination Request " },
129         {TERMACK,    "Termination Ack " },
130         {CODEREJ,    "Code Reject " },
131         {PROTREJ, "Protocol Reject " },
132         {ECHOREQ, "Echo Request " },
133         {ECHOREP, "Echo Reply " },
134         {DISCREQ, "Discard Request " },
135         {CBCP_OPT, "Use callback control protocol" },
136         {0,             NULL            } };
137
138 /*
139  * Options.  (LCP)
140  */
141 #define CI_MRU    1 /* Maximum Receive Unit */
142 #define CI_ASYNCMAP 2 /* Async Control Character Map */
143 #define CI_AUTHTYPE 3 /* Authentication Type */
144 #define CI_QUALITY  4 /* Quality Protocol */
145 #define CI_MAGICNUMBER  5 /* Magic Number */
146 #define CI_PCOMPRESSION 7 /* Protocol Field Compression */
147 #define CI_ACCOMPRESSION 8  /* Address/Control Field Compression */
148 #define CI_CALLBACK 13  /* callback */
149
150 static const value_string lcp_opt_vals[] = {
151         {CI_MRU,          "Maximum Receive Unit" },
152         {CI_ASYNCMAP,     "Async Control Character Map" },
153         {CI_AUTHTYPE,     "Authentication Type" },
154         {CI_QUALITY,      "Quality Protocol" },
155         {CI_MAGICNUMBER,  "Magic Number" },
156         {CI_PCOMPRESSION, "Protocol Field Compression" },
157         {CI_ACCOMPRESSION,"Address/Control Field Compression" },
158         {CI_CALLBACK,     "callback" },
159         {0,             NULL            } };
160
161 /*
162  * Options.  (IPCP)
163  */
164 #define CI_ADDRS  1 /* IP Addresses */
165 #define CI_COMPRESSTYPE 2 /* Compression Type */
166 #define CI_ADDR   3
167 #define CI_MS_DNS1  129 /* Primary DNS value */
168 #define CI_MS_WINS1 130 /* Primary WINS value */
169 #define CI_MS_DNS2  131 /* Secondary DNS value */
170 #define CI_MS_WINS2 132 /* Secondary WINS value */
171
172 static const value_string ipcp_opt_vals[] = {
173         {CI_ADDRS,       "IP Addresses" },
174         {CI_COMPRESSTYPE,"Compression Type" },
175         {CI_ADDR,        "Address" }, 
176         {CI_MS_DNS1,     "Primary DNS value" },
177         {CI_MS_WINS1,    "Primary WINS value" },
178         {CI_MS_DNS2,     "Secondary DNS value" },
179         {CI_MS_WINS2,    "Secondary WINS value" },
180         {0,             NULL            } };
181
182 void
183 capture_ppp( const u_char *pd, guint32 cap_len, packet_counts *ld ) {
184   switch (pntohs(&pd[2])) {
185     case PPP_IP:
186       capture_ip(pd, 4, cap_len, ld);
187       break;
188     default:
189       ld->other++;
190       break;
191   }
192 }
193
194 void
195 dissect_ipcp( const u_char *pd, int offset, frame_data *fd, proto_tree *tree ) {
196   proto_tree *fh_tree;
197   proto_item *ti;
198
199         int ipcpcode;
200         int ipcpid;
201         int optionslength;
202
203         ipcpcode = pd[0+offset];
204         ipcpid = pd[1+offset];
205         optionslength= pntohs(&pd[2+offset]);
206         
207         if(check_col(fd, COL_INFO))
208                 col_add_fstr(fd, COL_INFO, "IPCP %s", 
209                         val_to_str(ipcpcode, cp_vals, "Unknown"));
210
211   if(tree) {
212     ti = proto_tree_add_text(tree, 0+offset, 4, "IP Control Protocol" );
213     fh_tree = proto_item_add_subtree(ti, ETT_IPCP);
214     proto_tree_add_text(fh_tree, 0+offset, 1, "Code: %s (0x%02x)",
215       val_to_str(ipcpcode, cp_vals, "Unknown"), ipcpcode);
216     proto_tree_add_text(fh_tree, 1+offset, 1, "Identifier: 0x%02x",
217                         ipcpid);
218     proto_tree_add_text(fh_tree, 2+offset, 2, "Length: %d",
219                         optionslength);
220   }
221
222   switch (ipcpcode) {
223                 /* decode lcp options here. */
224     default:
225       dissect_data(pd, 4+offset, fd, tree);
226       break;
227   }
228 }
229
230 void
231 dissect_lcp( const u_char *pd, int offset, frame_data *fd, proto_tree *tree ) {
232   proto_tree *fh_tree;
233   proto_item *ti;
234
235         int lcpcode;
236         int lcpid;
237         int optionslength;
238
239         lcpcode = pd[0+offset];
240         lcpid = pd[1+offset];
241         optionslength= pntohs(&pd[2+offset]);
242         
243         if(check_col(fd, COL_INFO))
244                 col_add_fstr(fd, COL_INFO, "LCP %s", 
245                         val_to_str(lcpcode, lcp_vals, "Unknown"));
246
247   if(tree) {
248     ti = proto_tree_add_text(tree, 0+offset, 4, "Link Control Protocol" );
249     fh_tree = proto_item_add_subtree(ti, ETT_LCP);
250     proto_tree_add_text(fh_tree, 0+offset, 1, "Code: %s (0x%02x)",
251       val_to_str(lcpcode, lcp_vals, "Unknown"), lcpcode);
252     proto_tree_add_text(fh_tree, 1+offset, 1, "Identifier: 0x%02x",
253                         lcpid);
254     proto_tree_add_text(fh_tree, 2+offset, 2, "Length: %d",
255                         optionslength);
256   }
257
258   switch (lcpcode) {
259                 /* decode lcp options here. */
260     default:
261       dissect_data(pd, 4+offset, fd, tree);
262       break;
263   }
264 }
265
266 void
267 dissect_payload_ppp( const u_char *pd, int offset, frame_data *fd, proto_tree *tree ) {
268   e_ppphdr   ph;
269   proto_tree *fh_tree;
270   proto_item *ti;
271
272 /*  ph.ppp_addr = pd[0+offset]; */
273 /* ph.ppp_ctl  = pd[1+offset]; */
274   ph.ppp_prot = pntohs(&pd[0+offset]);
275
276   /* populate a tree in the second pane with the status of the link
277      layer (ie none) */
278   if(tree) {
279     ti = proto_tree_add_item(tree, proto_ppp, 0+offset, 2, NULL);
280     fh_tree = proto_item_add_subtree(ti, ETT_PPP);
281     proto_tree_add_text(fh_tree, 0+offset, 2, "Protocol: %s (0x%04x)",
282       val_to_str(ph.ppp_prot, ppp_vals, "Unknown"), ph.ppp_prot);
283   }
284
285   switch (ph.ppp_prot) {
286     case PPP_IP:
287       dissect_ip(pd, 2+offset, fd, tree);
288       break;
289     case PPP_AT:
290       dissect_ddp(pd, 2+offset, fd, tree);
291       break;
292     case PPP_IPX:
293       dissect_ipx(pd, 2+offset, fd, tree);
294       break;
295     case PPP_VINES:
296       dissect_vines(pd, 2+offset, fd, tree);
297       break;
298     case PPP_IPV6:
299       dissect_ipv6(pd, 2+offset, fd, tree);
300       break;
301     case PPP_LCP:
302       dissect_lcp(pd, 2+offset, fd, tree);
303       break;
304     case PPP_IPCP:
305       dissect_ipcp(pd, 2+offset, fd, tree);
306       break;
307     default:
308       dissect_data(pd, 2+offset, fd, tree);
309       if (check_col(fd, COL_INFO))
310         col_add_fstr(fd, COL_INFO, "PPP %s (0x%04x)", 
311                                         val_to_str(ph.ppp_prot, ppp_vals, "Unknown"), ph.ppp_prot);
312       break;
313   }
314 }
315
316 void
317 dissect_ppp( const u_char *pd, frame_data *fd, proto_tree *tree ) {
318   e_ppphdr   ph;
319   proto_tree *fh_tree;
320   proto_item *ti;
321
322   static const value_string ppp_vals[] = {
323     {PPP_IP,     "IP"             },
324     {PPP_AT,     "Appletalk"      },
325     {PPP_IPX,    "Netware IPX/SPX"},
326     {PPP_VINES,  "Vines"          },
327     {PPP_IPV6,   "IPv6"           },
328     {0,           NULL            } };
329
330   ph.ppp_addr = pd[0];
331   ph.ppp_ctl  = pd[1];
332   ph.ppp_prot = pntohs(&pd[2]);
333
334   /* load the top pane info. This should be overwritten by
335      the next protocol in the stack */
336
337          if(check_col(fd, COL_RES_DL_SRC))
338            col_add_str(fd, COL_RES_DL_SRC, "N/A" );
339          if(check_col(fd, COL_RES_DL_DST))
340            col_add_str(fd, COL_RES_DL_DST, "N/A" );
341          if(check_col(fd, COL_PROTOCOL))
342            col_add_str(fd, COL_PROTOCOL, "N/A" );
343          if(check_col(fd, COL_INFO))
344            col_add_str(fd, COL_INFO, "PPP" );
345
346   /* populate a tree in the second pane with the status of the link
347      layer (ie none) */
348   if(tree) {
349     ti = proto_tree_add_item(tree, proto_ppp, 0, 4, NULL);
350     fh_tree = proto_item_add_subtree(ti, ETT_PPP);
351     proto_tree_add_text(fh_tree, 0, 1, "Address: %02x", ph.ppp_addr);
352     proto_tree_add_text(fh_tree, 1, 1, "Control: %02x", ph.ppp_ctl);
353     proto_tree_add_text(fh_tree, 2, 2, "Protocol: %s (0x%04x)",
354       val_to_str(ph.ppp_prot, ppp_vals, "Unknown"), ph.ppp_prot);
355   }
356
357   switch (ph.ppp_prot) {
358     case PPP_IP:
359       dissect_ip(pd, 4, fd, tree);
360       break;
361     case PPP_AT:
362       dissect_ddp(pd, 4, fd, tree);
363       break;
364     case PPP_IPX:
365       dissect_ipx(pd, 4, fd, tree);
366       break;
367     case PPP_VINES:
368       dissect_vines(pd, 4, fd, tree);
369       break;
370     case PPP_IPV6:
371       dissect_ipv6(pd, 4, fd, tree);
372       break;
373     default:
374       dissect_data(pd, 4, fd, tree);
375       if (check_col(fd, COL_PROTOCOL))
376         col_add_fstr(fd, COL_PROTOCOL, "0x%04x", ph.ppp_prot);
377       break;
378   }
379 }
380
381 void
382 proto_register_ppp(void)
383 {
384 /*        static hf_register_info hf[] = {
385                 { &variable,
386                 { "Name",           "ppp.abbreviation", TYPE, VALS_POINTER }},
387         };*/
388
389         proto_ppp = proto_register_protocol("Point-to-Point Protocol", "ppp");
390  /*       proto_register_field_array(proto_ppp, hf, array_length(hf));*/
391 }