Initial import
[samba] / source / wrepld / parser.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Jean François Micouleau      1998-2002.
5  *  
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "includes.h"
22 #include "wins_repl.h"
23
24 extern TALLOC_CTX *mem_ctx;
25
26 /****************************************************************************
27 grow the send buffer if necessary
28 ****************************************************************************/
29 BOOL grow_buffer(struct BUFFER *buffer, int more)
30 {
31         char *temp;
32
33         DEBUG(10,("grow_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more));
34         
35         /* grow by at least 256 bytes */
36         if (more<256)
37                 more=256;
38
39         if (buffer->offset+more >= buffer->length) {
40                 temp=talloc_realloc(mem_ctx, buffer->buffer, char, buffer->length + more);
41                 if (temp==NULL) {
42                         DEBUG(0,("grow_buffer: can't grow buffer\n"));
43                         return False;
44                 }
45                 buffer->length+=more;
46                 buffer->buffer=temp;
47         }
48
49         return True;
50 }
51
52 /****************************************************************************
53 check if the buffer has that much data
54 ****************************************************************************/
55 static BOOL check_buffer(struct BUFFER *buffer, int more)
56 {
57         DEBUG(10,("check_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more));
58         
59         if (buffer->offset+more > buffer->length) {
60                 DEBUG(10,("check_buffer: buffer smaller than requested, size is: %d needed: %d\n", buffer->length, buffer->offset+more));
61                 return False;
62         }
63
64         return True;
65 }
66
67 /****************************************************************************
68 decode a WINS_OWNER struct
69 ****************************************************************************/
70 static void decode_wins_owner(struct BUFFER *inbuf, WINS_OWNER *wins_owner)
71 {
72         if(!check_buffer(inbuf, 24))
73                 return;
74
75         wins_owner->address.s_addr=IVAL(inbuf->buffer, inbuf->offset);
76         wins_owner->max_version=((SMB_BIG_UINT)RIVAL(inbuf->buffer, inbuf->offset+4))<<32;
77         wins_owner->max_version|=RIVAL(inbuf->buffer, inbuf->offset+8);
78         wins_owner->min_version=((SMB_BIG_UINT)RIVAL(inbuf->buffer, inbuf->offset+12))<<32;
79         wins_owner->min_version|=RIVAL(inbuf->buffer, inbuf->offset+16);
80         wins_owner->type=RIVAL(inbuf->buffer, inbuf->offset+20);
81         inbuf->offset+=24;
82
83 }
84
85 /****************************************************************************
86 decode a WINS_NAME struct
87 ****************************************************************************/
88 static void decode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name)
89 {       
90         char *p;
91         int i;
92
93         if(!check_buffer(outbuf, 40))
94                 return;
95
96         wins_name->name_len=RIVAL(outbuf->buffer, outbuf->offset);
97         outbuf->offset+=4;
98         memcpy(wins_name->name,outbuf->buffer+outbuf->offset, 15);
99         wins_name->name[15]='\0';
100         if((p = strchr(wins_name->name,' ')) != NULL)
101                 *p = 0;
102
103         outbuf->offset+=15;
104
105         wins_name->type=(int)outbuf->buffer[outbuf->offset++];
106         
107         /*
108          * fix to bug in WINS replication,
109          * present in all versions including W2K SP2 !
110          */
111         if (wins_name->name[0]==0x1B) {
112                 wins_name->name[0]=(char)wins_name->type;
113                 wins_name->type=0x1B;
114         }
115         
116         wins_name->empty=RIVAL(outbuf->buffer, outbuf->offset);
117         outbuf->offset+=4;
118         
119         wins_name->name_flag=RIVAL(outbuf->buffer, outbuf->offset);
120         outbuf->offset+=4;
121         wins_name->group_flag=RIVAL(outbuf->buffer, outbuf->offset);
122         outbuf->offset+=4;
123         wins_name->id=((SMB_BIG_UINT)RIVAL(outbuf->buffer, outbuf->offset))<<32;
124         outbuf->offset+=4;
125         wins_name->id|=RIVAL(outbuf->buffer, outbuf->offset);
126         outbuf->offset+=4;
127         
128         /* special groups have multiple address */
129         if (wins_name->name_flag & 2) {
130                 if(!check_buffer(outbuf, 4))
131                         return;
132                 wins_name->num_ip=IVAL(outbuf->buffer, outbuf->offset);
133                 outbuf->offset+=4;
134         }
135         else
136                 wins_name->num_ip=1;
137
138         if(!check_buffer(outbuf, 4))
139                 return;
140         wins_name->owner.s_addr=IVAL(outbuf->buffer, outbuf->offset);
141         outbuf->offset+=4;
142
143         if (wins_name->name_flag & 2) {
144                 wins_name->others=talloc_array(mem_ctx, struct in_addr, wins_name->num_ip);
145                 if (wins_name->others==NULL)
146                         return;
147
148                 if(!check_buffer(outbuf, 4*wins_name->num_ip))
149                         return;
150                 for (i=0; i<wins_name->num_ip; i++) {
151                         wins_name->others[i].s_addr=IVAL(outbuf->buffer, outbuf->offset);
152                         outbuf->offset+=4;
153                 }
154         }
155
156         if(!check_buffer(outbuf, 4))
157                 return;
158         wins_name->foo=RIVAL(outbuf->buffer, outbuf->offset);
159         outbuf->offset+=4;
160
161 }
162
163 /****************************************************************************
164 decode a update notification request
165 ****************************************************************************/
166 static void decode_update_notify_request(struct BUFFER *inbuf, UPDATE_NOTIFY_REQUEST *un_rq)
167 {
168         int i;
169
170         if(!check_buffer(inbuf, 4))
171                 return;
172         un_rq->partner_count=RIVAL(inbuf->buffer, inbuf->offset);
173         inbuf->offset+=4;
174
175         un_rq->wins_owner=talloc_array(mem_ctx, WINS_OWNER, un_rq->partner_count);
176         if (un_rq->wins_owner==NULL)
177                 return;
178
179         for (i=0; i<un_rq->partner_count; i++)
180                 decode_wins_owner(inbuf, &un_rq->wins_owner[i]);
181
182         if(!check_buffer(inbuf, 4))
183                 return;
184         un_rq->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset);
185         inbuf->offset+=4;
186 }
187
188 /****************************************************************************
189 decode a send entries request
190 ****************************************************************************/
191 static void decode_send_entries_request(struct BUFFER *inbuf, SEND_ENTRIES_REQUEST *se_rq)
192 {
193         decode_wins_owner(inbuf, &se_rq->wins_owner);
194 }
195
196 /****************************************************************************
197 decode a send entries reply
198 ****************************************************************************/
199 static void decode_send_entries_reply(struct BUFFER *inbuf, SEND_ENTRIES_REPLY *se_rp)
200 {
201         int i;
202
203         if(!check_buffer(inbuf, 4))
204                 return;
205         se_rp->max_names = RIVAL(inbuf->buffer, inbuf->offset);
206         inbuf->offset+=4;
207
208         se_rp->wins_name=talloc_array(mem_ctx, WINS_NAME, se_rp->max_names);
209         if (se_rp->wins_name==NULL)
210                 return;
211
212         for (i=0; i<se_rp->max_names; i++)
213                 decode_wins_name(inbuf, &se_rp->wins_name[i]);
214 }
215
216 /****************************************************************************
217 decode a add version number map table reply
218 ****************************************************************************/
219 static void decode_add_version_number_map_table_reply(struct BUFFER *inbuf, AVMT_REP *avmt_rep)
220 {
221         int i;
222
223         if(!check_buffer(inbuf, 4))
224                 return;
225
226         avmt_rep->partner_count=RIVAL(inbuf->buffer, inbuf->offset);
227         inbuf->offset+=4;
228
229         avmt_rep->wins_owner=talloc_array(mem_ctx, WINS_OWNER, avmt_rep->partner_count);
230         if (avmt_rep->wins_owner==NULL)
231                 return;
232
233         for (i=0; i<avmt_rep->partner_count; i++)
234                 decode_wins_owner(inbuf, &avmt_rep->wins_owner[i]);
235
236         if(!check_buffer(inbuf, 4))
237                 return;
238         avmt_rep->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset);
239         inbuf->offset+=4;
240 }
241
242 /****************************************************************************
243 decode a replicate packet and fill a structure
244 ****************************************************************************/
245 static void decode_replicate(struct BUFFER *inbuf, REPLICATE *rep)
246 {
247         if(!check_buffer(inbuf, 4))
248                 return;
249
250         rep->msg_type = RIVAL(inbuf->buffer, inbuf->offset);
251
252         inbuf->offset+=4;
253
254         switch (rep->msg_type) {
255                 case 0:
256                         break;
257                 case 1:
258                         /* add version number map table reply */
259                         decode_add_version_number_map_table_reply(inbuf, &rep->avmt_rep);
260                         break;
261                 case 2:
262                         /* send entry request */
263                         decode_send_entries_request(inbuf, &rep->se_rq);
264                         break;
265                 case 3:
266                         /* send entry request */
267                         decode_send_entries_reply(inbuf, &rep->se_rp);
268                         break;
269                 case 4:
270                         /* update notification request */
271                         decode_update_notify_request(inbuf, &rep->un_rq);
272                         break;
273                 default:
274                         DEBUG(0,("decode_replicate: unknown message type:%d\n", rep->msg_type));
275                         break;
276         }
277 }
278
279 /****************************************************************************
280 read the generic header and fill the struct.
281 ****************************************************************************/
282 static void read_generic_header(struct BUFFER *inbuf, generic_header *q)
283 {
284         if(!check_buffer(inbuf, 16))
285                 return;
286
287         q->data_size = RIVAL(inbuf->buffer, inbuf->offset+0);
288         q->opcode    = RIVAL(inbuf->buffer, inbuf->offset+4);
289         q->assoc_ctx = RIVAL(inbuf->buffer, inbuf->offset+8);
290         q->mess_type = RIVAL(inbuf->buffer, inbuf->offset+12);
291 }
292
293 /*******************************************************************
294 decode a start association request
295 ********************************************************************/
296 static void decode_start_assoc_request(struct BUFFER *inbuf, START_ASSOC_REQUEST *q)
297 {
298         if(!check_buffer(inbuf, 8))
299                 return;
300
301         q->assoc_ctx = RIVAL(inbuf->buffer, inbuf->offset+0);
302         q->min_ver = RSVAL(inbuf->buffer, inbuf->offset+4);
303         q->maj_ver = RSVAL(inbuf->buffer, inbuf->offset+6);
304 }
305
306 /*******************************************************************
307 decode a start association reply
308 ********************************************************************/
309 static void decode_start_assoc_reply(struct BUFFER *inbuf, START_ASSOC_REPLY *r)
310 {
311         if(!check_buffer(inbuf, 8))
312                 return;
313
314         r->assoc_ctx=RIVAL(inbuf->buffer, inbuf->offset+0);
315         r->min_ver = RSVAL(inbuf->buffer, inbuf->offset+4);
316         r->maj_ver = RSVAL(inbuf->buffer, inbuf->offset+6);
317 }
318
319 /*******************************************************************
320 decode a start association reply
321 ********************************************************************/
322 static void decode_stop_assoc(struct BUFFER *inbuf, STOP_ASSOC *r)
323 {
324         if(!check_buffer(inbuf, 4))
325                 return;
326
327         r->reason=RIVAL(inbuf->buffer, inbuf->offset);
328 }
329
330 /****************************************************************************
331 decode a packet and fill a generic structure
332 ****************************************************************************/
333 void decode_generic_packet(struct BUFFER *inbuf, GENERIC_PACKET *q)
334 {
335         read_generic_header(inbuf, &q->header);
336
337         inbuf->offset+=16;
338
339         switch (q->header.mess_type) {
340                 case 0:
341                         decode_start_assoc_request(inbuf, &q->sa_rq);
342                         break;
343                 case 1:
344                         decode_start_assoc_reply(inbuf, &q->sa_rp);
345                         break;
346                 case 2:
347                         decode_stop_assoc(inbuf, &q->so);
348                         break;
349                 case 3:
350                         decode_replicate(inbuf, &q->rep);
351                         break;
352                 default:
353                         DEBUG(0,("decode_generic_packet: unknown message type:%d\n", q->header.mess_type));
354                         break;
355         }
356 }
357
358 /****************************************************************************
359 encode a WINS_OWNER struct
360 ****************************************************************************/
361 static void encode_wins_owner(struct BUFFER *outbuf, WINS_OWNER *wins_owner)
362 {
363         if (!grow_buffer(outbuf, 24))
364                 return;
365
366         SIVAL(outbuf->buffer, outbuf->offset, wins_owner->address.s_addr);
367         outbuf->offset+=4;
368         RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version>>32));
369         outbuf->offset+=4;
370         RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version&0xffffffff));
371         outbuf->offset+=4;
372         RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version>>32);
373         outbuf->offset+=4;
374         RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version&0xffffffff);
375         outbuf->offset+=4;
376         RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->type);
377         outbuf->offset+=4;
378         
379 }
380
381 /****************************************************************************
382 encode a WINS_NAME struct
383 ****************************************************************************/
384 static void encode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name)
385 {       
386         int i;
387
388         if (!grow_buffer(outbuf, 48+(4*wins_name->num_ip)))
389                 return;
390
391         RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_len);
392         outbuf->offset+=4;
393         
394         memset(outbuf->buffer+outbuf->offset, ' ', 15);
395
396         /* to prevent copying the leading \0 */
397         memcpy(outbuf->buffer+outbuf->offset, wins_name->name, strlen(wins_name->name));
398         outbuf->offset+=15;             
399
400         outbuf->buffer[outbuf->offset++]=(char)wins_name->type;
401
402         RSIVAL(outbuf->buffer, outbuf->offset, wins_name->empty);
403         outbuf->offset+=4;
404
405         RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_flag);
406         outbuf->offset+=4;
407         RSIVAL(outbuf->buffer, outbuf->offset, wins_name->group_flag);
408         outbuf->offset+=4;
409         RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id>>32);
410         outbuf->offset+=4;
411         RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id);
412         outbuf->offset+=4;
413
414         if (wins_name->name_flag & 2) {
415                 SIVAL(outbuf->buffer, outbuf->offset, wins_name->num_ip);
416                 outbuf->offset+=4;
417         }       
418
419         SIVAL(outbuf->buffer, outbuf->offset, wins_name->owner.s_addr);
420         outbuf->offset+=4;
421
422         if (wins_name->name_flag & 2) {
423                 for (i=0;i<wins_name->num_ip;i++) {
424                         SIVAL(outbuf->buffer, outbuf->offset, wins_name->others[i].s_addr);
425                         outbuf->offset+=4;
426                 }
427         }       
428
429         RSIVAL(outbuf->buffer, outbuf->offset, wins_name->foo);
430         outbuf->offset+=4;
431 }
432
433 /****************************************************************************
434 encode a update notification request
435 ****************************************************************************/
436 static void encode_update_notify_request(struct BUFFER *outbuf, UPDATE_NOTIFY_REQUEST *un_rq)
437 {
438         int i;
439
440         if (!grow_buffer(outbuf, 8))
441                 return;
442                 
443         RSIVAL(outbuf->buffer, outbuf->offset, un_rq->partner_count);
444         outbuf->offset+=4;
445
446         for (i=0; i<un_rq->partner_count; i++)
447                 encode_wins_owner(outbuf,  &un_rq->wins_owner[i]);
448
449         SIVAL(outbuf->buffer, outbuf->offset, un_rq->initiating_wins_server.s_addr);
450         outbuf->offset+=4;
451         
452 }
453
454 /****************************************************************************
455 decode a send entries request
456 ****************************************************************************/
457 static void encode_send_entries_request(struct BUFFER *outbuf, SEND_ENTRIES_REQUEST *se_rq)
458 {
459         encode_wins_owner(outbuf, &se_rq->wins_owner);
460 }
461
462 /****************************************************************************
463 decode a send entries reply
464 ****************************************************************************/
465 static void encode_send_entries_reply(struct BUFFER *outbuf, SEND_ENTRIES_REPLY *se_rp)
466 {
467         int i;
468
469         if (!grow_buffer(outbuf, 4))
470                 return;
471                 
472         RSIVAL(outbuf->buffer, outbuf->offset, se_rp->max_names);
473         outbuf->offset+=4;
474
475         for (i=0; i<se_rp->max_names; i++)
476                 encode_wins_name(outbuf, &se_rp->wins_name[i]);
477
478 }
479
480 /****************************************************************************
481 encode a add version number map table reply
482 ****************************************************************************/
483 static void encode_add_version_number_map_table_reply(struct BUFFER *outbuf, AVMT_REP *avmt_rep)
484 {
485         int i;
486
487         if (!grow_buffer(outbuf, 8))
488                 return;
489
490         RSIVAL(outbuf->buffer, outbuf->offset, avmt_rep->partner_count);
491         outbuf->offset+=4;
492         
493         for (i=0; i<avmt_rep->partner_count; i++)
494                 encode_wins_owner(outbuf, &avmt_rep->wins_owner[i]);
495
496         SIVAL(outbuf->buffer, outbuf->offset, avmt_rep->initiating_wins_server.s_addr);
497         outbuf->offset+=4;
498         
499 }
500
501 /****************************************************************************
502 decode a replicate packet and fill a structure
503 ****************************************************************************/
504 static void encode_replicate(struct BUFFER *outbuf, REPLICATE *rep)
505 {
506         if (!grow_buffer(outbuf, 4))
507                 return;
508
509         RSIVAL(outbuf->buffer, outbuf->offset, rep->msg_type);
510         outbuf->offset+=4;
511
512         switch (rep->msg_type) {
513                 case 0:
514                         break;
515                 case 1:
516                         /* add version number map table reply */
517                         encode_add_version_number_map_table_reply(outbuf, &rep->avmt_rep);
518                         break;
519                 case 2:
520                         /* send entry request */
521                         encode_send_entries_request(outbuf, &rep->se_rq);
522                         break;
523                 case 3:
524                         /* send entry request */
525                         encode_send_entries_reply(outbuf, &rep->se_rp);
526                         break;
527                 case 4:
528                         /* update notification request */
529                         encode_update_notify_request(outbuf, &rep->un_rq);
530                         break;
531                 default:
532                         DEBUG(0,("encode_replicate: unknown message type:%d\n", rep->msg_type));
533                         break;
534         }
535 }
536
537 /****************************************************************************
538 write the generic header.
539 ****************************************************************************/
540 static void write_generic_header(struct BUFFER *outbuf, generic_header *r)
541 {
542         RSIVAL(outbuf->buffer, 0, r->data_size);
543         RSIVAL(outbuf->buffer, 4, r->opcode);
544         RSIVAL(outbuf->buffer, 8, r->assoc_ctx);
545         RSIVAL(outbuf->buffer,12, r->mess_type);
546 }
547
548 /*******************************************************************
549 decode a start association request
550 ********************************************************************/
551 static void encode_start_assoc_request(struct BUFFER *outbuf, START_ASSOC_REQUEST *q)
552 {
553         if (!grow_buffer(outbuf, 45))
554                 return;
555
556         RSIVAL(outbuf->buffer, outbuf->offset, q->assoc_ctx);
557         RSSVAL(outbuf->buffer, outbuf->offset+4, q->min_ver);
558         RSSVAL(outbuf->buffer, outbuf->offset+6, q->maj_ver);
559         
560         outbuf->offset=45;
561 }
562
563 /*******************************************************************
564 decode a start association reply
565 ********************************************************************/
566 static void encode_start_assoc_reply(struct BUFFER *outbuf, START_ASSOC_REPLY *r)
567 {
568         if (!grow_buffer(outbuf, 45))
569                 return;
570
571         RSIVAL(outbuf->buffer, outbuf->offset, r->assoc_ctx);
572         RSSVAL(outbuf->buffer, outbuf->offset+4, r->min_ver);
573         RSSVAL(outbuf->buffer, outbuf->offset+6, r->maj_ver);
574
575         outbuf->offset=45;
576 }
577
578 /*******************************************************************
579 decode a start association reply
580 ********************************************************************/
581 static void encode_stop_assoc(struct BUFFER *outbuf, STOP_ASSOC *r)
582 {
583         if (!grow_buffer(outbuf, 44))
584                 return;
585
586         RSIVAL(outbuf->buffer, outbuf->offset, r->reason);
587         
588         outbuf->offset=44;
589 }
590
591 /****************************************************************************
592 write the generic header size.
593 ****************************************************************************/
594 static void write_generic_header_size(generic_header *r, int size)
595 {
596         /* the buffer size is the total size minus the size field */
597         r->data_size=size-4;
598 }
599
600 /****************************************************************************
601 encode a packet and read a generic structure
602 ****************************************************************************/
603 void encode_generic_packet(struct BUFFER *outbuf, GENERIC_PACKET *q)
604 {
605         if (!grow_buffer(outbuf, 16))
606                 return;
607
608         outbuf->offset=16;
609
610         switch (q->header.mess_type) {
611                 case 0:
612                         encode_start_assoc_request(outbuf, &q->sa_rq);
613                         break;
614                 case 1:
615                         encode_start_assoc_reply(outbuf, &q->sa_rp);
616                         break;
617                 case 2:
618                         encode_stop_assoc(outbuf, &q->so);
619                         break;
620                 case 3:
621                         encode_replicate(outbuf, &q->rep);
622                         break;
623                 default:
624                         DEBUG(0,("encode_generic_packet: unknown message type:%d\n", q->header.mess_type));
625                         break;
626         }
627         
628         write_generic_header_size(&q->header, outbuf->offset);
629         write_generic_header(outbuf, &q->header);
630 }
631
632
633 /****************************************************************************
634 dump a WINS_OWNER structure
635 ****************************************************************************/
636 static void dump_wins_owner(WINS_OWNER *wins_owner)
637 {
638         DEBUGADD(10,("\t\t\t\taddress         : %s\n", inet_ntoa(wins_owner->address)));
639         DEBUGADD(10,("\t\t\t\tmax version: %d\n", (int)wins_owner->max_version));
640         DEBUGADD(10,("\t\t\t\tmin version: %d\n", (int)wins_owner->min_version));
641         DEBUGADD(10,("\t\t\t\ttype            : %d\n", wins_owner->type));
642 }
643
644 /****************************************************************************
645 dump a WINS_NAME structure
646 ****************************************************************************/
647 static void dump_wins_name(WINS_NAME *wins_name)
648 {
649         fstring name;
650         int i;
651
652         strncpy(name, wins_name->name, 15);
653
654         DEBUGADD(10,("name: %d, %s<%02x> %x,%x, %d %s %d ", wins_name->name_len, name, wins_name->type,
655                     wins_name->name_flag, wins_name->group_flag, (int)wins_name->id,
656                     inet_ntoa(wins_name->owner), wins_name->num_ip));
657
658         if (wins_name->num_ip!=1)
659                 for (i=0; i<wins_name->num_ip; i++)
660                         DEBUGADD(10,("%s ", inet_ntoa(wins_name->others[i])));  
661
662         DEBUGADD(10,("\n"));
663 }
664
665 /****************************************************************************
666 dump a replicate structure
667 ****************************************************************************/
668 static void dump_replicate(REPLICATE *rep)
669 {
670         int i;
671
672         DEBUGADD(5,("\t\tmsg_type: %d ", rep->msg_type));
673
674         switch (rep->msg_type) {
675                 case 0:
676                         DEBUGADD(5,("(Add Version Map Table Request)\n"));
677                         break;
678                 case 1:
679                         DEBUGADD(5,("(Add Version Map Table Reply)\n"));
680                         DEBUGADD(5,("\t\t\tpartner_count         : %d\n", rep->avmt_rep.partner_count));
681                         for (i=0; i<rep->avmt_rep.partner_count; i++)
682                                 dump_wins_owner(&rep->avmt_rep.wins_owner[i]);
683                         DEBUGADD(5,("\t\t\tinitiating_wins_server: %s\n", inet_ntoa(rep->avmt_rep.initiating_wins_server)));
684                         break;
685                 case 2:
686                         DEBUGADD(5,("(Send Entries Request)\n"));
687                         dump_wins_owner(&rep->se_rq.wins_owner);
688                         break;
689                 case 3:
690                         DEBUGADD(5,("(Send Entries Reply)\n"));
691                         DEBUGADD(5,("\t\t\tmax_names         : %d\n", rep->se_rp.max_names));
692                         for (i=0; i<rep->se_rp.max_names; i++)
693                                 dump_wins_name(&rep->se_rp.wins_name[i]);
694                         break;
695                 case 4:
696                         DEBUGADD(5,("(Update Notify Request)\n"));
697                         DEBUGADD(5,("\t\t\tpartner_count         : %d\n", rep->un_rq.partner_count));
698                         for (i=0; i<rep->un_rq.partner_count; i++)
699                                 dump_wins_owner(&rep->un_rq.wins_owner[i]);
700                         DEBUGADD(5,("\t\t\tinitiating_wins_server: %s\n", inet_ntoa(rep->un_rq.initiating_wins_server)));
701                         break;
702                 default:
703                         DEBUG(5,("\n"));
704                         break;
705         }
706 }
707
708 /****************************************************************************
709 dump a generic structure
710 ****************************************************************************/
711 void dump_generic_packet(GENERIC_PACKET *q)
712 {
713         DEBUG(5,("dump_generic_packet:\n"));
714         DEBUGADD(5,("\tdata_size: %08x\n", q->header.data_size));
715         DEBUGADD(5,("\topcode   : %08x\n", q->header.opcode));
716         DEBUGADD(5,("\tassoc_ctx: %08x\n", q->header.assoc_ctx));
717         DEBUGADD(5,("\tmess_type: %08x ", q->header.mess_type));
718
719         switch (q->header.mess_type) {
720                 case 0:
721                         DEBUGADD(5,("(Start Association Request)\n"));
722                         DEBUGADD(5,("\t\tassoc_ctx: %08x\n", q->sa_rq.assoc_ctx));
723                         DEBUGADD(5,("\t\tmin_ver  : %04x\n", q->sa_rq.min_ver));
724                         DEBUGADD(5,("\t\tmaj_ver  : %04x\n", q->sa_rq.maj_ver));
725                         break;
726                 case 1:
727                         DEBUGADD(5,("(Start Association Reply)\n"));
728                         DEBUGADD(5,("\t\tassoc_ctx: %08x\n", q->sa_rp.assoc_ctx));
729                         DEBUGADD(5,("\t\tmin_ver  : %04x\n", q->sa_rp.min_ver));
730                         DEBUGADD(5,("\t\tmaj_ver  : %04x\n", q->sa_rp.maj_ver));
731                         break;
732                 case 2:
733                         DEBUGADD(5,("(Stop Association)\n"));
734                         DEBUGADD(5,("\t\treason: %08x\n", q->so.reason));
735                         break;
736                 case 3:
737                         DEBUGADD(5,("(Replication Message)\n"));
738                         dump_replicate(&q->rep);
739                         break;
740                 default:
741                         DEBUG(5,("\n"));
742                         break;
743         }
744
745 }
746
747 /****************************************************************************
748 generate a stop packet
749 ****************************************************************************/
750 void stop_packet(GENERIC_PACKET *q, GENERIC_PACKET *r, int reason)
751 {
752         r->header.opcode=OPCODE_NON_NBT;
753         r->header.assoc_ctx=get_server_assoc(q->header.assoc_ctx);
754         r->header.mess_type=MESSAGE_TYPE_STOP_ASSOC;
755         r->so.reason=reason;
756         
757 }
758
759