2
* Unix SMB/CIFS implementation.
3
* RPC Pipe client / server routines
4
* Copyright (C) Jean Fran�ois Micouleau 1998-2002.
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.
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.
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.
22
#include "wins_repl.h"
24
extern TALLOC_CTX *mem_ctx;
26
/****************************************************************************
27
grow the send buffer if necessary
28
****************************************************************************/
29
BOOL grow_buffer(struct BUFFER *buffer, int more)
33
DEBUG(10,("grow_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more));
35
/* grow by at least 256 bytes */
39
if (buffer->offset+more >= buffer->length) {
40
temp=talloc_realloc(mem_ctx, buffer->buffer, char, buffer->length + more);
42
DEBUG(0,("grow_buffer: can't grow buffer\n"));
52
/****************************************************************************
53
check if the buffer has that much data
54
****************************************************************************/
55
static BOOL check_buffer(struct BUFFER *buffer, int more)
57
DEBUG(10,("check_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more));
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));
67
/****************************************************************************
68
decode a WINS_OWNER struct
69
****************************************************************************/
70
static void decode_wins_owner(struct BUFFER *inbuf, WINS_OWNER *wins_owner)
72
if(!check_buffer(inbuf, 24))
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);
85
/****************************************************************************
86
decode a WINS_NAME struct
87
****************************************************************************/
88
static void decode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name)
93
if(!check_buffer(outbuf, 40))
96
wins_name->name_len=RIVAL(outbuf->buffer, outbuf->offset);
98
memcpy(wins_name->name,outbuf->buffer+outbuf->offset, 15);
99
wins_name->name[15]='\0';
100
if((p = strchr(wins_name->name,' ')) != NULL)
105
wins_name->type=(int)outbuf->buffer[outbuf->offset++];
108
* fix to bug in WINS replication,
109
* present in all versions including W2K SP2 !
111
if (wins_name->name[0]==0x1B) {
112
wins_name->name[0]=(char)wins_name->type;
113
wins_name->type=0x1B;
116
wins_name->empty=RIVAL(outbuf->buffer, outbuf->offset);
119
wins_name->name_flag=RIVAL(outbuf->buffer, outbuf->offset);
121
wins_name->group_flag=RIVAL(outbuf->buffer, outbuf->offset);
123
wins_name->id=((SMB_BIG_UINT)RIVAL(outbuf->buffer, outbuf->offset))<<32;
125
wins_name->id|=RIVAL(outbuf->buffer, outbuf->offset);
128
/* special groups have multiple address */
129
if (wins_name->name_flag & 2) {
130
if(!check_buffer(outbuf, 4))
132
wins_name->num_ip=IVAL(outbuf->buffer, outbuf->offset);
138
if(!check_buffer(outbuf, 4))
140
wins_name->owner.s_addr=IVAL(outbuf->buffer, outbuf->offset);
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)
148
if(!check_buffer(outbuf, 4*wins_name->num_ip))
150
for (i=0; i<wins_name->num_ip; i++) {
151
wins_name->others[i].s_addr=IVAL(outbuf->buffer, outbuf->offset);
156
if(!check_buffer(outbuf, 4))
158
wins_name->foo=RIVAL(outbuf->buffer, outbuf->offset);
163
/****************************************************************************
164
decode a update notification request
165
****************************************************************************/
166
static void decode_update_notify_request(struct BUFFER *inbuf, UPDATE_NOTIFY_REQUEST *un_rq)
170
if(!check_buffer(inbuf, 4))
172
un_rq->partner_count=RIVAL(inbuf->buffer, inbuf->offset);
175
un_rq->wins_owner=talloc_array(mem_ctx, WINS_OWNER, un_rq->partner_count);
176
if (un_rq->wins_owner==NULL)
179
for (i=0; i<un_rq->partner_count; i++)
180
decode_wins_owner(inbuf, &un_rq->wins_owner[i]);
182
if(!check_buffer(inbuf, 4))
184
un_rq->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset);
188
/****************************************************************************
189
decode a send entries request
190
****************************************************************************/
191
static void decode_send_entries_request(struct BUFFER *inbuf, SEND_ENTRIES_REQUEST *se_rq)
193
decode_wins_owner(inbuf, &se_rq->wins_owner);
196
/****************************************************************************
197
decode a send entries reply
198
****************************************************************************/
199
static void decode_send_entries_reply(struct BUFFER *inbuf, SEND_ENTRIES_REPLY *se_rp)
203
if(!check_buffer(inbuf, 4))
205
se_rp->max_names = RIVAL(inbuf->buffer, inbuf->offset);
208
se_rp->wins_name=talloc_array(mem_ctx, WINS_NAME, se_rp->max_names);
209
if (se_rp->wins_name==NULL)
212
for (i=0; i<se_rp->max_names; i++)
213
decode_wins_name(inbuf, &se_rp->wins_name[i]);
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)
223
if(!check_buffer(inbuf, 4))
226
avmt_rep->partner_count=RIVAL(inbuf->buffer, inbuf->offset);
229
avmt_rep->wins_owner=talloc_array(mem_ctx, WINS_OWNER, avmt_rep->partner_count);
230
if (avmt_rep->wins_owner==NULL)
233
for (i=0; i<avmt_rep->partner_count; i++)
234
decode_wins_owner(inbuf, &avmt_rep->wins_owner[i]);
236
if(!check_buffer(inbuf, 4))
238
avmt_rep->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset);
242
/****************************************************************************
243
decode a replicate packet and fill a structure
244
****************************************************************************/
245
static void decode_replicate(struct BUFFER *inbuf, REPLICATE *rep)
247
if(!check_buffer(inbuf, 4))
250
rep->msg_type = RIVAL(inbuf->buffer, inbuf->offset);
254
switch (rep->msg_type) {
258
/* add version number map table reply */
259
decode_add_version_number_map_table_reply(inbuf, &rep->avmt_rep);
262
/* send entry request */
263
decode_send_entries_request(inbuf, &rep->se_rq);
266
/* send entry request */
267
decode_send_entries_reply(inbuf, &rep->se_rp);
270
/* update notification request */
271
decode_update_notify_request(inbuf, &rep->un_rq);
274
DEBUG(0,("decode_replicate: unknown message type:%d\n", rep->msg_type));
279
/****************************************************************************
280
read the generic header and fill the struct.
281
****************************************************************************/
282
static void read_generic_header(struct BUFFER *inbuf, generic_header *q)
284
if(!check_buffer(inbuf, 16))
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);
293
/*******************************************************************
294
decode a start association request
295
********************************************************************/
296
static void decode_start_assoc_request(struct BUFFER *inbuf, START_ASSOC_REQUEST *q)
298
if(!check_buffer(inbuf, 8))
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);
306
/*******************************************************************
307
decode a start association reply
308
********************************************************************/
309
static void decode_start_assoc_reply(struct BUFFER *inbuf, START_ASSOC_REPLY *r)
311
if(!check_buffer(inbuf, 8))
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);
319
/*******************************************************************
320
decode a start association reply
321
********************************************************************/
322
static void decode_stop_assoc(struct BUFFER *inbuf, STOP_ASSOC *r)
324
if(!check_buffer(inbuf, 4))
327
r->reason=RIVAL(inbuf->buffer, inbuf->offset);
330
/****************************************************************************
331
decode a packet and fill a generic structure
332
****************************************************************************/
333
void decode_generic_packet(struct BUFFER *inbuf, GENERIC_PACKET *q)
335
read_generic_header(inbuf, &q->header);
339
switch (q->header.mess_type) {
341
decode_start_assoc_request(inbuf, &q->sa_rq);
344
decode_start_assoc_reply(inbuf, &q->sa_rp);
347
decode_stop_assoc(inbuf, &q->so);
350
decode_replicate(inbuf, &q->rep);
353
DEBUG(0,("decode_generic_packet: unknown message type:%d\n", q->header.mess_type));
358
/****************************************************************************
359
encode a WINS_OWNER struct
360
****************************************************************************/
361
static void encode_wins_owner(struct BUFFER *outbuf, WINS_OWNER *wins_owner)
363
if (!grow_buffer(outbuf, 24))
366
SIVAL(outbuf->buffer, outbuf->offset, wins_owner->address.s_addr);
368
RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version>>32));
370
RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version&0xffffffff));
372
RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version>>32);
374
RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version&0xffffffff);
376
RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->type);
381
/****************************************************************************
382
encode a WINS_NAME struct
383
****************************************************************************/
384
static void encode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name)
388
if (!grow_buffer(outbuf, 48+(4*wins_name->num_ip)))
391
RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_len);
394
memset(outbuf->buffer+outbuf->offset, ' ', 15);
396
/* to prevent copying the leading \0 */
397
memcpy(outbuf->buffer+outbuf->offset, wins_name->name, strlen(wins_name->name));
400
outbuf->buffer[outbuf->offset++]=(char)wins_name->type;
402
RSIVAL(outbuf->buffer, outbuf->offset, wins_name->empty);
405
RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_flag);
407
RSIVAL(outbuf->buffer, outbuf->offset, wins_name->group_flag);
409
RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id>>32);
411
RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id);
414
if (wins_name->name_flag & 2) {
415
SIVAL(outbuf->buffer, outbuf->offset, wins_name->num_ip);
419
SIVAL(outbuf->buffer, outbuf->offset, wins_name->owner.s_addr);
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);
429
RSIVAL(outbuf->buffer, outbuf->offset, wins_name->foo);
433
/****************************************************************************
434
encode a update notification request
435
****************************************************************************/
436
static void encode_update_notify_request(struct BUFFER *outbuf, UPDATE_NOTIFY_REQUEST *un_rq)
440
if (!grow_buffer(outbuf, 8))
443
RSIVAL(outbuf->buffer, outbuf->offset, un_rq->partner_count);
446
for (i=0; i<un_rq->partner_count; i++)
447
encode_wins_owner(outbuf, &un_rq->wins_owner[i]);
449
SIVAL(outbuf->buffer, outbuf->offset, un_rq->initiating_wins_server.s_addr);
454
/****************************************************************************
455
decode a send entries request
456
****************************************************************************/
457
static void encode_send_entries_request(struct BUFFER *outbuf, SEND_ENTRIES_REQUEST *se_rq)
459
encode_wins_owner(outbuf, &se_rq->wins_owner);
462
/****************************************************************************
463
decode a send entries reply
464
****************************************************************************/
465
static void encode_send_entries_reply(struct BUFFER *outbuf, SEND_ENTRIES_REPLY *se_rp)
469
if (!grow_buffer(outbuf, 4))
472
RSIVAL(outbuf->buffer, outbuf->offset, se_rp->max_names);
475
for (i=0; i<se_rp->max_names; i++)
476
encode_wins_name(outbuf, &se_rp->wins_name[i]);
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)
487
if (!grow_buffer(outbuf, 8))
490
RSIVAL(outbuf->buffer, outbuf->offset, avmt_rep->partner_count);
493
for (i=0; i<avmt_rep->partner_count; i++)
494
encode_wins_owner(outbuf, &avmt_rep->wins_owner[i]);
496
SIVAL(outbuf->buffer, outbuf->offset, avmt_rep->initiating_wins_server.s_addr);
501
/****************************************************************************
502
decode a replicate packet and fill a structure
503
****************************************************************************/
504
static void encode_replicate(struct BUFFER *outbuf, REPLICATE *rep)
506
if (!grow_buffer(outbuf, 4))
509
RSIVAL(outbuf->buffer, outbuf->offset, rep->msg_type);
512
switch (rep->msg_type) {
516
/* add version number map table reply */
517
encode_add_version_number_map_table_reply(outbuf, &rep->avmt_rep);
520
/* send entry request */
521
encode_send_entries_request(outbuf, &rep->se_rq);
524
/* send entry request */
525
encode_send_entries_reply(outbuf, &rep->se_rp);
528
/* update notification request */
529
encode_update_notify_request(outbuf, &rep->un_rq);
532
DEBUG(0,("encode_replicate: unknown message type:%d\n", rep->msg_type));
537
/****************************************************************************
538
write the generic header.
539
****************************************************************************/
540
static void write_generic_header(struct BUFFER *outbuf, generic_header *r)
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);
548
/*******************************************************************
549
decode a start association request
550
********************************************************************/
551
static void encode_start_assoc_request(struct BUFFER *outbuf, START_ASSOC_REQUEST *q)
553
if (!grow_buffer(outbuf, 45))
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);
563
/*******************************************************************
564
decode a start association reply
565
********************************************************************/
566
static void encode_start_assoc_reply(struct BUFFER *outbuf, START_ASSOC_REPLY *r)
568
if (!grow_buffer(outbuf, 45))
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);
578
/*******************************************************************
579
decode a start association reply
580
********************************************************************/
581
static void encode_stop_assoc(struct BUFFER *outbuf, STOP_ASSOC *r)
583
if (!grow_buffer(outbuf, 44))
586
RSIVAL(outbuf->buffer, outbuf->offset, r->reason);
591
/****************************************************************************
592
write the generic header size.
593
****************************************************************************/
594
static void write_generic_header_size(generic_header *r, int size)
596
/* the buffer size is the total size minus the size field */
600
/****************************************************************************
601
encode a packet and read a generic structure
602
****************************************************************************/
603
void encode_generic_packet(struct BUFFER *outbuf, GENERIC_PACKET *q)
605
if (!grow_buffer(outbuf, 16))
610
switch (q->header.mess_type) {
612
encode_start_assoc_request(outbuf, &q->sa_rq);
615
encode_start_assoc_reply(outbuf, &q->sa_rp);
618
encode_stop_assoc(outbuf, &q->so);
621
encode_replicate(outbuf, &q->rep);
624
DEBUG(0,("encode_generic_packet: unknown message type:%d\n", q->header.mess_type));
628
write_generic_header_size(&q->header, outbuf->offset);
629
write_generic_header(outbuf, &q->header);
633
/****************************************************************************
634
dump a WINS_OWNER structure
635
****************************************************************************/
636
static void dump_wins_owner(WINS_OWNER *wins_owner)
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));
644
/****************************************************************************
645
dump a WINS_NAME structure
646
****************************************************************************/
647
static void dump_wins_name(WINS_NAME *wins_name)
652
strncpy(name, wins_name->name, 15);
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));
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])));
665
/****************************************************************************
666
dump a replicate structure
667
****************************************************************************/
668
static void dump_replicate(REPLICATE *rep)
672
DEBUGADD(5,("\t\tmsg_type: %d ", rep->msg_type));
674
switch (rep->msg_type) {
676
DEBUGADD(5,("(Add Version Map Table Request)\n"));
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)));
686
DEBUGADD(5,("(Send Entries Request)\n"));
687
dump_wins_owner(&rep->se_rq.wins_owner);
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]);
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)));
708
/****************************************************************************
709
dump a generic structure
710
****************************************************************************/
711
void dump_generic_packet(GENERIC_PACKET *q)
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));
719
switch (q->header.mess_type) {
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));
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));
733
DEBUGADD(5,("(Stop Association)\n"));
734
DEBUGADD(5,("\t\treason: %08x\n", q->so.reason));
737
DEBUGADD(5,("(Replication Message)\n"));
738
dump_replicate(&q->rep);
747
/****************************************************************************
748
generate a stop packet
749
****************************************************************************/
750
void stop_packet(GENERIC_PACKET *q, GENERIC_PACKET *r, int reason)
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;