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