Add a new "prefs_register_protocol()" routine, which is like
[obnox/wireshark/wip.git] / packet-l2tp.c
1 /* packet-l2tp.c
2  * Routines for Layer Two Tunnelling Protocol (L2TP) (RFC 2661) packet
3  * disassembly
4  * John Thomes <john@ensemblecom.com>
5  *
6  * Minor changes by: (2000-01-10)
7  * Laurent Cazalet <laurent.cazalet@mailclub.net>
8  * Thomas Parvais <thomas.parvais@advalvas.be>
9  *
10  * $Id: packet-l2tp.c,v 1.18 2001/01/03 06:55:29 guy Exp $
11  *
12  * Ethereal - Network traffic analyzer
13  * By Gerald Combs <gerald@zing.org>
14  * Copyright 1998 Gerald Combs
15  *
16  * 
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  * 
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  * 
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
30  */
31
32
33 static int proto_l2tp = -1;
34 static int hf_l2tp_code = -1; /* XXX - to be removed */
35 static int hf_l2tp_type = -1;
36 static int hf_l2tp_length_bit = -1;
37 static int hf_l2tp_seq_bit = -1;
38 static int hf_l2tp_offset_bit = -1;
39 static int hf_l2tp_priority = -1; 
40 static int hf_l2tp_version = -1;
41 static int hf_l2tp_length = -1;
42 static int hf_l2tp_tunnel = -1;
43 static int hf_l2tp_session = -1;
44 static int hf_l2tp_Ns = -1;
45 static int hf_l2tp_Nr = -1;
46 static int hf_l2tp_offset = -1;
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #ifdef HAVE_SYS_TYPES_H
53 # include <sys/types.h>
54 #endif
55
56 #ifdef HAVE_NETINET_IN_H
57 #include <netinet/in.h>
58 #endif
59
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <ctype.h>
64 #include <glib.h>
65 #include "packet.h"
66 #include "resolv.h"
67
68 #define UDP_PORT_L2TP   1701
69
70 #define CONTROL_BIT(msg_info) (msg_info & 0x8000)   /* Type bit control = 1 data = 0 */
71 #define LENGTH_BIT(msg_info) (msg_info & 0x4000)    /* Length bit = 1  */ 
72 #define RESERVE_BITS(msg_info) (msg_info &0x37F8)   /* Reserved bit - usused */
73 #define SEQUENCE_BIT(msg_info) (msg_info & 0x0800)  /* SEQUENCE bit = 1 Ns and Nr fields */
74 #define OFFSET_BIT(msg_info) (msg_info & 0x0200)    /* Offset */
75 #define PRIORITY_BIT(msg_info) (msg_info & 0x0100)  /* Priority */
76 #define L2TP_VERSION(msg_info) (msg_info & 0x000f)  /* Version of l2tp */
77 #define MANDATORY_BIT(msg_info) (msg_info & 0x8000) /* Mandatory = 1 */
78 #define HIDDEN_BIT(msg_info) (msg_info & 0x4000)    /* Hidden = 1 */
79 #define AVP_LENGTH(msg_info) (msg_info & 0x03ff)    /* AVP Length */
80 #define FRAMING_ASYNC(msg_info) (msg_info & 0x0001) /* ASYNCFraming Type */
81 #define FRAMING_SYNC(msg_info)  (msg_info & 0x0002) /* SYNC Type */
82
83
84 static gint ett_l2tp = -1;
85 static gint ett_l2tp_ctrl = -1;
86 static gint ett_l2tp_avp = -1;
87
88 #define AVP_SCCRQ      1
89 #define AVP_SCCRP      2
90 #define AVP_SCCCN      3
91 #define AVP_StopCCN    4
92 #define AVP_Reserved   5
93 #define AVP_HELLO      6 
94 #define AVP_OCRQ       7 
95 #define AVP_OCRP       8 
96 #define AVP_ORCRP      9 
97 #define AVP_ICRQ      10 
98 #define AVP_ICRP      11 
99 #define AVP_ICCN      12 
100 #define AVP_Reserved1 13 
101 #define AVP_CDN       14 
102
103
104 #define NUM_CONTROL_CALL_TYPES  16
105 static const char *calltypestr[NUM_CONTROL_CALL_TYPES+1] = {
106   "Unknown Call Type           ",
107   "Start_Control_Request       ",
108   "Start_Control_Reply         ",
109   "Start_Control_Connected     ",
110   "Stop_Control_Notification   ",
111   "Reserved                    ",
112   "Hello                       ",
113   "Outgoing_Call_Request       ",
114   "Outgoing_Call_Reply         ",
115   "Outgoing_Call_Connected     ",
116   "Incoming_Call_Request       ",
117   "Incoming_Call_Reply         ",
118   "Incoming_Call_Connected     ",
119   "Reserved                    ",
120   "Call_Disconnect_Notification",
121   "WAN_Error_Notify            ",
122   "Set_Link_Info               ",
123 };
124
125 static const char *calltype_short_str[NUM_CONTROL_CALL_TYPES+1] = {
126   "Unknown ",
127   "SCCRQ   ",
128   "SCCRP   ",
129   "SCCCN   ",
130   "StopCCN ",
131   "Reserved",
132   "Hello   ",
133   "OCRQ    ",
134   "OCRP    ",
135   "OCCN    ",
136   "ICRQ    ",
137   "ICRP    ",
138   "ICCN    ",
139   "Reserved",
140   "CDN     ",
141   "WEN     ",
142   "SLI     ",
143 };
144
145
146 static const char *control_msg  = "Control Message";
147 static const char *data_msg     = "Data    Message";
148 static const value_string l2tp_type_vals[] = {
149         { 0, "Data Message" },
150         { 1, "Control Message" },
151 };
152
153 static const true_false_string l2tp_length_bit_truth =
154         { "Length field is present", "Length field is not present" };
155
156 static const true_false_string l2tp_seq_bit_truth =
157         { "Ns and Nr fields are present", "Ns and Nr fields are not present" };
158
159 static const true_false_string l2tp_offset_bit_truth =
160         { "Offset Size field is present", "Offset size field is not present" };
161
162 static const true_false_string l2tp_priority_truth =
163         { "This data message has priority", "No priority" };
164
165 #define NUM_AUTH_TYPES  6
166 static const char *authen_types[NUM_AUTH_TYPES] = {
167   "Reserved",
168   "Textual username and password",
169   "PPP CHAP",
170   "PPP PAP",
171   "No Authentication",
172   "Microsoft CHAP Version 1",
173 };
174
175 #define  CONTROL_MESSAGE  0
176 #define  RESULT_ERROR_CODE 1
177 #define  PROTOCOL_VERSION  2
178 #define  FRAMING_CAPABIlITIES 3
179 #define  BEARER_CAPABIlITIES 4
180 #define  TIE_BREAKER 5
181 #define  FIRMWARE_REVISION 6
182 #define  HOST_NAME 7
183 #define  VENDOR_NAME 8
184 #define  ASSIGNED_TUNNEL_ID 9
185 #define  RECEIVE_WINDOW_SIZE 10
186 #define  CHALLENGE 11
187 #define  CAUSE_CODE 12 
188 #define  CHALLENGE_RESPONSE 13
189 #define  ASSIGNED_SESSION 14
190 #define  CALL_SERIAL_NUMBER 15
191 #define  MINIMUM_BPS 16
192 #define  MAXIMUM_BPS 17
193 #define  BEARER_TYPE 18
194 #define  FRAMING_TYPE 19
195 #define  UNKNOWN_MESSAGE 20
196 #define  CALLED_NUMBER 21
197 #define  CALLING_NUMBER 22
198 #define  SUB_ADDRESS 23
199 #define  TX_CONNECT_SPEED 24
200 #define  PHYSICAL_CHANNEL 25
201 #define  INITIAL_RECEIVED_LCP 26
202 #define  LAST_SEND_LCP_CONFREQ 27
203 #define  LAST_RECEIVED_LCP_CONFREQ 28
204 #define  PROXY_AUTHEN_TYPE 29
205 #define  PROXY_AUTHEN_NAME 30
206 #define  PROXY_AUTHEN_CHALLENGE 31
207 #define  PROXY_AUTHEN_ID 32
208 #define  PROXY_AUTHEN_RESPONSE 33
209 #define  CALL_STATUS_AVPS 34
210 #define  ACCM 35
211 #define  UNKOWN_MESSAGE_36
212 #define  PRIVATE_GROUP_ID 37
213 #define  RX_CONNECT_SPEED 38
214 #define  SEQUENCING_REQUIRED 39
215
216 #define NUM_AVP_TYPES  40
217 static const char *avptypestr[NUM_AVP_TYPES] = {
218   "Control Message ",
219   "Result-Error Code ",
220   "Protocol Version ",
221   "Framing Capabilities ",
222   "Bearer Capabilities  ",
223   "Tie Breaker ",
224   "Firmware Revision ",
225   "Host Name ",
226   "Vendor Name ",
227   "Assigned Tunnel ID ",
228   "Receive Window Size ",
229   "Challenge ",
230   "Cause Code ",
231   "Challenge Response ",
232   "Assigned Session ",
233   "Call Serial Number ",
234   "Minimun BPS ",
235   "Maximum bps ",
236   "Bearer Type ",
237   "Framing Type ",
238   "Unknown Message ",
239   "Called Number ",
240   "Calling Number ",
241   "Sub-Address ",
242   "Connect Speed ",
243   "Physical Channel ",
244   "Initial Received lcP ",
245   "Last Send LCP CONFREQ ",
246   "Last Received LCP CONFREQ ",
247   "Proxy Authen Type ",
248   "Proxy Authen Name ",
249   "Proxy Authen Challenge ",
250   "Proxy Authen ID ",
251   "Proxy Authen Response ",
252   "Call status AVPs ",
253   "ACCM ",
254   "Unknown Message ",
255   "Private group ID ",
256   "RxConnect Speed ",
257   "Sequencing Required ",
258 };
259
260
261 static gchar textbuffer[200];
262
263 static dissector_handle_t ppp_handle;
264
265 static void
266 dissect_l2tp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
267 {
268   proto_tree *l2tp_tree=NULL, *l2tp_avp_tree, *ctrl_tree;
269   proto_item *ti, *tf;
270   int rhcode;
271   int index = 0;
272   int tmp_index;
273   int proto_length = 0;
274   unsigned short  length = 0;           /* Length field */
275   unsigned short  tid;                  /* Tunnel ID */
276   unsigned short  cid;                  /* Call ID */
277   unsigned short  offset_size;          /* Offset size */
278   unsigned short ver_len_hidden;
279   unsigned short vendor;
280   unsigned short avp_type;
281   unsigned short msg_type;
282   unsigned short avp_len;
283   unsigned short result_code;
284   unsigned short error_code;
285   unsigned short avp_ver;
286   unsigned short avp_rev;
287   unsigned short framing;
288   unsigned short firmware_rev;
289   unsigned short gen_type;
290   unsigned long long_type;
291   char  error_string[100];
292   char  message_string[200];
293
294   guint16       control;
295   tvbuff_t      *next_tvb;
296
297   CHECK_DISPLAY_AS_DATA(proto_l2tp, tvb, pinfo, tree);
298
299   pinfo->current_proto = "L2TP";
300   if (check_col(pinfo->fd, COL_PROTOCOL))       /* build output for closed L2tp frame displayed  */
301         col_set_str(pinfo->fd, COL_PROTOCOL, "L2TP"); 
302
303   control = tvb_get_ntohs(tvb, 0);
304
305   if (L2TP_VERSION(control) != 2) {
306           if (check_col(pinfo->fd, COL_INFO)) {
307                 col_add_fstr(pinfo->fd, COL_INFO, "L2TP Version %u", L2TP_VERSION(control) );
308           }
309           return;
310   }
311
312   rhcode= 10;
313
314   if (LENGTH_BIT(control)) {            /* length field included ? */
315       index += 2;                       /* skip ahead */
316       length = tvb_get_ntohs(tvb, index);
317   }
318
319   /* collect the tunnel id & call id */
320   index += 2;
321   tid = tvb_get_ntohs(tvb, index);
322   index += 2;
323   cid = tvb_get_ntohs(tvb, index);
324
325   if (check_col(pinfo->fd, COL_INFO)) {
326         if (CONTROL_BIT(control)) {
327             /* CONTROL MESSAGE */
328             tmp_index = index;
329
330               if ((LENGTH_BIT(control))&&(length==12))                  /* ZLB Message */
331                   sprintf(textbuffer,"%s - ZLB      (tunnel id=%d, session id=%d)",
332                           control_msg , tid ,cid);
333               else
334               {
335                 if (SEQUENCE_BIT(control)) {
336                     tmp_index += 4;
337                 }
338     
339                 tmp_index+=4;
340     
341                 avp_type = tvb_get_ntohs(tvb, (tmp_index+=2));
342     
343                 if (avp_type == CONTROL_MESSAGE)
344                 {
345                     /* We print message type */
346                     msg_type = tvb_get_ntohs(tvb, (tmp_index+=2));
347                     sprintf(textbuffer,"%s - %s (tunnel id=%d, session id=%d)",
348                             control_msg ,
349                             ((NUM_CONTROL_CALL_TYPES + 1 ) > msg_type) ?
350                             calltype_short_str[msg_type] : "Unknown",
351                             tid ,cid);
352                 }
353                 else
354                 {
355                     /*
356                      * This is not a control message.
357                      * We never pass here except in case of bad l2tp packet!
358                      */
359                     sprintf(textbuffer,"%s (tunnel id=%d, session id=%d)",
360                             control_msg ,  tid ,cid);
361     
362                 }
363               }
364         }
365         else {
366             /* DATA Message */
367                sprintf(textbuffer,"%s            (tunnel id=%d, session id=%d)",
368                        data_msg, tid ,cid);
369         }
370         col_add_fstr(pinfo->fd,COL_INFO,textbuffer);
371   }
372
373   if (LENGTH_BIT(control)) {
374         proto_length = length;
375   }
376   else {
377         proto_length = tvb_length(tvb);
378   }
379
380   if (tree) {
381         ti = proto_tree_add_item(tree,proto_l2tp, tvb, 0, proto_length, FALSE);
382         l2tp_tree = proto_item_add_subtree(ti, ett_l2tp);
383
384         ti = proto_tree_add_text(l2tp_tree, tvb, 0, 2,
385                         "Packet Type: %s Tunnel Id=%d Session Id=%d",
386                         (CONTROL_BIT(control) ? control_msg : data_msg), tid, cid);
387
388         ctrl_tree = proto_item_add_subtree(ti, ett_l2tp_ctrl);
389         proto_tree_add_uint(ctrl_tree, hf_l2tp_type, tvb, 0, 2, control);
390         proto_tree_add_boolean(ctrl_tree, hf_l2tp_length_bit, tvb, 0, 2, control);
391         proto_tree_add_boolean(ctrl_tree, hf_l2tp_seq_bit, tvb, 0, 2, control);
392         proto_tree_add_boolean(ctrl_tree, hf_l2tp_offset_bit, tvb, 0, 2, control);
393         proto_tree_add_boolean(ctrl_tree, hf_l2tp_priority, tvb, 0, 2, control);
394         proto_tree_add_uint(ctrl_tree, hf_l2tp_version, tvb, 0, 2, control);
395   }
396   index = 2;
397   if (LENGTH_BIT(control)) {
398           if (tree) {
399                 proto_tree_add_item(l2tp_tree, hf_l2tp_length, tvb, index, 2, FALSE);
400           }
401         index += 2;
402   }
403
404   if (tree) {
405         proto_tree_add_item(l2tp_tree, hf_l2tp_tunnel, tvb, index, 2, FALSE);
406   }
407   index += 2;
408   if (tree) {
409         proto_tree_add_item(l2tp_tree, hf_l2tp_session, tvb, index, 2, FALSE);
410   }
411   index += 2;
412
413   if (SEQUENCE_BIT(control)) {
414           if (tree) {
415                 proto_tree_add_item(l2tp_tree, hf_l2tp_Ns, tvb, index, 2, FALSE);
416           }
417           index += 2;
418           if (tree) {
419                 proto_tree_add_item(l2tp_tree, hf_l2tp_Nr, tvb, index, 2, FALSE);
420           }
421           index += 2;
422   }
423   if (OFFSET_BIT(control)) {
424         offset_size = tvb_get_ntohs(tvb, index);
425         if (tree) {
426                 proto_tree_add_uint(l2tp_tree, hf_l2tp_offset, tvb, index, 2, FALSE);
427         }
428         index += 2;
429         if (tree) {
430                 proto_tree_add_text(l2tp_tree, tvb, index, offset_size, "Offset Padding");
431         }
432         index += offset_size;
433   }
434   if (tree && (LENGTH_BIT(control))&&(length==12)) {
435             proto_tree_add_text(l2tp_tree, tvb, 0, 0, "Zero Length Bit message");
436   }
437
438   if (!CONTROL_BIT(control)) {  /* Data Messages so we are done */
439         /* If we have data, signified by having a length bit, dissect it */
440         if (tvb_offset_exists(tvb, index)) {
441                 next_tvb = tvb_new_subset(tvb, index, -1, proto_length - index);
442                 call_dissector(ppp_handle, next_tvb, pinfo, tree);
443         }
444         return;
445   }
446
447   if (tree) {
448         if (!LENGTH_BIT(control)) {
449                 return;
450         }
451         while (index < length ) {    /* Process AVP's */
452                 tmp_index       = index;
453                 ver_len_hidden  = tvb_get_ntohs(tvb, tmp_index);
454                 avp_len         = AVP_LENGTH(ver_len_hidden);
455                 vendor          = tvb_get_ntohs(tvb, (tmp_index+=2));
456                 avp_type        = tvb_get_ntohs(tvb, (tmp_index+=2));
457
458                 tf =  proto_tree_add_uint_format(l2tp_tree,hf_l2tp_code, tvb, index , avp_len,
459                                                  rhcode, "AVP Type  %s  ",  (NUM_AVP_TYPES > avp_type)
460                                                  ? avptypestr[avp_type] : "Unknown");
461                 l2tp_avp_tree = proto_item_add_subtree(tf,  ett_l2tp_avp);
462
463                 proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index , 1,
464                                            rhcode, " Mandatory:%s" ,
465                                            (MANDATORY_BIT(ver_len_hidden)) ? "True" : "False" );
466                 proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index , 1,
467                                            rhcode, " Hidden:%s" ,
468                                            (HIDDEN_BIT(ver_len_hidden)) ? "True" : "False" );
469                 proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, (index + 1), 1,
470                                            rhcode, " Length:%d" , avp_len );
471
472                 if (avp_len == 0) {
473                         proto_tree_add_text(l2tp_avp_tree, tvb, (index + 1), 1, "Length should not be zero");
474                         return;
475                 }
476
477                 if (HIDDEN_BIT(ver_len_hidden)) { /* don't try do display hidden */
478                         index += avp_len;
479                         continue;
480                 }
481
482                 switch (avp_type) {
483
484                 case CONTROL_MESSAGE:
485                     msg_type = tvb_get_ntohs(tvb, (tmp_index+=2));
486                     proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 2 ,
487                                                rhcode, " Control Message Type: (%d)  %s", msg_type,
488                                                ((NUM_CONTROL_CALL_TYPES + 1 ) > msg_type) ?
489                                                calltypestr[msg_type] : "Unknown" );
490                     break;
491
492                 case RESULT_ERROR_CODE:
493                         if ( avp_len >= 8 ) {
494                                 result_code = tvb_get_ntohs(tvb, (tmp_index+=2));
495                                 proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
496                                   2, rhcode,
497                                   " Result code: %d",  result_code  );
498                 
499                         }
500                         if ( avp_len >= 10 ) {
501                                 error_code = tvb_get_ntohs(tvb, (tmp_index+=2));
502                                 proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 8,
503                                   2, rhcode,
504                                   " Error code: %d", error_code);
505                         }
506                         if ( avp_len > 10 ) {
507                                 memset(error_string,'\0' ,sizeof(error_string));
508                                 strncpy(error_string, tvb_get_ptr(tvb, tmp_index,(avp_len - 10)),
509                                                 avp_len - 10);
510                                 proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 10, (avp_len - 10),
511                                   rhcode, " Error Message: %s",  error_string  );
512                         }
513                         break;
514
515                 case PROTOCOL_VERSION:
516                         avp_ver = tvb_get_ntohs(tvb, (tmp_index+=2));
517                         avp_rev = tvb_get_ntohs(tvb, (tmp_index+=2));
518                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 1,
519                           rhcode, " Version: %d",  ((avp_ver&0xff00)>>8)  );
520                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 7, 1,
521                           rhcode, " Revision: %d",  (avp_ver&0x00ff));
522                         break;
523
524                 case FRAMING_CAPABIlITIES:
525                         tmp_index+=2;
526                         framing = tvb_get_ntohs(tvb, (tmp_index+=2));
527                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 4,
528                           rhcode, " ASYNC FRAMING: %s" , (FRAMING_ASYNC(framing)) ? "True" : "False" );  
529                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 4,
530                           rhcode, " SYNC FRAMING: %s" , (FRAMING_SYNC(framing)) ? "True" : "False" );  
531                         break;
532
533                 case BEARER_CAPABIlITIES:
534                         tmp_index+=2;
535                         framing = tvb_get_ntohs(tvb, (tmp_index+=2));
536                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 4 ,
537                           rhcode, " Analog Access: %s" , (FRAMING_ASYNC(framing)) ? "True" : "False" );  
538                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 4,
539                           rhcode, " Digital Access: %s" , (FRAMING_SYNC(framing)) ? "True" : "False" );  
540                         break;
541
542                 case TIE_BREAKER:
543                         long_type = tvb_get_ntohl(tvb, (tmp_index+=8));
544                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 1,
545                           rhcode, " TIE_BREAKER %lu 0x%lx", long_type,long_type );
546                         break;
547
548                 case FIRMWARE_REVISION:
549                         firmware_rev = tvb_get_ntohs(tvb, (tmp_index+=2));
550                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 2,
551                           rhcode, " Firmware Revision: %d 0x%x", firmware_rev,firmware_rev );
552                         break;
553
554                 case HOST_NAME:
555                         memset(error_string,'\0',sizeof(error_string));
556                         strncpy(error_string, tvb_get_ptr(tvb, (tmp_index+=2), (avp_len - 6)),
557                                         avp_len - 6);
558                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 
559                           (avp_len - 6), rhcode, " Host Name: %s",  error_string  );
560                         break;
561
562                 case VENDOR_NAME:
563                         memset(message_string,'\0' ,sizeof(message_string));
564                         strncpy(message_string, tvb_get_ptr(tvb, (tmp_index+=2),(avp_len - 6)),
565                                         avp_len - 6);
566                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 
567                           (avp_len - 6), rhcode, " Vendor Name: %s",  message_string  );
568                         break;
569
570                 case ASSIGNED_TUNNEL_ID:
571                         gen_type = tvb_get_ntohs(tvb, (tmp_index+=2));
572                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
573                           2, rhcode, " Tunnel ID: %d",  gen_type  );
574                         break;
575
576                 case RECEIVE_WINDOW_SIZE:
577                         gen_type = tvb_get_ntohs(tvb, (tmp_index+=2));
578                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
579                           2, rhcode, " Receive Window Size: %d",  gen_type  );
580                         break;
581
582                 case CHALLENGE:
583                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
584                           (avp_len - 6 ), rhcode, "  CHAP Challenge: ");
585                         break;
586
587                 case CHALLENGE_RESPONSE:
588                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
589                           (avp_len - 6 ), rhcode, "  CHAP Challenge Response: ");
590                         break;
591
592                 case CAUSE_CODE:
593                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
594                           1, rhcode, " Cause Code: ");
595                         break;
596
597                 case ASSIGNED_SESSION:
598                         gen_type = tvb_get_ntohs(tvb, (tmp_index+=2));
599                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
600                           2, rhcode, " Assigned Session: %d",  gen_type  );
601                         break;
602
603                 case CALL_SERIAL_NUMBER:
604                         gen_type = tvb_get_ntohs(tvb, (tmp_index+=2));
605                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
606                           4, rhcode, " Call Serial Number: %d",  gen_type  );
607                         break;
608
609                 case MINIMUM_BPS:
610                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
611                           4, rhcode, " Minimum BPS: ");
612                         break;
613
614                 case MAXIMUM_BPS:
615                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
616                           4, rhcode, " Maximum BPS ");
617                         break;
618
619                 case BEARER_TYPE:
620                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
621                           4, rhcode, " Bearer Type: ");
622                         break;
623
624                 case FRAMING_TYPE:
625                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
626                           4, rhcode, " Framing Type: ");
627                         break;
628
629                 case UNKNOWN_MESSAGE:
630                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
631                           1, rhcode, " Unknown Message: ");
632                         break;
633
634                 case CALLED_NUMBER:
635                         memset(message_string,'\0' ,sizeof(message_string));
636                         strncpy(message_string, tvb_get_ptr(tvb, (tmp_index+=2),(avp_len - 6)),
637                                         avp_len - 6);
638                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 
639                           (avp_len - 6), rhcode, " Called Number: %s",  message_string  );
640                         break;
641
642                 case CALLING_NUMBER:
643                         memset(message_string,'\0' ,sizeof(message_string));
644                         strncpy(message_string, tvb_get_ptr(tvb, (tmp_index+=2),(avp_len - 6)),
645                                         avp_len - 6);
646                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 
647                           (avp_len - 6), rhcode, " Calling Number: %s",  message_string  );
648                         break;
649
650                 case SUB_ADDRESS:
651                         memset(message_string,'\0' ,sizeof(message_string));
652                         strncpy(message_string, tvb_get_ptr(tvb, (tmp_index+=2),(avp_len - 6)),
653                                         avp_len - 6);
654                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb, index + 6, 
655                           (avp_len - 6), rhcode, " Sub-Address: %s",  message_string  );
656                         break;
657
658                 case TX_CONNECT_SPEED:
659                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
660                           4, rhcode, " Connect Speed: ");
661                         break;
662
663                 case PHYSICAL_CHANNEL:
664                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
665                           4, rhcode, " Physical Channel: ");
666                         break;
667
668                 case INITIAL_RECEIVED_LCP:
669                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
670                           (avp_len - 6 ), rhcode, " Initial LCP Conf REQ: ");
671                         break;
672
673                 case LAST_SEND_LCP_CONFREQ:
674                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
675                           (avp_len - 6 ), rhcode, " Last Sent LCP Conf REQ: ");
676                         break;
677
678                 case LAST_RECEIVED_LCP_CONFREQ:
679                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
680                           (avp_len - 6 ), rhcode, " Last Received LCP Conf REQ: ");
681                         break;
682
683                 case PROXY_AUTHEN_TYPE:
684                         msg_type = tvb_get_ntohs(tvb, (tmp_index+=2));
685                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
686                           1, rhcode, " Proxy Authen Type: %s ", authen_types[msg_type] );
687                         break;
688
689                 case PROXY_AUTHEN_NAME:
690                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
691                           (avp_len - 6 ), rhcode, " Proxy Authen Name: ");
692                         break;
693
694                 case PROXY_AUTHEN_CHALLENGE:
695                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
696                           (avp_len - 6 ), rhcode, " Proxy Authen Challenge: ");
697                         break;
698
699                 case PROXY_AUTHEN_ID:
700                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
701                           2, rhcode, " Paorx Authen ID: ");
702                         break;
703
704                 case PROXY_AUTHEN_RESPONSE:
705                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
706                           (avp_len - 6 ), rhcode, " Proxy Authen Response: ");
707                         break;
708
709                 case CALL_STATUS_AVPS:
710                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
711                           4, rhcode, "  CRC Errors: ");
712                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 10,
713                           4, rhcode, "  Framing Errors: ");
714                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 14,
715                           4, rhcode, "  Hardware Overruns: ");
716                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 18,
717                           4, rhcode, "  Buffer Overruns: ");
718                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 23,
719                           4, rhcode, "  Time-out Errors: ");
720                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 26,
721                           4, rhcode, "  Alignment Errors: ");
722                         break;
723
724                 case ACCM:
725                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
726                           2, rhcode, " Reserve Quantity: ");
727                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 8,
728                           4, rhcode, " Send ACCM: ");
729                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 12,
730                           4, rhcode, " Recv ACCM: ");
731                         break;
732
733                 case PRIVATE_GROUP_ID:
734                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
735                           1, rhcode, " Private Group ID: ");
736                         break;
737
738                 case RX_CONNECT_SPEED:
739                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index + 6,
740                           4, rhcode, " RX Connect Speed: ");
741                         break;
742
743                 case SEQUENCING_REQUIRED:
744                         proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_code, tvb,index ,
745                           1, rhcode, " Sequencing Required: ");
746                         break;
747                 }
748
749                 /* printf("Avp Decode avp_len= %d index= %d length= %d %x\n ",avp_len,
750                    index,length,length); */
751
752                 index += avp_len;
753         }
754
755   }
756 }
757
758 /* registration with the filtering engine */
759 void
760 proto_register_l2tp(void)
761 {
762         static hf_register_info hf[] = {
763                 { &hf_l2tp_code,
764                 { "code", "lt2p.code", FT_UINT16, BASE_DEC, NULL, 0, /* XXX - to be removed */
765                         "Type bit" }},
766
767                 { &hf_l2tp_type,
768                 { "Type", "lt2p.type", FT_UINT16, BASE_DEC, VALS(l2tp_type_vals), 0x8000,
769                         "Type bit" }},
770
771                 { &hf_l2tp_length_bit,
772                 { "Length Bit", "lt2p.length_bit", FT_BOOLEAN, 16, TFS(&l2tp_length_bit_truth), 0x4000,
773                         "Length bit" }},
774
775                 { &hf_l2tp_seq_bit,
776                 { "Sequence Bit", "lt2p.seq_bit", FT_BOOLEAN, 16, TFS(&l2tp_seq_bit_truth), 0x0800,
777                         "Sequence bit" }},
778
779                 { &hf_l2tp_offset_bit,
780                 { "Offset bit", "lt2p.offset_bit", FT_BOOLEAN, 16, TFS(&l2tp_offset_bit_truth), 0x0200,
781                         "Offset bit" }},
782
783                 { &hf_l2tp_priority,
784                 { "Priority", "lt2p.priority", FT_BOOLEAN, 16, TFS(&l2tp_priority_truth), 0x0100,
785                         "Priority bit" }},
786
787                 { &hf_l2tp_version,
788                 { "Version", "lt2p.version", FT_UINT16, BASE_DEC, NULL, 0x000f,
789                         "Version" }},
790
791                 { &hf_l2tp_length,
792                 { "Length","l2tp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
793                         "" }},
794
795                 { &hf_l2tp_tunnel,
796                 { "Tunnel ID","l2tp.tunnel", FT_UINT16, BASE_DEC, NULL, 0x0, /* Probably should be FT_BYTES */
797                         "Tunnel ID" }},
798
799                 { &hf_l2tp_session,
800                 { "Session ID","l2tp.session", FT_UINT16, BASE_DEC, NULL, 0x0, /* Probably should be FT_BYTES */
801                         "Session ID" }},
802
803                 { &hf_l2tp_Ns,
804                 { "Ns","l2tp.Ns", FT_UINT16, BASE_DEC, NULL, 0x0,
805                         "" }},
806
807                 { &hf_l2tp_Nr,
808                 { "Nr","l2tp.Nr", FT_UINT16, BASE_DEC, NULL, 0x0,
809                         "" }},
810
811                 { &hf_l2tp_offset,
812                 { "Offset","l2tp.offset", FT_UINT16, BASE_DEC, NULL, 0x0,
813                         "Number of octest past the L2TP header at which the"
814                                 "payload data starts." }},
815
816         };
817
818         static gint *ett[] = {
819                 &ett_l2tp,
820                 &ett_l2tp_ctrl,
821                 &ett_l2tp_avp,
822         };
823
824         proto_l2tp = proto_register_protocol(
825                 "Layer 2 Tunneling Protocol", "L2TP", "l2tp");
826         proto_register_field_array(proto_l2tp, hf, array_length(hf));
827         proto_register_subtree_array(ett, array_length(ett));
828 }
829
830 void
831 proto_reg_handoff_l2tp(void)
832 {
833         dissector_add("udp.port", UDP_PORT_L2TP, dissect_l2tp);
834
835         /*
836          * Get a handle for the PPP dissector.
837          */
838         ppp_handle = find_dissector("ppp");
839 }