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
24extern TALLOC_CTX *mem_ctx;
25
26/****************************************************************************
27grow the send buffer if necessary
28****************************************************************************/
29BOOL 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=(char *)talloc_realloc(mem_ctx, buffer->buffer, sizeof(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/****************************************************************************
53check if the buffer has that much data
54****************************************************************************/
55static 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/****************************************************************************
68decode a WINS_OWNER struct
69****************************************************************************/
70static 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/****************************************************************************
86decode a WINS_NAME struct
87****************************************************************************/
88static 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=(struct in_addr *)talloc(mem_ctx, sizeof(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/****************************************************************************
164decode a update notification request
165****************************************************************************/
166static 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=(WINS_OWNER *)talloc(mem_ctx, un_rq->partner_count*sizeof(WINS_OWNER));
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/****************************************************************************
189decode a send entries request
190****************************************************************************/
191static 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/****************************************************************************
197decode a send entries reply
198****************************************************************************/
199static 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=(WINS_NAME *)talloc(mem_ctx, se_rp->max_names*sizeof(WINS_NAME));
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/****************************************************************************
217decode a add version number map table reply
218****************************************************************************/
219static 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=(WINS_OWNER *)talloc(mem_ctx, avmt_rep->partner_count*sizeof(WINS_OWNER));
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/****************************************************************************
243decode a replicate packet and fill a structure
244****************************************************************************/
245static 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/****************************************************************************
280read the generic header and fill the struct.
281****************************************************************************/
282static 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/*******************************************************************
294decode a start association request
295********************************************************************/
296static 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/*******************************************************************
307decode a start association reply
308********************************************************************/
309static 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/*******************************************************************
320decode a start association reply
321********************************************************************/
322static 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/****************************************************************************
331decode a packet and fill a generic structure
332****************************************************************************/
333void 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/****************************************************************************
359encode a WINS_OWNER struct
360****************************************************************************/
361static 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/****************************************************************************
382encode a WINS_NAME struct
383****************************************************************************/
384static 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/****************************************************************************
434encode a update notification request
435****************************************************************************/
436static 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/****************************************************************************
455decode a send entries request
456****************************************************************************/
457static 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/****************************************************************************
463decode a send entries reply
464****************************************************************************/
465static 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/****************************************************************************
481encode a add version number map table reply
482****************************************************************************/
483static 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/****************************************************************************
502decode a replicate packet and fill a structure
503****************************************************************************/
504static 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/****************************************************************************
538write the generic header.
539****************************************************************************/
540static 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/*******************************************************************
549decode a start association request
550********************************************************************/
551static 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/*******************************************************************
564decode a start association reply
565********************************************************************/
566static 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/*******************************************************************
579decode a start association reply
580********************************************************************/
581static 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/****************************************************************************
592write the generic header size.
593****************************************************************************/
594static 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/****************************************************************************
601encode a packet and read a generic structure
602****************************************************************************/
603void 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/****************************************************************************
634dump a WINS_OWNER structure
635****************************************************************************/
636static 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/****************************************************************************
645dump a WINS_NAME structure
646****************************************************************************/
647static 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/****************************************************************************
666dump a replicate structure
667****************************************************************************/
668static 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/****************************************************************************
709dump a generic structure
710****************************************************************************/
711void 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/****************************************************************************
748generate a stop packet
749****************************************************************************/
750void 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
760