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