Keep the sample command line in the usage message within 80 characters.
[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.3 2000/01/10 23:22:22 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_length = -1;
35 static int hf_l2tp_code = -1;
36 static int hf_l2tp_id =-1;
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #ifdef HAVE_SYS_TYPES_H
43 # include <sys/types.h>
44 #endif
45
46 #ifdef HAVE_NETINET_IN_H
47 #include <netinet/in.h>
48 #endif
49
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <ctype.h>
54 #include <glib.h>
55 #include "packet.h"
56 #include "resolv.h"
57
58
59
60 #define CONTROL_BIT(msg_info) (msg_info & 0x8000)   /* Type bit control = 1 data = 0 */
61 #define LENGTH_BIT(msg_info) (msg_info & 0x4000)    /* Length bit = 1  */ 
62 #define RESERVE_BITS(msg_info) (msg_info &0x37F8)   /* Reserved bit - usused */
63 #define SEQUENCE_BIT(msg_info) (msg_info & 0x0800)  /* SEQUENCE bit = 1 Ns and Nr fields */
64 #define OFFSET_BIT(msg_info) (msg_info & 0x0300)    /* Offset */
65 #define PRIORITY_BIT(msg_info) (msg_info & 0x0100)  /* Priority */
66 #define L2TP_VERSION(msg_info) (msg_info & 0x0007)  /* Version of l2tp */
67 #define MANDATORY_BIT(msg_info) (msg_info & 0x8000) /* Mandatory = 1 */
68 #define HIDDEN_BIT(msg_info) (msg_info & 0x4000)    /* Hidden = 1 */
69 #define AVP_LENGTH(msg_info) (msg_info & 0x03ff)    /* AVP Length */
70 #define FRAMING_ASYNC(msg_info) (msg_info & 0x0001) /* ASYNCFraming Type */
71 #define FRAMING_SYNC(msg_info)  (msg_info & 0x0002) /* SYNC Type */
72
73
74
75 static gint ett_l2tp = -1;
76 static gint ett_l2tp_avp = -1;
77
78 #define AVP_SCCRQ      1
79 #define AVP_SCCRP      2
80 #define AVP_SCCCN      3
81 #define AVP_StopCCN    4
82 #define AVP_Reserved   5
83 #define AVP_HELLO      6 
84 #define AVP_OCRQ       7 
85 #define AVP_OCRP       8 
86 #define AVP_ORCRP      9 
87 #define AVP_ICRQ      10 
88 #define AVP_ICRP      11 
89 #define AVP_ICCN      12 
90 #define AVP_Reserved1 13 
91 #define AVP_CDN       14 
92
93
94 #define NUM_CONTROL_CALL_TYPES  16
95 static const char *calltypestr[NUM_CONTROL_CALL_TYPES+1] = {
96   "Unknown Call Type           ",
97   "Start_Control_Request       ",
98   "Start_Control_Reply         ",
99   "Start_Control_Connected     ",
100   "Stop_Control_Notification   ",
101   "Reserved                    ",
102   "Hello                       ",
103   "Outgoing_Call_Request       ",
104   "Outgoing_Call_Reply         ",
105   "Outgoing_Call_Connected     ",
106   "Incoming_Call_Request       ",
107   "Incoming_Call_Reply         ",
108   "Incoming_Call_Connected     ",
109   "Reserved                    ",
110   "Call_Disconnect_Notification",
111   "WAN_Error_Notify            ",
112   "Set_Link_Info               ",
113 };
114
115 static const char *calltype_short_str[NUM_CONTROL_CALL_TYPES+1] = {
116   "Unknown ",
117   "SCCRQ   ",
118   "SCCRP   ",
119   "SCCCN   ",
120   "StopCCN ",
121   "Reserved",
122   "Hello   ",
123   "OCRQ    ",
124   "OCRP    ",
125   "OCCN    ",
126   "ICRQ    ",
127   "ICRP    ",
128   "ICCN    ",
129   "Reserved",
130   "CDN     ",
131   "WEN     ",
132   "SLI     ",
133 };
134
135
136  static const char *control_msg="Control Message";
137  static const char *data_msg="Data    Message";
138
139
140 #define NUM_AUTH_TYPES  6
141 static const char *authen_types[NUM_AUTH_TYPES] = {
142   "Reserved",
143   "Textual username and password",
144   "PPP CHAP",
145   "PPP PAP",
146   "No Authentication",
147   "Microsoft CHAP Version 1",
148 };
149
150 #define  CONTROL_MESSAGE  0
151 #define  RESULT_ERROR_CODE 1
152 #define  PROTOCOL_VERSION  2
153 #define  FRAMING_CAPABIlITIES 3
154 #define  BEARER_CAPABIlITIES 4
155 #define  TIE_BREAKER 5
156 #define  FIRMWARE_REVISION 6
157 #define  HOST_NAME 7
158 #define  VENDOR_NAME 8
159 #define  ASSIGNED_TUNNEL_ID 9
160 #define  RECEIVE_WINDOW_SIZE 10
161 #define  CHALLENGE 11
162 #define  CAUSE_CODE 12 
163 #define  CHALLENGE_RESPONSE 13
164 #define  ASSIGNED_SESSION 14
165 #define  CALL_SERIAL_NUMBER 15
166 #define  MINIMUM_BPS 16
167 #define  MAXIMUM_BPS 17
168 #define  BEARER_TYPE 18
169 #define  FRAMING_TYPE 19
170 #define  UNKNOWN_MESSAGE 20
171 #define  CALLED_NUMBER 21
172 #define  CALLING_NUMBER 22
173 #define  SUB_ADDRESS 23
174 #define  TX_CONNECT_SPEED 24
175 #define  PHYSICAL_CHANNEL 25
176 #define  INITIAL_RECEIVED_LCP 26
177 #define  LAST_SEND_LCP_CONFREQ 27
178 #define  LAST_RECEIVED_LCP_CONFREQ 28
179 #define  PROXY_AUTHEN_TYPE 29
180 #define  PROXY_AUTHEN_NAME 30
181 #define  PROXY_AUTHEN_CHALLENGE 31
182 #define  PROXY_AUTHEN_ID 32
183 #define  PROXY_AUTHEN_RESPONSE 33
184 #define  CALL_STATUS_AVPS 34
185 #define  ACCM 35
186 #define  UNOWN_MESSAGE_36
187 #define  PRIVATE_GROUP_ID 37
188 #define  RX_CONNECT_SPEED 38
189 #define  SEQUENCING_REQUIRED 39
190
191 #define NUM_AVP_TYPES  40
192 static const char *avptypestr[NUM_AVP_TYPES] = {
193   "Control Message ",
194   "Result-Error Code ",
195   "Protocol Version ",
196   "Framing Capabilities ",
197   "Bearer Capabilities  ",
198   "Tie Breaker ",
199   "Firmware Revision ",
200   "Host Name ",
201   "Vendor Name ",
202   "Assigned Tunnel ID ",
203   "Receive Window Size ",
204   "Challlenge ",
205   "Cause Code ",
206   "Challenge Response ",
207   "Assigned Session ",
208   "Call Serial Number ",
209   "Minimun BPS ",
210   "Maximum bps ",
211   "Bearer Type ",
212   "Framing Type ",
213   "Unknown Message ",
214   "Called Number ",
215   "Calling Number ",
216   "Sub-Address ",
217   "Connect Speed ",
218   "Physical Channel ",
219   "Initial Received lcP ",
220   "Last Send LCP CONFREQ ",
221   "Last Received LCP CONFREQ ",
222   "Proxy Authen Type ",
223   "Proxy Authen Name ",
224   "Proxy Authen Challenge ",
225   "Proxy Authen ID ",
226   "Proxy Authen Response ",
227   "Call status AVPs ",
228   "ACCM ",
229   "Unknown Message ",
230   "Private group ID ",
231   "RxConnect Speed ",
232   "Sequencing Required ",
233 };
234
235
236 static gchar textbuffer[200];
237 void dissect_l2tp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
238 {
239   proto_tree *l2tp_tree, *l2tp_avp_tree;
240   proto_item *ti, *tf;
241   int rhcode;
242   u_char *tmp_ptr;                      /* temp pointer used during AVP decode */
243   u_char *ptr;                          /* pointer used during l2tp  decode */
244   int index = 2;                        /* keeps track of depth into the AVP */
245   unsigned short  ver;                  /* Version and more */
246   unsigned short  length;               /* Length field */
247   unsigned short  tid;                  /* Tunnel ID */
248   unsigned short  cid;                  /* Call ID */
249   unsigned short  Nr;                   /* Next recv */
250   unsigned short  Ns;                   /* Next sent */
251   unsigned short ver_len_hidden;
252   unsigned short vendor;
253   unsigned short avp_type;
254   unsigned short msg_type;
255   unsigned short avp_len;
256   unsigned short error_type;
257   unsigned short avp_ver;
258   unsigned short avp_rev;
259   unsigned short framing;
260   unsigned short firmware_rev;
261   unsigned short gen_type;
262   unsigned long long_type;
263   char  error_string[100];
264   char  message_string[200];
265
266   ptr =  (u_char * )pd;                 /* point to the frame */
267   ptr = ptr + offset;                   /* current offset into the decoded frame  */
268   memcpy(&ver,ptr,sizeof(unsigned short)); /* collect the version */
269   ver = htons(ver);
270   rhcode= 10;
271   Ns = Nr = 0;
272
273   if (LENGTH_BIT(ver)) {                /* length field included ? */
274       ptr += 2; index += 2;             /* skip ahead */
275       memcpy(&length,ptr,sizeof(unsigned short)); /* collect the length */
276       length = (htons(length));
277   }
278
279   memcpy(&tid,(ptr+=2),sizeof(unsigned short));  /* collect the tunnel id & call id */ 
280   memcpy(&cid,(ptr+=2),sizeof(unsigned short));
281   index += 4;
282   if (check_col(fd, COL_PROTOCOL))      /* build output for closed L2tp frame displayed  */
283         col_add_str(fd, COL_PROTOCOL, "L2TP"); 
284   if (check_col(fd, COL_INFO)) {
285         tid = htons(tid); cid = htons(cid); 
286
287         if (CONTROL_BIT(ver)) {
288             /* CONTROL MESSAGE */
289             tmp_ptr = ptr;
290
291               if ((LENGTH_BIT(ver))&&(length==12))              /* ZLB Message */
292                   sprintf(textbuffer,"%s - ZLB      (tunnel id=%d, session id=%d)",
293                           control_msg , tid ,cid);
294               else
295               {
296                 if (SEQUENCE_BIT(ver)) {
297                     tmp_ptr=tmp_ptr+4;
298                 }
299     
300                 tmp_ptr+=4;
301     
302                 memcpy(&avp_type,(tmp_ptr+=2),sizeof(unsigned short));
303                 avp_type=htons(avp_type);
304     
305                 if (avp_type == CONTROL_MESSAGE)
306                 {
307                     /* We print message type */
308                     memcpy(&msg_type,(tmp_ptr+=2),sizeof(unsigned short));
309                     msg_type=ntohs(msg_type);
310                     sprintf(textbuffer,"%s - %s (tunnel id=%d, session id=%d)",
311                             control_msg ,
312                             ((NUM_CONTROL_CALL_TYPES + 1 ) > msg_type) ?
313                             calltype_short_str[msg_type] : "Unknown",
314                             tid ,cid);
315                 }
316                 else
317                 {
318                     /*
319                      * This is not a control message.
320                      * We never pass here except in case of bad l2tp packet!
321                      */
322                     sprintf(textbuffer,"%s (tunnel id=%d, session id=%d)",
323                             control_msg ,  tid ,cid);
324     
325                 }
326               }
327         }
328         else {
329             /* DATA Message */
330                sprintf(textbuffer,"%s            (tunnel id=%d, session id=%d)",
331                        data_msg, tid ,cid);
332         }
333         col_add_fstr(fd,COL_INFO,textbuffer);
334   }
335   if (tree) {
336         ti = proto_tree_add_item(tree,proto_l2tp, offset, length , NULL);
337         l2tp_tree = proto_item_add_subtree(ti, ett_l2tp);
338         proto_tree_add_item_format(l2tp_tree,hf_l2tp_code, offset ,1,
339         rhcode, "Packet Type: %s Tunnel Id=%d Session Id=%d",( CONTROL_BIT(ver) ? control_msg : data_msg) ,tid,cid);
340         if (LENGTH_BIT(ver)) {
341                 proto_tree_add_item_format(l2tp_tree,hf_l2tp_code, (offset +=  2), 2,
342                 rhcode, "Length: %d ", length);
343         }
344         if (SEQUENCE_BIT(ver)) {
345                 memcpy(&Ns,(ptr+=2),sizeof(unsigned short));
346                 memcpy(&Nr,(ptr+=2),sizeof(unsigned short));
347                 index += 4;
348                 proto_tree_add_item_format(l2tp_tree,hf_l2tp_code, (offset +=  6 ), 4,
349                 rhcode, "Ns: %d Nr: %d ", htons(Ns), htons(Nr));
350         }
351         if ((LENGTH_BIT(ver))&&(length==12)) {
352             proto_tree_add_item_format(l2tp_tree,hf_l2tp_code,offset,1,rhcode,
353                                        "Zero Length Bit message");
354         }
355         if (!CONTROL_BIT(ver)) {  /* Data Messages so we are done */
356                  proto_tree_add_item_format(l2tp_tree,hf_l2tp_code, (offset +=  4) , (length - 12 )  , rhcode, "Data: ");
357                  return;
358          }
359
360         offset += 4;
361         while (index < length ) {    /* Process AVP's */
362                 tmp_ptr =  ptr;
363                 memcpy(&ver_len_hidden,(tmp_ptr+=2),sizeof(unsigned short));
364                 avp_len =  AVP_LENGTH(htons(ver_len_hidden));
365                 index += avp_len; /* track how far into the control msg */ 
366                 memcpy(&vendor,(tmp_ptr+=2),sizeof(unsigned short));
367                 memcpy(&avp_type,(tmp_ptr+=2),sizeof(unsigned short));
368                 avp_type=htons(avp_type);
369                 tf =  proto_tree_add_item_format(l2tp_tree,hf_l2tp_code, offset , avp_len,
370                                                  rhcode, "AVP Type  %s  ",  (NUM_AVP_TYPES > avp_type)
371                                                  ? avptypestr[avp_type] : "Unknown");
372                 l2tp_avp_tree = proto_item_add_subtree(tf,  ett_l2tp_avp);
373
374                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset , 1,
375                                            rhcode, " Mandatory:%s" , (MANDATORY_BIT(htons(ver_len_hidden))) ? "True" : "False" );
376                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset , 1,
377                                            rhcode, " Hidden:%s" , (HIDDEN_BIT(htons(ver_len_hidden))) ? "True" : "False" );
378                         proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, (offset + 1), 1,
379                                                    rhcode, " Length:%d" , avp_len );
380
381                         if (HIDDEN_BIT(htons(ver_len_hidden))) { /* don't try do display hidden */
382                                 ptr = ptr +  avp_len;
383                                 continue;
384                         }
385
386                         switch (avp_type) {
387
388                         case CONTROL_MESSAGE:
389                             memcpy(&msg_type,(tmp_ptr+=2),sizeof(unsigned short));
390                             msg_type=htons(msg_type);
391                             proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 2 ,
392                                                        rhcode, " Control Message Type: (%d)  %s", msg_type,
393                                                        ((NUM_CONTROL_CALL_TYPES + 1 ) > msg_type) ?
394                                                        calltypestr[msg_type] : "Unknown" );
395                             break;
396
397                         case RESULT_ERROR_CODE:
398                                 if ( avp_len >= 10 ) {
399                                         memcpy(&error_type,(tmp_ptr+=2),sizeof(unsigned short));
400                                         error_type=htons(error_type);
401                                         proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
402                                           2, rhcode,
403                                           " Error Type: %d",  error_type  );
404                         
405                                 }
406
407                                 if ( avp_len > 10 ) {
408                                         memset(error_string,'\0' ,sizeof(error_string));
409                                         tmp_ptr+=4;
410                                         strncpy(error_string,(tmp_ptr),(avp_len - 10));
411                                         proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 9, (avp_len - 10),
412                                           rhcode, " Error Message: %s",  error_string  );
413                                 }
414                                 break;
415
416                         case PROTOCOL_VERSION:
417                                 tmp_ptr+=2;
418                                 memcpy(&avp_ver,(tmp_ptr),sizeof(unsigned short));
419                                 memcpy(&avp_rev,(tmp_ptr),sizeof(unsigned short));
420                                 avp_ver=(htons(avp_ver));
421                                 avp_rev=(htons(avp_rev));
422                                 memcpy(&avp_rev,(tmp_ptr+=2),sizeof(unsigned short));
423                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 1,
424                                   rhcode, " Version: %d",  ((avp_ver&0xff00)>>8)  );
425                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 7, 1,
426                                   rhcode, " Revision: %d",  (avp_ver&0x00ff));
427                                 break;
428
429                         case FRAMING_CAPABIlITIES:
430                                 tmp_ptr+=2;
431                                 memcpy(&framing,(tmp_ptr+=2),sizeof(unsigned short));
432                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 4,
433                                   rhcode, " ASYNC FRAMING: %s" , (FRAMING_ASYNC(htons(framing))) ? "True" : "False" );  
434                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 4,
435                                   rhcode, " SYNC FRAMING: %s" , (FRAMING_SYNC(htons(framing))) ? "True" : "False" );  
436                                 break;
437
438                         case BEARER_CAPABIlITIES:
439                                 tmp_ptr+=2;
440                                 memcpy(&framing,(tmp_ptr+=2),sizeof(unsigned short));
441                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 4 ,
442                                   rhcode, " Analog Access: %s" , (FRAMING_ASYNC(htons(framing))) ? "True" : "False" );  
443                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 4,
444                                   rhcode, " Digital Access: %s" , (FRAMING_SYNC(htons(framing))) ? "True" : "False" );  
445                                 break;
446
447                         case TIE_BREAKER:
448                                 memcpy(&long_type,(tmp_ptr+=8),sizeof(unsigned long));
449                                 long_type = htonl(long_type);
450                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 1,
451                                   rhcode, " TIE_BREAKER %l 0x%x", long_type,long_type );
452                                 break;
453
454                         case FIRMWARE_REVISION:
455                                 memcpy(&firmware_rev,(tmp_ptr+=2),sizeof(unsigned short));
456                                 firmware_rev=htons(firmware_rev);
457                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 2,
458                                   rhcode, " Firmware Revision: %d 0x%x", firmware_rev,firmware_rev );
459                                 break;
460
461                         case HOST_NAME:
462                                 memset(error_string,'\0',sizeof(error_string));
463                                 strncpy(error_string,(tmp_ptr+=2),(avp_len - 6));
464                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 
465                                   (avp_len - 6), rhcode, " Host Name: %s",  error_string  );
466                                 break;
467
468                         case VENDOR_NAME:
469                                 memset(message_string,'\0' ,sizeof(message_string));
470                                 strncpy(message_string,(tmp_ptr+=2),(avp_len - 6));
471                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 
472                                   (avp_len - 6), rhcode, " Vendor Name: %s",  message_string  );
473                                 break;
474
475                         case ASSIGNED_TUNNEL_ID:
476                                 memcpy(&gen_type,(tmp_ptr+=2),sizeof(unsigned short));
477                                 gen_type=htons(gen_type);
478                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
479                                   2, rhcode, " Tunnel ID: %d",  gen_type  );
480                                 break;
481
482                         case RECEIVE_WINDOW_SIZE:
483                                 memcpy(&gen_type,(tmp_ptr+=2),sizeof(unsigned short));
484                                 gen_type=htons(gen_type);
485                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
486                                   2, rhcode, " Receive Window Size: %d",  gen_type  );
487                                 break;
488
489                         case CHALLENGE:
490                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
491                                   (avp_len - 6 ), rhcode, "  CHAP Challenge: ");
492                                 break;
493
494                         case CHALLENGE_RESPONSE:
495                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
496                                   (avp_len - 6 ), rhcode, "  CHAP Challenge Response: ");
497                                 break;
498
499                         case CAUSE_CODE:
500                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
501                                   1, rhcode, " Cause Code: ");
502                                 break;
503
504                         case ASSIGNED_SESSION:
505                                 memcpy(&gen_type,(tmp_ptr+=2),sizeof(unsigned short));
506                                 gen_type=htons(gen_type);
507                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
508                                   2, rhcode, " Assigned Session: %d",  gen_type  );
509                                 break;
510
511                         case CALL_SERIAL_NUMBER:
512                                 memcpy(&gen_type,(tmp_ptr+=2),sizeof(unsigned short));
513                                 gen_type=htons(gen_type);
514                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
515                                   4, rhcode, " Call Serial Number: %d",  gen_type  );
516                                 break;
517
518                         case MINIMUM_BPS:
519                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
520                                   4, rhcode, " Minimum BPS: ");
521                                 break;
522
523                         case MAXIMUM_BPS:
524                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
525                                   4, rhcode, " Maximum BPS ");
526                                 break;
527
528                         case BEARER_TYPE:
529                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
530                                   4, rhcode, " Bearer Type: ");
531                                 break;
532
533                         case FRAMING_TYPE:
534                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
535                                   4, rhcode, " Framing Type: ");
536                                 break;
537
538                         case UNKNOWN_MESSAGE:
539                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
540                                   1, rhcode, " Unknown Message: ");
541                                 break;
542
543                         case CALLED_NUMBER:
544                                 memset(message_string,'\0' ,sizeof(message_string));
545                                 strncpy(message_string,(tmp_ptr+=2),(avp_len - 6));
546                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 
547                                   (avp_len - 6), rhcode, " Called Number: %s",  message_string  );
548                                 break;
549
550                         case CALLING_NUMBER:
551                                 memset(message_string,'\0' ,sizeof(message_string));
552                                 strncpy(message_string,(tmp_ptr+=2),(avp_len - 6));
553                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 
554                                   (avp_len - 6), rhcode, " Calling Number: %s",  message_string  );
555                                 break;
556
557                         case SUB_ADDRESS:
558                                 memset(message_string,'\0' ,sizeof(message_string));
559                                 strncpy(message_string,(tmp_ptr+=2),(avp_len - 6));
560                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code, offset + 6, 
561                                   (avp_len - 6), rhcode, " Sub-Address: %s",  message_string  );
562                                 break;
563
564                         case TX_CONNECT_SPEED:
565                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
566                                   4, rhcode, " Connect Speed: ");
567                                 break;
568
569                         case PHYSICAL_CHANNEL:
570                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
571                                   4, rhcode, " Physical Channel: ");
572                                 break;
573
574                         case INITIAL_RECEIVED_LCP:
575                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
576                                   (avp_len - 6 ), rhcode, " Initial LCP Conf REQ: ");
577                                 break;
578
579                         case LAST_SEND_LCP_CONFREQ:
580                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
581                                   (avp_len - 6 ), rhcode, " Last Sent LCP Conf REQ: ");
582                                 break;
583
584                         case LAST_RECEIVED_LCP_CONFREQ:
585                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
586                                   (avp_len - 6 ), rhcode, " Last Received LCP Conf REQ: ");
587                                 break;
588
589                         case PROXY_AUTHEN_TYPE:
590                                 memcpy(&msg_type,(tmp_ptr+=2),sizeof(unsigned short));
591                                 msg_type=htons(msg_type);
592                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
593                                   1, rhcode, " Proxy Authen Type: %s ", authen_types[msg_type] );
594                                 break;
595
596                         case PROXY_AUTHEN_NAME:
597                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
598                                   (avp_len - 6 ), rhcode, " Proxy Authen Name: ");
599                                 break;
600
601                         case PROXY_AUTHEN_CHALLENGE:
602                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
603                                   (avp_len - 6 ), rhcode, " Proxy Authen Challenge: ");
604                                 break;
605
606                         case PROXY_AUTHEN_ID:
607                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
608                                   2, rhcode, " Paorx Authen ID: ");
609                                 break;
610
611                         case PROXY_AUTHEN_RESPONSE:
612                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
613                                   (avp_len - 6 ), rhcode, " Proxy Authen Response: ");
614                                 break;
615
616                         case CALL_STATUS_AVPS:
617                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
618                                   4, rhcode, "  CRC Errors: ");
619                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 10,
620                                   4, rhcode, "  Framing Errors: ");
621                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 14,
622                                   4, rhcode, "  Hardware Overruns: ");
623                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 18,
624                                   4, rhcode, "  Buffer Overruns: ");
625                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 23,
626                                   4, rhcode, "  Time-out Errors: ");
627                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 26,
628                                   4, rhcode, "  Alignment Errors: ");
629                                 break;
630
631                         case ACCM:
632                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
633                                   2, rhcode, " Reserve Quantity: ");
634                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 8,
635                                   4, rhcode, " Send ACCM: ");
636                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 12,
637                                   4, rhcode, " Recv ACCM: ");
638                                 break;
639
640                         case PRIVATE_GROUP_ID:
641                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
642                                   1, rhcode, " Private Group ID: ");
643                                 break;
644
645                         case RX_CONNECT_SPEED:
646                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset + 6,
647                                   4, rhcode, " RX Connect Speed: ");
648                                 break;
649
650                         case SEQUENCING_REQUIRED:
651                                 proto_tree_add_item_format(l2tp_avp_tree,hf_l2tp_code,offset ,
652                                   1, rhcode, " Sequencing Required: ");
653                                 break;
654                         }
655
656                         /* printf("Avp Decode avp_len= %d index= %d length= %d %x\n ",avp_len,
657                            index,length,length); */
658
659                         ptr = ptr +  avp_len;
660                         offset += avp_len;
661                 }
662         }
663 }
664
665 /* registration with the filtering engine */
666 void
667 proto_register_l2tp(void)
668 {
669         static hf_register_info hf[] = {
670                 { &hf_l2tp_code,
671                 { "Code","l2tp.code", FT_UINT8, BASE_DEC, NULL, 0x0,
672                         "" }},
673
674                 { &hf_l2tp_id,
675                 { "Identifier", "l2tp.id", FT_UINT8, BASE_DEC, NULL, 0x0,
676                         "" }},
677
678                 { &hf_l2tp_length,
679                 { "Length","l2tp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
680                         "" }}
681         };
682
683         static gint *ett[] = {
684                 &ett_l2tp,
685                 &ett_l2tp_avp,
686         };
687
688         proto_l2tp = proto_register_protocol ("L2TP Protocol", "l2tp");
689         proto_register_field_array(proto_l2tp, hf, array_length(hf));
690         proto_register_subtree_array(ett, array_length(ett));
691 }