Change from Andreas Sikkema to change the "old" and "new" members of the
[obnox/wireshark/wip.git] / packet-msproxy.c
1 /* packet-msproxy.c
2  * Routines for Microsoft Proxy packet dissection
3  * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
4  *
5  * $Id: packet-msproxy.c,v 1.11 2000/08/21 18:36:34 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@zing.org>
9  * Copyright 1998 Gerald Combs
10  *
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  * This was derived from the dante socks implimentation source code. 
28  * Most of the information came from common.h and msproxy_clientprotocol.c
29  *
30  * See http://www.inet.no/dante for more information 
31  *
32  */
33
34 /************************************************************************
35  *                                                                      *
36  *  Notes: These are possible command values. User input is welcome     *
37  *                                                                      *
38  *  Command = 0x040a - Remote host closed connection (maybe ?? )        *
39  *  Command = 0x0411 - Remote host closed connection                    *
40  *  Command = 0x0413 - Local host closed connection or SYN worked       *
41  *                                                                      *
42  ************************************************************************/
43
44
45
46
47 #ifdef HAVE_CONFIG_H
48 # include "config.h"
49 #endif
50
51 #ifdef HAVE_SYS_TYPES_H
52 # include <sys/types.h>
53 #endif
54
55 #ifdef HAVE_NETINET_IN_H
56 # include <netinet/in.h>
57 #endif
58
59 #include <stdio.h>
60 #include <string.h>
61 #include <glib.h>
62
63 #ifdef NEED_SNPRINTF_H
64 # include "snprintf.h"
65 #endif
66
67 #include "packet.h"
68 #include "resolv.h"
69 #include "globals.h"
70 #include "alignment.h"
71 #include "conversation.h"
72
73 #include "packet-tcp.h"
74 #include "packet-udp.h"
75
76 #define CHECK_PACKET_LENGTH(X) if (!BYTES_ARE_IN_FRAME(offset, X)){  \
77         proto_tree_add_text(tree, NullTVB, offset, 0, "****FRAME TOO SHORT***"); return;}
78
79 extern void udp_hash_add(guint16 proto,
80         void (*dissect)(const u_char *, int, frame_data *, proto_tree *));
81
82
83 static int proto_msproxy = -1;
84
85 static int ett_msproxy = -1;
86 static int ett_msproxy_name = -1;
87
88 static int hf_msproxy_cmd = -1;
89 static int hf_msproxy_clntport = -1;
90
91 static int hf_msproxy_dstaddr = -1;
92
93 static int hf_msproxy_srcport = -1;
94 static int hf_msproxy_dstport = -1;
95 static int hf_msproxy_serverport = -1;
96 static int hf_msproxy_serveraddr = -1;
97 static int hf_msproxy_bindport = -1;
98 static int hf_msproxy_bindaddr = -1;
99 static int hf_msproxy_boundport = -1;
100 static int hf_msproxy_bind_id = -1;
101 static int hf_msproxy_resolvaddr = -1;
102
103 static int hf_msproxy_server_int_addr = -1;
104 static int hf_msproxy_server_int_port = -1;
105 static int hf_msproxy_server_ext_addr = -1;
106 static int hf_msproxy_server_ext_port = -1;
107
108
109 #define UDP_PORT_MSPROXY 1745
110
111 #define N_MSPROXY_HELLO                 0x05    /* packet 1 from client */
112 #define N_MSPROXY_ACK                   0x10    /* packet 1 from server */
113 #define N_MSPROXY_USERINFO_ACK          0x04    /* packet 2 from server */
114 #define N_MSPROXY_AUTH                  0x47    /* packet 3 from client */
115 #define N_MSPROXY_RESOLVE               0x07    /* Resolve request      */
116
117
118 /*$$$ 0x0500 was dante value, I see 0x05ff and 0x0500 */
119
120 #define MSPROXY_HELLO                   0x0500  
121 #define MSPROXY_HELLO_2                 0x05ff  
122
123 #define MSPROXY_HELLO_ACK               0x1000  
124
125 #define MSPROXY_USERINFO                0x1000  
126 #define MSPROXY_USERINFO_ACK            0x0400  
127
128 #define MSPROXY_AUTH                    0x4700  
129 #define MSPROXY_AUTH_1_ACK              0x4714
130 #define MSPROXY_AUTH_2                  0x4701
131 #define MSPROXY_AUTH_2_ACK              0x4715
132 #define MSPROXY_AUTH_2_ACK2             0x4716
133
134 #define MSPROXY_RESOLVE                 0x070d  
135 #define MSPROXY_RESOLVE_ACK             0x070f
136
137 #define MSPROXY_BIND                    0x0704  
138 #define MSPROXY_BIND_ACK                0x0706  
139
140 #define MSPROXY_TCP_BIND                0x0707
141 #define MSPROXY_TCP_BIND_ACK            0x0708  
142
143 #define MSPROXY_LISTEN                  0x0406  
144
145 #define MSPROXY_BINDINFO                0x0709
146
147 #define MSPROXY_BINDINFO_ACK            0x070a  
148
149 #define MSPROXY_CONNECT                 0x071e  
150 #define MSPROXY_CONNECT_ACK             0x0703  
151
152 #define MSPROXY_UDPASSOCIATE            0x0705  
153 #define MSPROXY_UDPASSOCIATE_ACK        0x0706  
154
155 #define MSPROXY_UDP_BIND_REQ            0x070b
156
157 #define MSPROXY_CONNECTED               0x042c  
158 #define MSPROXY_SESSIONEND              0x251e                  
159
160 #define MSPROXY_BIND_AUTHFAILED         0x0804  
161 #define MSPROXY_CONNECT_AUTHFAILED      0x081e  
162 #define MSPROXY_CONNREFUSED             0x4             /* low 12 bits seem to vary.    */
163
164 #define FROM_SERVER 1                   /* direction of packet data for get_msproxy_cmd_name */
165 #define FROM_CLIENT 0
166
167
168
169
170 /*$$$ should this be the same as redirect_entry_t ?? */
171 /*  then the add_conversation could just copy the structure */
172 /* using the same allocation (instance  for you object guys)    */
173 /* wouldn't work because there may be multiple child conversations */
174 /* from the same MSProxy conversation */
175
176 typedef struct {
177         guint32 dst_addr;
178         guint32 clnt_port;
179         guint32 dst_port;
180         guint32 server_int_port;
181         int     proto;
182 }hash_entry_t;
183
184
185 /************** conversation hash stuff ***************/
186
187 #define hash_init_count 20
188 #define hash_val_length (sizeof(hash_entry_t))
189
190 static GMemChunk *vals = NULL;
191
192 typedef struct {
193         guint32 remote_addr;
194         guint32 clnt_port;
195         guint32 server_int_port;
196         guint32 remote_port;
197         int     proto;
198 }redirect_entry_t;
199
200
201 /************** negotiated conversation hash stuff ***************/
202
203 #define redirect_init_count 20
204 #define redirect_val_length (sizeof(redirect_entry_t))
205
206 static GMemChunk *redirect_vals = NULL;
207
208
209 static guint32 last_row= 0;     /* used to see if packet is new */
210
211 static void msproxy_sub_dissector( const u_char *pd, int offset, frame_data *fd,
212                 proto_tree *tree) {
213
214 /* Conversation dissector called from TCP or UDP dissector. Decode and  */
215 /* display the socks header, the pass the rest of the data to the tcp   */
216 /* or udp port decode routine to  handle the payload.                   */
217
218         guint32 *ptr;
219         redirect_entry_t *redirect_info;
220         conversation_t *conversation;
221         proto_tree      *msp_tree;
222         proto_item      *ti;
223         
224         conversation = find_conversation( &pi.src, &pi.dst, pi.ptype,
225                 pi.srcport, pi.destport);
226
227         g_assert( conversation);        /* should always find a conversation */
228
229         redirect_info = (redirect_entry_t*)conversation->data;
230
231         if (check_col(fd, COL_PROTOCOL))
232                 col_add_str(fd, COL_PROTOCOL, "MS Proxy");
233
234         if (check_col(fd, COL_INFO))
235                 col_add_fstr(fd, COL_INFO, "%s", 
236                         (( redirect_info->proto == PT_TCP) ? "TCP stream" :
237                          "UDP packets"));
238
239         if ( tree) {
240                 ti = proto_tree_add_item( tree, proto_msproxy, NullTVB, offset, 0,
241                         FALSE );
242
243                 msp_tree = proto_item_add_subtree(ti, ett_msproxy);
244
245                 proto_tree_add_uint( msp_tree, hf_msproxy_dstport, NullTVB,
246                         offset, 0, redirect_info->remote_port);
247
248                 proto_tree_add_ipv4( msp_tree, hf_msproxy_dstaddr, NullTVB, offset, 0,
249                         redirect_info->remote_addr);
250                         
251         }
252
253 /* set pi src/dst port and call the udp sub-dissector lookup */
254
255         if ( pi.srcport == redirect_info->clnt_port)            
256                 ptr = &pi.destport;
257         else
258                 ptr = &pi.srcport;
259
260         *ptr = redirect_info->remote_port;
261         
262         if ( redirect_info->proto == PT_TCP)
263                 decode_tcp_ports( pd, offset, fd, tree, pi.srcport, pi.destport);
264         else
265                 decode_udp_ports( pd, offset, fd, tree, pi.srcport, pi.destport);
266  
267         *ptr = redirect_info->server_int_port;
268 }
269
270
271
272 static void add_msproxy_conversation( hash_entry_t *hash_info){
273
274 /* check to see if a conversation already exists, if it does assume     */
275 /* it's our conversation and quit. Otherwise create a new conversation. */
276 /* Load the conversation dissector to our  dissector and load the       */
277 /* conversation data structure with the info needed to call the TCP or  */
278 /* UDP port decoder.                                                    */
279
280 /* NOTE: Currently this assume that the conversation will be created    */
281 /*      during a packet from the server.  If that changes, the pi.src   */
282 /*      and pi.dst will not be correct and this routine will have to    */
283 /*      change.                                                         */
284
285         redirect_entry_t *new_conv_info;
286         
287         conversation_t *conversation = find_conversation( &pi.src, &pi.dst, 
288                 hash_info->proto, hash_info->server_int_port,
289                 hash_info->clnt_port);
290
291         if ( conversation)
292                 return;
293
294         new_conv_info = g_mem_chunk_alloc(redirect_vals);
295         conversation = conversation_new( &pi.src, &pi.dst, hash_info->proto,
296                 hash_info->server_int_port, hash_info->clnt_port, new_conv_info);
297
298         g_assert( new_conv_info);
299         g_assert( conversation);
300
301         new_conv_info->remote_addr = hash_info->dst_addr;
302         new_conv_info->clnt_port = hash_info->clnt_port;
303         new_conv_info->remote_port = hash_info->dst_port;
304         new_conv_info->server_int_port = hash_info->server_int_port;
305         new_conv_info->proto = hash_info->proto;
306         
307         old_conversation_set_dissector(conversation, msproxy_sub_dissector);
308 }
309
310
311
312 static int display_application_name(const u_char *pd, int offset,
313         frame_data *fd, proto_tree *tree) {
314         
315 /* display the application name in the proto tree.                      */
316
317 /* NOTE: this routine assumes that the tree pointer is valid (not NULL) */      
318
319         char temp[255];
320         
321         if (!IS_DATA_IN_FRAME(offset)){ 
322                 proto_tree_add_text(tree, NullTVB, offset, 0, "****FRAME TOO SHORT***");
323                 return 0;
324         }
325         
326         strncpy( temp, &pd[ offset], MIN( 255, END_OF_FRAME));
327         temp[ MIN( 255, END_OF_FRAME)] = 0;                     
328         proto_tree_add_text( tree, NullTVB, offset, strlen(temp), "Application: %s", temp);
329
330         return strlen(temp);
331
332 }
333
334
335 static char *get_msproxy_cmd_name( int cmd, int direction) {
336
337 /* return the command name string for cmd */
338
339         switch (cmd){
340                 case MSPROXY_HELLO_2:
341                 case MSPROXY_HELLO:             return "Hello"; 
342
343 /* MSPROXY_HELLO_ACK & MSPROXY_USERINFO have the same value (0x1000).   */
344 /* So use the direction flag to determine which to use.                 */
345
346                 case MSPROXY_USERINFO:          
347                         if ( direction == FROM_SERVER)
348                                 return "Hello Acknowledge";
349                         else
350                                 return "User Info";
351                 case MSPROXY_USERINFO_ACK:      return "User Info Acknowledge";
352                 case MSPROXY_AUTH:              return "Authentication";
353                 case MSPROXY_AUTH_1_ACK:        return "Authentication Acknowledge";
354                 case MSPROXY_AUTH_2:            return "Authentication 2";
355                 case MSPROXY_AUTH_2_ACK:        return "Authentication 2 Acknowledge";
356                 case MSPROXY_RESOLVE:           return "Resolve";
357                 case MSPROXY_RESOLVE_ACK:       return "Resolve Acknowledge";
358                 case MSPROXY_BIND:              return "Bind";
359                 case MSPROXY_TCP_BIND:          return "TCP Bind";
360                 case MSPROXY_TCP_BIND_ACK:      return "TCP Bind Acknowledge";
361                 case MSPROXY_LISTEN:            return "Listen";
362                 case MSPROXY_BINDINFO:          return "Bind Info";
363                 case MSPROXY_BINDINFO_ACK:      return "Bind Info Acknowledge";
364                 case MSPROXY_CONNECT:           return "Connect";
365                 case MSPROXY_CONNECT_ACK:       return "Connect Acknowledge";
366                 case MSPROXY_UDPASSOCIATE:      return "UDP Associate";
367                 case MSPROXY_UDP_BIND_REQ:      return "UDP Bind";
368                 case MSPROXY_UDPASSOCIATE_ACK:  return "Bind or Associate Acknowledge";
369                 case MSPROXY_CONNECTED:         return "Connected";
370                 case MSPROXY_SESSIONEND:        return "Session End";
371
372                 default:                        return "Unknown";                               
373         }
374 }
375
376
377
378 static void dissect_user_info_2(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
379
380 /* decode the user, application, computer name  */
381
382
383         char str[ 255];
384
385         if ( tree) {    
386                 strncpy( str, &pd[ offset], MIN( 255, END_OF_FRAME));
387                 str[ MIN( 255, END_OF_FRAME)] = 0;                      
388         
389                 proto_tree_add_text( tree, NullTVB, offset, strlen( str) + 1,
390                         "User name: %s", str); 
391                 offset += strlen( str) + 2;
392         
393                 strncpy( str, &pd[ offset], MIN( 255, END_OF_FRAME));
394                 str[ MIN( 255, END_OF_FRAME)] = 0;                      
395         
396                 proto_tree_add_text( tree, NullTVB, offset, strlen( str) + 1,
397                         "Application name: %s", str); 
398                 offset += strlen( str) + 1;
399         
400                 strncpy( str, &pd[ offset], MIN( 255, END_OF_FRAME));
401                 str[ MIN( 255, END_OF_FRAME)] = 0;                      
402         
403                 proto_tree_add_text( tree, NullTVB, offset, strlen( str) + 1,
404                         "Client computer name: %s", str); 
405         }
406 }
407
408
409
410 static void dissect_msproxy_request_1(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
411
412 /* decode the request _1 structure  */
413
414
415         offset += 180;
416
417         dissect_user_info_2( pd, 262, fd, tree);        
418
419 }
420
421
422
423 static void dissect_bind(const u_char *pd, int offset, frame_data *fd,
424          proto_tree *tree, hash_entry_t *conv_info) {
425
426 /* decode the bind request   */
427
428         offset += 18;
429
430         CHECK_PACKET_LENGTH( 4);
431         if ( tree)
432                 proto_tree_add_ipv4( tree, hf_msproxy_bindaddr, NullTVB, offset, 4,
433                         GWORD( pd, offset));
434         offset += 4;
435
436         CHECK_PACKET_LENGTH( 2);
437         if ( tree)
438                 proto_tree_add_uint( tree, hf_msproxy_bindport, NullTVB, offset, 2,
439                          pntohs( &pd[ offset]));
440         offset += 6;
441                         
442         CHECK_PACKET_LENGTH( 2);
443         if ( tree)
444                 proto_tree_add_uint( tree, hf_msproxy_clntport, NullTVB, offset, 2,
445                          pntohs( &pd[ offset]));
446         offset += 2;
447                         
448         conv_info->clnt_port = pntohs( &pd[ offset]); 
449         offset += 6;
450
451         if ( tree){
452                 CHECK_PACKET_LENGTH( 2);
453                 proto_tree_add_uint( tree, hf_msproxy_boundport, NullTVB, offset, 2,
454                         pntohs( &pd[ offset]));
455
456                 offset += 82;
457                 display_application_name( pd, offset, fd, tree);
458         }
459 }
460
461
462
463 static void dissect_auth(const u_char *pd, int offset,
464         frame_data *fd, proto_tree *tree) {
465
466 /* decode the authorization request  */
467
468         char temp[255];
469
470         if ( tree) {
471                 offset += 134;
472
473                 strncpy( temp, &pd[ offset], 7);
474                 temp[ 7] = 0;                   
475                 proto_tree_add_text( tree, NullTVB, offset, 7, "NTLMSSP signature: %s",
476                         temp);
477                 offset += 7;
478         }
479 }
480
481
482
483 static void dissect_tcp_bind(const u_char *pd, int offset,
484         frame_data *fd, proto_tree *tree, hash_entry_t *conv_info) {
485
486 /* decode the bind packet. Set the protocol type in the conversation    */
487 /* information so the bind_info can use it to create the payload        */
488 /* dissector.                                                           */
489
490
491         conv_info->proto = PT_TCP;
492
493         if ( tree) {
494                 offset += 6;
495
496                 CHECK_PACKET_LENGTH( 4);
497                 proto_tree_add_uint( tree, hf_msproxy_bind_id, NullTVB, offset, 4, pntohl( &pd[ offset]));
498                 offset += 16;
499
500                 CHECK_PACKET_LENGTH( 2);
501                 proto_tree_add_uint( tree, hf_msproxy_boundport, NullTVB, offset, 2,
502                         pntohs( &pd[ offset]));
503
504                 offset += 96;
505                 display_application_name( pd, offset, fd, tree);
506         }
507 }
508
509
510 static void dissect_request_connect(const u_char *pd, int offset, frame_data *fd,
511                 proto_tree *tree, hash_entry_t *conv_info) {
512
513 /* decode the connect request, display  */
514
515         conv_info->proto = PT_TCP;
516
517         offset += 20;
518
519         CHECK_PACKET_LENGTH( 2);
520         if ( tree)
521                 proto_tree_add_uint( tree, hf_msproxy_dstport, NullTVB, offset, 2,
522                         pntohs( &pd[ offset]));
523                 
524         conv_info->dst_port = pntohs( &pd[ offset]);
525         offset += 2;
526
527         CHECK_PACKET_LENGTH( 4);
528         if ( tree)
529                 proto_tree_add_ipv4( tree, hf_msproxy_dstaddr, NullTVB, offset, 4,
530                         GWORD( pd, offset));
531                         
532         memcpy( &conv_info->dst_addr, &pd[ offset], sizeof( guint32));
533
534         offset += 12;
535
536         CHECK_PACKET_LENGTH( 2);
537         conv_info->clnt_port = pntohs( &pd[ offset]);
538
539         if ( tree){
540                 proto_tree_add_uint( tree, hf_msproxy_clntport, NullTVB, offset, 2,
541                         pntohs( &pd[ offset]));
542         
543                 offset += 84;
544
545                 display_application_name( pd, offset, fd, tree);
546         }
547 }
548
549
550 static void dissect_bind_info_ack(const u_char *pd, int offset, frame_data *fd,
551         proto_tree *tree, hash_entry_t *conv_info) {
552
553 /* decode the client bind info ack  */
554
555
556         if ( tree){
557                 offset += 6;
558
559                 CHECK_PACKET_LENGTH( 4);
560                 proto_tree_add_uint( tree, hf_msproxy_bind_id, NullTVB, offset, 4, pntohl( &pd[ offset]));
561                 offset += 14;
562
563                 CHECK_PACKET_LENGTH( 2);
564                 proto_tree_add_uint( tree, hf_msproxy_dstport, NullTVB, offset, 2,
565                         pntohs( &pd[ offset]));
566                 offset += 2;
567
568                 CHECK_PACKET_LENGTH( 4);
569                 proto_tree_add_ipv4( tree, hf_msproxy_dstaddr, NullTVB, offset, 4,
570                         GWORD( pd, offset));
571                 offset += 12;
572
573                 CHECK_PACKET_LENGTH( 2);
574                 proto_tree_add_uint( tree, hf_msproxy_server_int_port, NullTVB, offset,
575                         2, pntohs( &pd[ offset]));
576                 offset += 4;
577
578                 CHECK_PACKET_LENGTH( 2);
579                 proto_tree_add_uint( tree, hf_msproxy_server_ext_port, NullTVB, offset,
580                         2, pntohs( &pd[ offset]));
581                 offset += 2;
582
583                 CHECK_PACKET_LENGTH( 4);
584                 proto_tree_add_ipv4( tree, hf_msproxy_server_ext_addr, NullTVB, offset,
585                         4, GWORD( pd, offset));
586
587                 offset += 78;
588                 display_application_name( pd, offset, fd, tree);
589         }
590 }
591
592
593 static void dissect_request_resolve(const u_char *pd, int offset,
594         frame_data *fd, proto_tree *tree) {
595
596 /* dissect the request resolve structure */
597 /* display a string with a length, characters encoding */
598 /* they are displayed under a tree with the name in Label variable */
599 /* return the length of the string and the length byte */
600
601         proto_tree      *name_tree;
602         proto_item      *ti;
603
604         char temp[ 256];
605         int length = GBYTE( pd, offset);
606
607         if ( tree){
608                 strncpy( temp, &pd[ offset + 18], length);
609                 temp[ length ] = 0;
610   
611                 ti = proto_tree_add_text(tree, NullTVB, offset, length + 1,
612                         "Host Name: %s", temp);
613
614                 name_tree = proto_item_add_subtree(ti, ett_msproxy_name);
615
616                 proto_tree_add_text( name_tree, NullTVB, offset, 1, "Length: %d", length);
617
618                 ++offset;
619                 offset += 17;
620
621                 proto_tree_add_text( name_tree, NullTVB, offset, length, "String: %s",
622                         temp);
623         }
624 }       
625
626
627
628 static void dissect_udp_bind(const u_char *pd, int offset,
629         frame_data *fd, proto_tree *tree, hash_entry_t *conv_info) {
630
631 /* Dissect the udp bind request.  Load the protocol id (PT_UDP) and the */
632 /* remote address so bind_info can use it to create conversation        */
633 /* dissector.                                                           */
634
635         conv_info->proto = PT_UDP;
636
637
638         offset += 8;
639
640         CHECK_PACKET_LENGTH( 4);
641         if ( tree)
642                 proto_tree_add_uint( tree, hf_msproxy_bind_id, NullTVB, offset, 4, pntohl( &pd[ offset]));
643         offset += 12;
644
645
646         CHECK_PACKET_LENGTH( 2);
647         if ( tree)
648                 proto_tree_add_uint( tree, hf_msproxy_dstport, NullTVB, offset, 2,
649                         pntohs( &pd[ offset]));
650         offset += 2;
651
652         CHECK_PACKET_LENGTH( 4);
653         if ( tree) 
654                 proto_tree_add_ipv4( tree, hf_msproxy_dstaddr, NullTVB, offset, 4,
655                         GWORD( pd, offset));
656
657         offset += 96;
658         
659         if ( tree)
660                 display_application_name( pd, offset, fd, tree);
661 }       
662  
663
664 static void dissect_udp_assoc(const u_char *pd, int offset,
665         frame_data *fd, proto_tree *tree, hash_entry_t *conv_info) {
666
667 /* dissect the udp associate request. And load client port into         */
668 /* conversation data structure for later.                               */
669
670
671         offset += 28;
672
673         CHECK_PACKET_LENGTH( 2);
674         if ( tree) 
675                 proto_tree_add_uint( tree, hf_msproxy_clntport, NullTVB, offset, 2,
676                         pntohs( &pd[ offset]));
677
678         conv_info->clnt_port = pntohs( &pd[ offset]); 
679
680         offset += 90;
681
682         if ( tree) 
683                 display_application_name( pd, offset, fd, tree);
684         
685
686 }       
687  
688
689 static void dissect_msproxy_request(const u_char *pd, int offset, frame_data *fd,
690         proto_tree *tree, hash_entry_t *conv_info) {
691
692         int cmd;
693         char temp[ 255];
694
695         if ( tree) {
696                 CHECK_PACKET_LENGTH( 4);
697                 proto_tree_add_text( tree, NullTVB, offset, 4, "Client id: 0x%0x", 
698                         GWORD( pd, offset));
699                 offset += 4;
700         
701                 CHECK_PACKET_LENGTH( 4);
702                 proto_tree_add_text( tree, NullTVB, offset, 4, "Version: 0x%04x", 
703                         GWORD( pd, offset));
704                 offset += 4;
705
706                 CHECK_PACKET_LENGTH( 4);
707                 proto_tree_add_text( tree, NullTVB, offset, 4, "Server id: 0x%0x", 
708                         GWORD( pd, offset));
709                 offset += 4;
710
711                 CHECK_PACKET_LENGTH( 2);
712                 proto_tree_add_text( tree, NullTVB, offset, 1, "Server ack: %u", 
713                         GBYTE( pd, offset));
714                 offset += 4;
715
716                 CHECK_PACKET_LENGTH( 1);
717                 proto_tree_add_text( tree, NullTVB, offset, 1, "Sequence Number: %u", 
718                         GBYTE( pd, offset));
719                 offset += 8;
720
721                 CHECK_PACKET_LENGTH( 4);
722                 strncpy( temp, &pd[ offset], 4);
723                 temp[ 4] = 0;                   
724                 proto_tree_add_text( tree, NullTVB, offset, 4, "RWSP signature: %s", temp);
725                 offset += 12;
726         } 
727         else                    /* no tree */
728                 offset += 36;
729
730         CHECK_PACKET_LENGTH( 1);
731         cmd = pntohs( &pd[offset]);
732
733         if ( tree)
734                 proto_tree_add_uint_format( tree, hf_msproxy_cmd, NullTVB, offset, 2,
735                         cmd, "Command: 0x%02x (%s)", cmd, 
736                         get_msproxy_cmd_name( cmd, FROM_CLIENT));
737
738         offset += 2;
739
740         switch (cmd){ 
741                 case MSPROXY_AUTH:
742                         dissect_auth( pd, offset, fd, tree);
743                         break;
744                         
745                 case MSPROXY_BIND:
746                         dissect_bind( pd, offset, fd, tree, conv_info);
747
748                         break;
749                 case  MSPROXY_UDP_BIND_REQ:
750                         dissect_udp_bind( pd, offset, fd, tree, conv_info);
751                         break;
752         
753                 case MSPROXY_AUTH_2:    /*$$ this is probably wrong place for this */
754                 case MSPROXY_TCP_BIND:
755                         dissect_tcp_bind( pd, offset, fd, tree, conv_info);
756                         break;
757         
758                 case MSPROXY_RESOLVE:
759                         dissect_request_resolve( pd, offset, fd, tree);
760                         break;
761         
762                 case MSPROXY_CONNECT:
763                 case MSPROXY_LISTEN:
764                         dissect_request_connect( pd, offset, fd, tree,
765                                 conv_info);
766                         break;
767         
768                 case MSPROXY_BINDINFO_ACK:
769                         dissect_bind_info_ack( pd, offset, fd, tree, conv_info);
770                         break;
771
772                 case MSPROXY_HELLO:
773                 case MSPROXY_HELLO_2:
774                         dissect_msproxy_request_1( pd, offset, fd, tree);
775                         break;
776
777                 case  MSPROXY_UDPASSOCIATE:
778                         dissect_udp_assoc( pd, offset, fd, tree, conv_info);
779                         break;
780                 default:
781                         if ( tree)
782                                 proto_tree_add_text( tree, NullTVB, offset, 0,
783                                         "Unhandled request command (report this, please)");
784         }
785 }
786
787
788
789 static void dissect_hello_ack(const u_char *pd, int offset, frame_data *fd,
790         proto_tree *tree, hash_entry_t *conv_info) {
791
792 /* decode the hello acknowledge packet  */
793
794         offset += 60;
795
796         if ( tree) {
797                 CHECK_PACKET_LENGTH( 2);
798                 proto_tree_add_uint( tree, hf_msproxy_serverport, NullTVB, offset, 2,
799                          pntohs( &pd[ offset]));
800                 offset += 2;
801         
802                 CHECK_PACKET_LENGTH( 4);
803                 proto_tree_add_ipv4( tree, hf_msproxy_serveraddr, NullTVB, offset, 4,
804                         GWORD( pd, offset));
805                 offset += 4;
806         }
807 }
808
809
810
811 static void dissect_user_info_ack(const u_char *pd, int offset,
812         frame_data *fd, proto_tree *tree) {
813
814 /* decode the  response _2 structure  */
815
816         offset += 18;
817
818         offset += 2;
819
820 }
821
822
823
824 static void dissect_udpassociate_ack( const u_char *pd, int offset, 
825         frame_data *fd, proto_tree *tree) {
826
827
828         offset += 6;
829
830         if ( tree) {
831                 CHECK_PACKET_LENGTH( 4);
832                 proto_tree_add_uint( tree, hf_msproxy_bind_id, NullTVB, offset, 4, pntohl( &pd[ offset]));
833                 offset += 14;
834
835                 CHECK_PACKET_LENGTH( 2);
836                 proto_tree_add_uint( tree, hf_msproxy_server_ext_port, NullTVB, offset, 2, pntohs( &pd[ offset]));
837                 offset += 2;
838
839                 CHECK_PACKET_LENGTH( 4);
840                 proto_tree_add_ipv4( tree, hf_msproxy_server_ext_addr, NullTVB, offset, 4, GWORD( pd, offset));
841
842                 offset += 96;
843                 display_application_name( pd, offset, fd, tree);
844         }
845 }
846
847
848
849 static void dissect_auth_1_ack(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
850
851
852         char temp[ 255];                
853
854         offset += 134;
855         if ( tree) {
856
857                 CHECK_PACKET_LENGTH( 7);
858                 strncpy( temp, &pd[ offset], 7);
859                 temp[ 7] = 0;                   
860                 proto_tree_add_text( tree, NullTVB, offset, 7, "NTLMSSP signature: %s", temp);
861                 offset += 48;
862
863                 strncpy( temp, &pd[ offset], MIN( 255, END_OF_FRAME));
864                 temp[ MIN( 255, END_OF_FRAME)] = 0;                     
865                 proto_tree_add_text( tree, NullTVB, offset, 255, "NT domain: %s", temp);
866                 offset += 7;
867         }
868 }
869
870
871
872 static void dissect_msproxy_response_4( const u_char *pd, int offset,
873         frame_data *fd, proto_tree *tree) {
874
875 /* decode the response _4 structure  */
876
877         offset += 134;
878 }
879
880
881
882 static void dissect_connect_ack( const u_char *pd, int offset, frame_data *fd,
883         proto_tree *tree, hash_entry_t *conv_info) {
884
885 /* decode the connect ack packet  */
886         offset += 20;
887
888         CHECK_PACKET_LENGTH( 2);
889
890         if ( tree)
891                 proto_tree_add_uint( tree, hf_msproxy_server_int_port, NullTVB, offset, 2, pntohs( &pd[ offset]));
892
893
894         conv_info->proto = PT_TCP;
895         conv_info->server_int_port = pntohs( &pd[ offset]);
896         offset += 2;
897         
898         if ( tree){
899                 CHECK_PACKET_LENGTH( 2);
900                 proto_tree_add_ipv4( tree, hf_msproxy_server_int_addr, NullTVB, offset, 2, GWORD( pd, offset));
901                 offset += 14;
902
903                 CHECK_PACKET_LENGTH( 2);
904                 proto_tree_add_uint( tree, hf_msproxy_server_ext_port, NullTVB, offset, 2, pntohs( &pd[ offset]));
905                 offset += 2;
906
907                 CHECK_PACKET_LENGTH( 4);
908                 proto_tree_add_ipv4( tree, hf_msproxy_server_ext_addr, NullTVB, offset, 4, GWORD( pd, offset));
909                 offset += 80;
910
911                 display_application_name( pd, offset, fd, tree);
912         }
913
914         add_msproxy_conversation( conv_info);
915 }
916
917
918
919 static void dissect_tcp_bind_ack( const u_char *pd, int offset, frame_data *fd,
920         proto_tree *tree) {
921
922 /* decode the tcp bind */
923
924         if ( tree) {
925                 offset += 6;
926
927                 CHECK_PACKET_LENGTH( 4);
928                 proto_tree_add_uint( tree, hf_msproxy_bind_id, NullTVB, offset, 4, pntohl( &pd[ offset]));
929                 offset += 16;
930
931                 CHECK_PACKET_LENGTH( 2);
932                 proto_tree_add_uint( tree, hf_msproxy_server_int_port, NullTVB, offset,
933                         2, pntohs( &pd[ offset]));
934                 offset += 6;
935
936                 CHECK_PACKET_LENGTH( 2);
937                 proto_tree_add_uint( tree, hf_msproxy_server_ext_port, NullTVB, offset,
938                         2, pntohs( &pd[ offset]));
939                 offset += 2;
940
941                 CHECK_PACKET_LENGTH( 4);
942                 proto_tree_add_ipv4( tree, hf_msproxy_server_ext_addr, NullTVB, offset,
943                         4, GWORD( pd, offset));
944
945                 offset += 88;
946
947                 display_application_name( pd, offset, fd, tree);
948         }
949 }
950
951
952
953 static void dissect_bind_info( const u_char *pd, int offset, frame_data *fd,
954         proto_tree *tree, hash_entry_t *conv_info) {
955
956 /* decode the Bind info response from server */
957
958         offset += 6;
959
960         CHECK_PACKET_LENGTH( 4);
961         if ( tree) 
962                 proto_tree_add_uint( tree, hf_msproxy_bind_id, NullTVB, offset, 4, pntohl( &pd[ offset]));
963         offset += 14;
964
965
966         CHECK_PACKET_LENGTH( 2);
967         if ( tree) 
968                 proto_tree_add_uint( tree, hf_msproxy_dstport, NullTVB, offset, 2,
969                         pntohs( &pd[ offset]));
970         conv_info->dst_port = pntohs( &pd[ offset]);
971         offset += 2;
972
973         CHECK_PACKET_LENGTH( 4);
974         if ( tree)
975                 proto_tree_add_ipv4( tree, hf_msproxy_dstaddr, NullTVB, offset, 4,
976                         GWORD( pd, offset));
977
978         memcpy( &conv_info->dst_addr, &pd[ offset], sizeof( guint32));
979         
980         offset += 12;
981
982         CHECK_PACKET_LENGTH( 2);
983         if ( tree) 
984                 proto_tree_add_uint( tree, hf_msproxy_server_int_port, NullTVB, offset,
985                         2, pntohs( &pd[ offset]));
986         conv_info->server_int_port = pntohs( &pd[ offset]);
987         offset += 4;
988         
989         if ( tree) {
990
991                 CHECK_PACKET_LENGTH( 2);
992                 proto_tree_add_uint( tree, hf_msproxy_server_ext_port, NullTVB, offset,
993                         2, pntohs( &pd[ offset]));
994                 offset += 2;
995
996                 CHECK_PACKET_LENGTH( 4);
997                 proto_tree_add_ipv4( tree, hf_msproxy_server_ext_addr, NullTVB, offset,
998                         4, GWORD( pd, offset));
999
1000                 offset += 78;
1001                 display_application_name( pd, offset, fd, tree);
1002                 
1003         }
1004         
1005         add_msproxy_conversation( conv_info);
1006 }
1007
1008
1009
1010 static void dissect_resolve(const u_char *pd, int offset, frame_data *fd,
1011         proto_tree *tree) {
1012
1013 /* dissect the  response resolve structure */
1014 /* display a string with a length, characters encoding */
1015 /* they are displayed under a tree with the name in Label variable */
1016 /* return the length of the string and the length byte */
1017
1018         if ( tree) {
1019
1020                 int addr_offset = GBYTE( pd, offset); 
1021         
1022                 proto_tree_add_text( tree, NullTVB, offset, 1, "Address offset: %d",
1023                         addr_offset);
1024
1025                 ++offset;
1026         
1027                 offset += 13;
1028
1029                 offset += addr_offset; 
1030
1031                 CHECK_PACKET_LENGTH( 4);
1032                 proto_tree_add_ipv4( tree, hf_msproxy_resolvaddr, NullTVB, offset, 4,
1033                         GWORD( pd, offset));
1034         }
1035 }       
1036
1037
1038
1039 static void dissect_msproxy_response(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, hash_entry_t *conv_info) {
1040
1041         char temp[ 255];
1042         int cmd;
1043
1044
1045         if ( tree) {
1046                 CHECK_PACKET_LENGTH( 4);
1047                 proto_tree_add_text( tree, NullTVB, offset, 4, "Client id: 0x%0x", 
1048                         GWORD( pd, offset));
1049                 offset += 4;
1050
1051                 CHECK_PACKET_LENGTH( 4);
1052                 proto_tree_add_text( tree, NullTVB, offset, 4, "Version: 0x%04x", 
1053                         GWORD( pd, offset));
1054                 offset += 4;
1055
1056                 CHECK_PACKET_LENGTH( 4);
1057                 proto_tree_add_text( tree, NullTVB, offset, 4, "Server id: 0x%04x", 
1058                         GWORD( pd, offset));
1059                 offset += 4;
1060
1061                 CHECK_PACKET_LENGTH( 1);
1062                 proto_tree_add_text( tree, NullTVB, offset, 1, "Client ack: 0x%02x", 
1063                         GBYTE( pd, offset));
1064
1065                 offset += 4;
1066
1067                 CHECK_PACKET_LENGTH( 1);
1068                 proto_tree_add_text( tree, NullTVB, offset, 1, "Sequence Number: 0x%02x", 
1069                         GBYTE( pd, offset));
1070         
1071                 offset += 8;
1072
1073                 CHECK_PACKET_LENGTH( 4);
1074                 strncpy( temp, &pd[ offset], 4);
1075                 temp[ 4] = 0;                   
1076                 proto_tree_add_text( tree, NullTVB, offset, 4, "RWSP signature: %s", temp);
1077
1078                 offset += 12;
1079         }
1080         else
1081                 offset += 36;
1082
1083         CHECK_PACKET_LENGTH( 2);
1084         cmd = pntohs( &pd[offset]);
1085         
1086         if ( tree)
1087                 proto_tree_add_uint_format( tree, hf_msproxy_cmd, NullTVB, offset, 2,
1088                         cmd, "Command: 0x%02x (%s)", cmd, 
1089                         get_msproxy_cmd_name( cmd, FROM_SERVER));
1090         offset += 2;
1091         
1092         switch (cmd) {
1093                 case MSPROXY_HELLO_ACK:
1094                         dissect_hello_ack( pd, offset, fd, tree, conv_info);
1095                         break;
1096         
1097                 case MSPROXY_USERINFO_ACK:
1098                         dissect_user_info_ack( pd, offset, fd, tree);
1099                         break;
1100                         
1101                 case MSPROXY_AUTH_1_ACK:
1102                         dissect_auth_1_ack( pd, offset, fd, tree);
1103                         break;
1104
1105 /* this also handle the MSPROXY_BIND_ACK ??? check this */
1106
1107                 case MSPROXY_UDPASSOCIATE_ACK:                  
1108                         dissect_udpassociate_ack( pd, offset, fd, tree);
1109                         break;
1110                 
1111                 case MSPROXY_AUTH_2_ACK:
1112                 case MSPROXY_AUTH_2_ACK2:
1113                         dissect_msproxy_response_4( pd, offset, fd, tree);
1114                         break;
1115
1116                 case MSPROXY_TCP_BIND_ACK:
1117                         dissect_tcp_bind_ack( pd, offset, fd, tree);
1118                         break;
1119
1120                 case MSPROXY_CONNECT_ACK:
1121                         dissect_connect_ack( pd, offset, fd, tree, conv_info);
1122                         break;
1123
1124                 case MSPROXY_BINDINFO:
1125                         dissect_bind_info( pd, offset, fd, tree, conv_info);
1126                         break;
1127         
1128                 case MSPROXY_RESOLVE_ACK:
1129                         dissect_resolve( pd, offset, fd, tree);
1130                         break;
1131                 
1132                 case MSPROXY_CONNECT_AUTHFAILED:
1133                 case MSPROXY_BIND_AUTHFAILED:
1134                         proto_tree_add_text( tree, NullTVB, offset, 0, "No know information (help wanted)");
1135                         break;
1136
1137                 default:
1138
1139                         if (tree &&
1140                            (((cmd >> 8) ==  MSPROXY_CONNREFUSED) ||
1141                             ((cmd >> 12) ==  MSPROXY_CONNREFUSED)))
1142                                 proto_tree_add_text( tree, NullTVB, offset, 0,
1143                                         "No know information (help wanted)");
1144         
1145                         else if ( tree)
1146                                 proto_tree_add_text( tree, NullTVB, offset, 0,
1147                                         "Unhandled response command (report this, please)");
1148         }
1149         
1150         
1151 }
1152
1153
1154
1155 static void dissect_msproxy(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1156
1157
1158         proto_tree      *msproxy_tree = NULL;
1159         proto_item      *ti;
1160         unsigned int    cmd;
1161
1162
1163         hash_entry_t *hash_info;
1164         conversation_t *conversation;
1165         
1166         OLD_CHECK_DISPLAY_AS_DATA(proto_msproxy, pd, offset, fd, tree);
1167
1168         conversation = find_conversation( &pi.src, &pi.dst, pi.ptype,
1169                 pi.srcport, pi.destport);
1170
1171         if ( conversation)                      /* conversation found */
1172                 hash_info = conversation->data;
1173
1174                         /* new conversation create local data structure */
1175         else {                          
1176                 hash_info = g_mem_chunk_alloc(vals);
1177
1178                 conversation_new( &pi.src, &pi.dst, pi.ptype,
1179                         pi.srcport, pi.destport, hash_info);
1180         }
1181
1182         if (check_col(fd, COL_PROTOCOL))
1183                 col_add_str(fd, COL_PROTOCOL, "MSproxy");
1184
1185
1186                                                 /* display packet info */
1187         if (check_col(fd, COL_INFO)){
1188         
1189                 cmd = pntohs( &pd[offset + 36]);
1190                 
1191                 if ( pi.srcport == UDP_PORT_MSPROXY)
1192                         col_add_fstr( fd, COL_INFO, "Server message: %s",
1193                                 get_msproxy_cmd_name( cmd, FROM_SERVER));
1194                 else
1195                         col_add_fstr(fd, COL_INFO, "Client message: %s",
1196                                 get_msproxy_cmd_name( cmd, FROM_CLIENT));
1197                 
1198         }
1199
1200         if (tree) {                             /* if proto tree, decode data */
1201                 ti = proto_tree_add_item( tree, proto_msproxy, NullTVB, offset,
1202                                 END_OF_FRAME, FALSE );
1203
1204                 msproxy_tree = proto_item_add_subtree(ti, ett_msproxy);
1205         }
1206
1207         if ( pi.srcport == UDP_PORT_MSPROXY)
1208                 dissect_msproxy_response( pd, offset, fd, msproxy_tree, hash_info);
1209         else
1210                 dissect_msproxy_request( pd, offset, fd, msproxy_tree, hash_info);
1211 }
1212
1213
1214
1215 static void msproxy_reinit( void){
1216
1217 /* Do the cleanup work when a new pass through the packet list is       */
1218 /* performed. Reset the highest row seen counter and re-initialize the  */
1219 /* conversation memory chunks.                                          */
1220
1221         last_row = 0;                   
1222         
1223         if (vals)
1224                 g_mem_chunk_destroy(vals);
1225
1226         vals = g_mem_chunk_new("msproxy_vals", hash_val_length,
1227                 hash_init_count * hash_val_length,
1228                 G_ALLOC_AND_FREE);
1229                 
1230         if (redirect_vals)
1231                 g_mem_chunk_destroy(redirect_vals);
1232
1233         redirect_vals = g_mem_chunk_new("msproxy_redirect_vals", redirect_val_length,
1234                 redirect_init_count * redirect_val_length,
1235                 G_ALLOC_AND_FREE);
1236 }
1237
1238
1239
1240 void
1241 proto_register_msproxy( void){
1242
1243 /* Prep the msproxy protocol, for now, just register it */
1244
1245         static gint *ett[] = {
1246                 &ett_msproxy,
1247                 &ett_msproxy_name
1248         };
1249         static hf_register_info hf[] = {
1250     
1251                 { &hf_msproxy_cmd,
1252                         { "Command", "msproxy.command", FT_UINT16, BASE_DEC,
1253                                  NULL, 0x0, ""
1254                         }
1255                 },
1256                 
1257                 { &hf_msproxy_dstaddr,
1258                         { "Destination Address", "msproxy.dstaddr", FT_IPv4, BASE_NONE, NULL,
1259                                 0x0, ""
1260                         }
1261                 },
1262
1263                 { &hf_msproxy_srcport,
1264                         { "Source Port", "msproxy.srcport", FT_UINT16,
1265                                 BASE_DEC, NULL, 0x0, ""
1266                         }
1267                 },
1268                 { &hf_msproxy_dstport,
1269                         { "Destination Port", "msproxy.dstport", FT_UINT16,
1270                                 BASE_DEC, NULL, 0x0, ""
1271                         }
1272                 },
1273                 { &hf_msproxy_clntport,
1274                         { "Client Port",        "msproxy.clntport", FT_UINT16,
1275                                 BASE_DEC, NULL, 0x0, ""
1276                         }
1277                 },
1278                 { &hf_msproxy_server_ext_addr,
1279                         { "Server External Address", "msproxy.server_ext_addr", FT_IPv4, BASE_NONE, NULL,
1280                                 0x0, ""
1281                         }
1282                 },
1283                 
1284                 { &hf_msproxy_server_ext_port,
1285                         { "Server External Port",       "msproxy.server_ext_port", FT_UINT16,
1286                                 BASE_DEC, NULL, 0x0, ""
1287                         }
1288                 },
1289
1290                 { &hf_msproxy_server_int_addr,
1291                         { "Server Internal Address", "msproxy.server_int_addr", FT_IPv4, BASE_NONE, NULL,
1292                                 0x0, ""
1293                         }
1294                 },
1295                 
1296                 { &hf_msproxy_server_int_port,
1297                         { "Server Internal Port",       "msproxy.server_int_port", FT_UINT16,
1298                                 BASE_DEC, NULL, 0x0, ""
1299                         }
1300                 },
1301                 { &hf_msproxy_serverport,
1302                         { "Server Port",        "msproxy.serverport", FT_UINT16,
1303                                 BASE_DEC, NULL, 0x0, ""
1304                         }
1305                 },
1306                 { &hf_msproxy_bindport,
1307                         { "Bind Port",  "msproxy.bindport", FT_UINT16,
1308                                 BASE_DEC, NULL, 0x0, ""
1309                         }
1310                 },
1311                 { &hf_msproxy_boundport,
1312                         { "Bound Port", "msproxy.boundport", FT_UINT16,
1313                                 BASE_DEC, NULL, 0x0, ""
1314                         }
1315                 },
1316                 { &hf_msproxy_serveraddr,
1317                         { "Server Address", "msproxy.serveraddr", FT_IPv4, BASE_NONE, NULL,
1318                                 0x0, ""
1319                         }
1320                 },
1321                 { &hf_msproxy_bindaddr,
1322                         { "Destination", "msproxy.bindaddr", FT_IPv4, BASE_NONE, NULL,
1323                                 0x0, ""
1324                         }
1325                 },
1326                 { &hf_msproxy_bind_id,
1327                         { "Bound Port Id",      "msproxy.bindid", FT_UINT32,
1328                                 BASE_HEX, NULL, 0x0, ""
1329                         }
1330                 },
1331                 { &hf_msproxy_resolvaddr,
1332                         { "Address", "msproxy.resolvaddr", FT_IPv4, BASE_NONE, NULL,
1333                                 0x0, ""
1334                         }
1335                 }
1336
1337         };
1338
1339         proto_msproxy = proto_register_protocol ( "MSProxy Protocol", "msproxy");           
1340
1341         proto_register_field_array(proto_msproxy, hf, array_length(hf));
1342         proto_register_subtree_array(ett, array_length(ett));  
1343
1344         register_init_routine( &msproxy_reinit);        /* register re-init routine */
1345 }
1346
1347
1348 void
1349 proto_reg_handoff_msproxy(void) {
1350
1351         /* dissector install routine */ 
1352  
1353         old_dissector_add("udp.port", UDP_PORT_MSPROXY, dissect_msproxy);
1354 }