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