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 static 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 if (buffer
->offset
+more
>= buffer
->length
) {
36 temp
=(char *)talloc_realloc(mem_ctx
, buffer
->buffer
, sizeof(char)* (buffer
->length
+256) );
38 DEBUG(0,("grow_buffer: can't grow buffer\n"));
48 /****************************************************************************
49 decode a WINS_OWNER struct
50 ****************************************************************************/
51 static int decode_wins_owner(char *inbuf
, int offset
, WINS_OWNER
*wins_owner
)
53 wins_owner
->address
.s_addr
=IVAL(inbuf
, offset
);
55 wins_owner
->max_version
=((SMB_BIG_UINT
)RIVAL(inbuf
, offset
))<<32;
57 wins_owner
->max_version
|=RIVAL(inbuf
, offset
);
59 wins_owner
->min_version
=((SMB_BIG_UINT
)RIVAL(inbuf
, offset
))<<32;
61 wins_owner
->min_version
|=RIVAL(inbuf
, offset
);
63 wins_owner
->type
=RIVAL(inbuf
, offset
);
69 /****************************************************************************
70 decode a WINS_NAME struct
71 ****************************************************************************/
72 static int decode_wins_name(char *outbuf
, int offset
, WINS_NAME
*wins_name
)
77 wins_name
->name_len
=RIVAL(outbuf
, offset
);
79 memcpy(wins_name
->name
,outbuf
+offset
, 15);
80 wins_name
->name
[16]='\0';
81 if((p
= strchr(wins_name
->name
,' ')) != NULL
)
86 wins_name
->type
=(int)outbuf
[offset
++];
89 * fix to bug in WINS replication,
90 * present in all versions including W2K SP2 !
92 if (wins_name
->name
[0]==0x1B) {
93 wins_name
->name
[0]=(char)wins_name
->type
;
97 wins_name
->empty
=RIVAL(outbuf
, offset
);
100 wins_name
->name_flag
=RIVAL(outbuf
, offset
);
102 wins_name
->group_flag
=RIVAL(outbuf
, offset
);
104 wins_name
->id
=((SMB_BIG_UINT
)RIVAL(outbuf
, offset
))<<32;
106 wins_name
->id
|=RIVAL(outbuf
, offset
);
109 /* special groups have multiple address */
110 if (wins_name
->name_flag
& 2) {
111 wins_name
->num_ip
=IVAL(outbuf
, offset
);
117 wins_name
->owner
.s_addr
=IVAL(outbuf
, offset
);
120 if (wins_name
->name_flag
& 2) {
121 wins_name
->others
=(struct in_addr
*)talloc(mem_ctx
, sizeof(struct in_addr
)*wins_name
->num_ip
);
122 if (wins_name
->others
==NULL
)
125 for (i
=0; i
<wins_name
->num_ip
; i
++) {
126 wins_name
->others
[i
].s_addr
=IVAL(outbuf
, offset
);
131 wins_name
->foo
=RIVAL(outbuf
, offset
);
137 /****************************************************************************
138 decode a update notification request
139 ****************************************************************************/
140 static void decode_update_notify_request(char *inbuf
, UPDATE_NOTIFY_REQUEST
*un_rq
)
145 un_rq
->partner_count
=RIVAL(inbuf
, 0);
147 un_rq
->wins_owner
=(WINS_OWNER
*)talloc(mem_ctx
, un_rq
->partner_count
*sizeof(WINS_OWNER
));
148 if (un_rq
->wins_owner
==NULL
)
151 for (i
=0; i
<un_rq
->partner_count
; i
++)
152 offset
=decode_wins_owner(inbuf
, offset
, &un_rq
->wins_owner
[i
]);
154 un_rq
->initiating_wins_server
.s_addr
=IVAL(inbuf
, offset
);
157 /****************************************************************************
158 decode a send entries request
159 ****************************************************************************/
160 static void decode_send_entries_request(char *inbuf
, SEND_ENTRIES_REQUEST
*se_rq
)
163 offset
=decode_wins_owner(inbuf
, 0, &se_rq
->wins_owner
);
166 /****************************************************************************
167 decode a send entries reply
168 ****************************************************************************/
169 static void decode_send_entries_reply(char *inbuf
, SEND_ENTRIES_REPLY
*se_rp
)
172 se_rp
->max_names
= RIVAL(inbuf
, 0);
174 se_rp
->wins_name
=(WINS_NAME
*)talloc(mem_ctx
, se_rp
->max_names
*sizeof(WINS_NAME
));
175 if (se_rp
->wins_name
==NULL
)
178 for (i
=0; i
<se_rp
->max_names
; i
++)
179 offset
= decode_wins_name(inbuf
, offset
, &se_rp
->wins_name
[i
]);
182 /****************************************************************************
183 decode a add version number map table reply
184 ****************************************************************************/
185 static void decode_add_version_number_map_table_reply(char *inbuf
, AVMT_REP
*avmt_rep
)
190 avmt_rep
->partner_count
=RIVAL(inbuf
, 0);
192 avmt_rep
->wins_owner
=(WINS_OWNER
*)talloc(mem_ctx
, avmt_rep
->partner_count
*sizeof(WINS_OWNER
));
193 if (avmt_rep
->wins_owner
==NULL
)
196 for (i
=0; i
<avmt_rep
->partner_count
; i
++)
197 offset
=decode_wins_owner(inbuf
, offset
, &avmt_rep
->wins_owner
[i
]);
199 avmt_rep
->initiating_wins_server
.s_addr
=IVAL(inbuf
, offset
);
202 /****************************************************************************
203 decode a replicate packet and fill a structure
204 ****************************************************************************/
205 static void decode_replicate(char *inbuf
, REPLICATE
*rep
)
207 rep
->msg_type
= RIVAL(inbuf
, 0);
209 switch (rep
->msg_type
) {
213 /* add version number map table reply */
214 decode_add_version_number_map_table_reply(inbuf
+4, &rep
->avmt_rep
);
217 /* send entry request */
218 decode_send_entries_request(inbuf
+4, &rep
->se_rq
);
221 /* send entry request */
222 decode_send_entries_reply(inbuf
+4, &rep
->se_rp
);
225 /* update notification request */
226 decode_update_notify_request(inbuf
+4, &rep
->un_rq
);
229 DEBUG(0,("decode_replicate: unknown message type:%d\n", rep
->msg_type
));
234 /****************************************************************************
235 read the generic header and fill the struct.
236 ****************************************************************************/
237 static void read_generic_header(char *inbuf
, generic_header
*q
)
239 q
->data_size
= RIVAL(inbuf
,0);
240 q
->opcode
= RIVAL(inbuf
,4);
241 q
->assoc_ctx
= RIVAL(inbuf
,8);
242 q
->mess_type
= RIVAL(inbuf
,12);
245 /*******************************************************************
246 decode a start association request
247 ********************************************************************/
248 static void decode_start_assoc_request(char *inbuf
, START_ASSOC_REQUEST
*q
)
250 q
->assoc_ctx
= RIVAL(inbuf
, 0);
251 q
->min_ver
= RSVAL(inbuf
, 4);
252 q
->maj_ver
= RSVAL(inbuf
, 6);
255 /*******************************************************************
256 decode a start association reply
257 ********************************************************************/
258 static void decode_start_assoc_reply(char *inbuf
, START_ASSOC_REPLY
*r
)
260 r
->assoc_ctx
=RIVAL(inbuf
, 0);
261 r
->min_ver
= RSVAL(inbuf
, 4);
262 r
->maj_ver
= RSVAL(inbuf
, 6);
265 /*******************************************************************
266 decode a start association reply
267 ********************************************************************/
268 static void decode_stop_assoc(char *inbuf
, STOP_ASSOC
*r
)
270 r
->reason
=RIVAL(inbuf
, 0);
273 /****************************************************************************
274 decode a packet and fill a generic structure
275 ****************************************************************************/
276 void decode_generic_packet(char *inbuf
, GENERIC_PACKET
*q
)
278 read_generic_header(inbuf
, &q
->header
);
280 switch (q
->header
.mess_type
) {
282 decode_start_assoc_request(inbuf
+16, &q
->sa_rq
);
285 decode_start_assoc_reply(inbuf
+16, &q
->sa_rp
);
288 decode_stop_assoc(inbuf
+16, &q
->so
);
291 decode_replicate(inbuf
+16, &q
->rep
);
294 DEBUG(0,("decode_generic_packet: unknown message type:%d\n", q
->header
.mess_type
));
299 static void encode_wins_owner(struct BUFFER
*outbuf
, WINS_OWNER
*wins_owner
)
301 if (!grow_buffer(outbuf
, 24))
304 SIVAL(outbuf
->buffer
, outbuf
->offset
, wins_owner
->address
.s_addr
);
306 RSIVAL(outbuf
->buffer
, outbuf
->offset
, (int)(wins_owner
->max_version
>>32));
308 RSIVAL(outbuf
->buffer
, outbuf
->offset
, (int)(wins_owner
->max_version
&0xffffffff));
310 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_owner
->min_version
>>32);
312 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_owner
->min_version
&0xffffffff);
314 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_owner
->type
);
319 static void encode_wins_name(struct BUFFER
*outbuf
, WINS_NAME
*wins_name
)
323 if (!grow_buffer(outbuf
, 48+(4*wins_name
->num_ip
)))
326 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->name_len
);
329 memset(outbuf
->buffer
+outbuf
->offset
, ' ', 15);
331 /* to prevent copying the leading \0 */
332 memcpy(outbuf
->buffer
+outbuf
->offset
, wins_name
->name
, strlen(wins_name
->name
));
335 outbuf
->buffer
[outbuf
->offset
++]=(char)wins_name
->type
;
337 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->empty
);
340 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->name_flag
);
342 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->group_flag
);
344 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->id
>>32);
346 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->id
);
349 if (wins_name
->name_flag
& 2) {
350 SIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->num_ip
);
354 SIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->owner
.s_addr
);
357 if (wins_name
->name_flag
& 2) {
358 for (i
=0;i
<wins_name
->num_ip
;i
++) {
359 SIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->others
[i
].s_addr
);
364 RSIVAL(outbuf
->buffer
, outbuf
->offset
, wins_name
->foo
);
368 /****************************************************************************
369 decode a update notification request
370 ****************************************************************************/
371 static void encode_update_notify_request(struct BUFFER
*outbuf
, UPDATE_NOTIFY_REQUEST
*un_rq
)
375 if (!grow_buffer(outbuf
, 8))
378 RSIVAL(outbuf
->buffer
, outbuf
->offset
, un_rq
->partner_count
);
381 for (i
=0; i
<un_rq
->partner_count
; i
++)
382 encode_wins_owner(outbuf
, &un_rq
->wins_owner
[i
]);
384 SIVAL(outbuf
->buffer
, outbuf
->offset
, un_rq
->initiating_wins_server
.s_addr
);
389 /****************************************************************************
390 decode a send entries request
391 ****************************************************************************/
392 static void encode_send_entries_request(struct BUFFER
*outbuf
, SEND_ENTRIES_REQUEST
*se_rq
)
394 encode_wins_owner(outbuf
, &se_rq
->wins_owner
);
397 /****************************************************************************
398 decode a send entries reply
399 ****************************************************************************/
400 static void encode_send_entries_reply(struct BUFFER
*outbuf
, SEND_ENTRIES_REPLY
*se_rp
)
404 if (!grow_buffer(outbuf
, 4))
407 RSIVAL(outbuf
->buffer
, outbuf
->offset
, se_rp
->max_names
);
410 for (i
=0; i
<se_rp
->max_names
; i
++)
411 encode_wins_name(outbuf
, &se_rp
->wins_name
[i
]);
415 /****************************************************************************
416 encode a add version number map table reply
417 ****************************************************************************/
418 static void encode_add_version_number_map_table_reply(struct BUFFER
*outbuf
, AVMT_REP
*avmt_rep
)
422 if (!grow_buffer(outbuf
, 8))
425 RSIVAL(outbuf
->buffer
, outbuf
->offset
, avmt_rep
->partner_count
);
428 for (i
=0; i
<avmt_rep
->partner_count
; i
++)
429 encode_wins_owner(outbuf
, &avmt_rep
->wins_owner
[i
]);
431 SIVAL(outbuf
->buffer
, outbuf
->offset
, avmt_rep
->initiating_wins_server
.s_addr
);
436 /****************************************************************************
437 decode a replicate packet and fill a structure
438 ****************************************************************************/
439 static void encode_replicate(struct BUFFER
*outbuf
, REPLICATE
*rep
)
441 if (!grow_buffer(outbuf
, 4))
444 RSIVAL(outbuf
->buffer
, outbuf
->offset
, rep
->msg_type
);
447 switch (rep
->msg_type
) {
451 /* add version number map table reply */
452 encode_add_version_number_map_table_reply(outbuf
, &rep
->avmt_rep
);
455 /* send entry request */
456 encode_send_entries_request(outbuf
, &rep
->se_rq
);
459 /* send entry request */
460 encode_send_entries_reply(outbuf
, &rep
->se_rp
);
463 /* update notification request */
464 encode_update_notify_request(outbuf
, &rep
->un_rq
);
467 DEBUG(0,("decode_replicate: unknown message type:%d\n", rep
->msg_type
));
472 /****************************************************************************
473 write the generic header.
474 ****************************************************************************/
475 static void write_generic_header(struct BUFFER
*outbuf
, generic_header
*r
)
477 RSIVAL(outbuf
->buffer
, 0, r
->data_size
);
478 RSIVAL(outbuf
->buffer
, 4, r
->opcode
);
479 RSIVAL(outbuf
->buffer
, 8, r
->assoc_ctx
);
480 RSIVAL(outbuf
->buffer
,12, r
->mess_type
);
483 /*******************************************************************
484 decode a start association request
485 ********************************************************************/
486 static void encode_start_assoc_request(struct BUFFER
*outbuf
, START_ASSOC_REQUEST
*q
)
488 if (!grow_buffer(outbuf
, 45))
491 RSIVAL(outbuf
->buffer
, outbuf
->offset
, q
->assoc_ctx
);
492 RSSVAL(outbuf
->buffer
, outbuf
->offset
+4, q
->min_ver
);
493 RSSVAL(outbuf
->buffer
, outbuf
->offset
+6, q
->maj_ver
);
498 /*******************************************************************
499 decode a start association reply
500 ********************************************************************/
501 static void encode_start_assoc_reply(struct BUFFER
*outbuf
, START_ASSOC_REPLY
*r
)
503 if (!grow_buffer(outbuf
, 45))
506 RSIVAL(outbuf
->buffer
, outbuf
->offset
, r
->assoc_ctx
);
507 RSSVAL(outbuf
->buffer
, outbuf
->offset
+4, r
->min_ver
);
508 RSSVAL(outbuf
->buffer
, outbuf
->offset
+6, r
->maj_ver
);
513 /*******************************************************************
514 decode a start association reply
515 ********************************************************************/
516 static void encode_stop_assoc(struct BUFFER
*outbuf
, STOP_ASSOC
*r
)
518 if (!grow_buffer(outbuf
, 44))
521 RSIVAL(outbuf
->buffer
, outbuf
->offset
, r
->reason
);
526 /****************************************************************************
527 write the generic header size.
528 ****************************************************************************/
529 static void write_generic_header_size(generic_header
*r
, int size
)
531 /* the buffer size is the total size minus the size field */
535 /****************************************************************************
536 encode a packet and read a generic structure
537 ****************************************************************************/
538 void encode_generic_packet(struct BUFFER
*outbuf
, GENERIC_PACKET
*q
)
540 if (!grow_buffer(outbuf
, 16))
545 switch (q
->header
.mess_type
) {
547 encode_start_assoc_request(outbuf
, &q
->sa_rq
);
550 encode_start_assoc_reply(outbuf
, &q
->sa_rp
);
553 encode_stop_assoc(outbuf
, &q
->so
);
556 encode_replicate(outbuf
, &q
->rep
);
559 DEBUG(0,("encode_generic_packet: unknown message type:%d\n", q
->header
.mess_type
));
563 write_generic_header_size(&q
->header
, outbuf
->offset
);
564 write_generic_header(outbuf
, &q
->header
);
568 /****************************************************************************
569 dump a WINS_OWNER structure
570 ****************************************************************************/
571 static void dump_wins_owner(WINS_OWNER
*wins_owner
)
573 DEBUGADD(10,("\t\t\t\taddress : %s\n", inet_ntoa(wins_owner
->address
)));
574 DEBUGADD(10,("\t\t\t\tmax version: %d\n", (int)wins_owner
->max_version
));
575 DEBUGADD(10,("\t\t\t\tmin version: %d\n", (int)wins_owner
->min_version
));
576 DEBUGADD(10,("\t\t\t\ttype : %d\n", wins_owner
->type
));
579 /****************************************************************************
580 dump a WINS_NAME structure
581 ****************************************************************************/
582 static void dump_wins_name(WINS_NAME
*wins_name
)
587 strncpy(name
, wins_name
->name
, 15);
589 DEBUGADD(10,("name: %d, %s<%02x> %x,%x, %d %s %d ", wins_name
->name_len
, name
, wins_name
->type
,
590 wins_name
->name_flag
, wins_name
->group_flag
, (int)wins_name
->id
,
591 inet_ntoa(wins_name
->owner
), wins_name
->num_ip
));
593 if (wins_name
->num_ip
!=1)
594 for (i
=0; i
<wins_name
->num_ip
; i
++)
595 DEBUGADD(10,("%s ", inet_ntoa(wins_name
->others
[i
])));
600 /****************************************************************************
601 dump a replicate structure
602 ****************************************************************************/
603 static void dump_replicate(REPLICATE
*rep
)
607 DEBUGADD(5,("\t\tmsg_type: %d ", rep
->msg_type
));
609 switch (rep
->msg_type
) {
611 DEBUGADD(5,("(Add Version Map Table Request)\n"));
614 DEBUGADD(5,("(Add Version Map Table Reply)\n"));
615 DEBUGADD(5,("\t\t\tpartner_count : %d\n", rep
->avmt_rep
.partner_count
));
616 for (i
=0; i
<rep
->avmt_rep
.partner_count
; i
++)
617 dump_wins_owner(&rep
->avmt_rep
.wins_owner
[i
]);
618 DEBUGADD(5,("\t\t\tinitiating_wins_server: %s\n", inet_ntoa(rep
->avmt_rep
.initiating_wins_server
)));
621 DEBUGADD(5,("(Send Entries Request)\n"));
622 dump_wins_owner(&rep
->se_rq
.wins_owner
);
625 DEBUGADD(5,("(Send Entries Reply)\n"));
626 DEBUGADD(5,("\t\t\tmax_names : %d\n", rep
->se_rp
.max_names
));
627 for (i
=0; i
<rep
->se_rp
.max_names
; i
++)
628 dump_wins_name(&rep
->se_rp
.wins_name
[i
]);
631 DEBUGADD(5,("(Update Notify Request)\n"));
632 DEBUGADD(5,("\t\t\tpartner_count : %d\n", rep
->un_rq
.partner_count
));
633 for (i
=0; i
<rep
->un_rq
.partner_count
; i
++)
634 dump_wins_owner(&rep
->un_rq
.wins_owner
[i
]);
635 DEBUGADD(5,("\t\t\tinitiating_wins_server: %s\n", inet_ntoa(rep
->un_rq
.initiating_wins_server
)));
643 /****************************************************************************
644 dump a generic structure
645 ****************************************************************************/
646 void dump_generic_packet(GENERIC_PACKET
*q
)
648 DEBUG(5,("dump_generic_packet:\n"));
649 DEBUGADD(5,("\tdata_size: %08x\n", q
->header
.data_size
));
650 DEBUGADD(5,("\topcode : %08x\n", q
->header
.opcode
));
651 DEBUGADD(5,("\tassoc_ctx: %08x\n", q
->header
.assoc_ctx
));
652 DEBUGADD(5,("\tmess_type: %08x ", q
->header
.mess_type
));
654 switch (q
->header
.mess_type
) {
656 DEBUGADD(5,("(Start Association Request)\n"));
657 DEBUGADD(5,("\t\tassoc_ctx: %08x\n", q
->sa_rq
.assoc_ctx
));
658 DEBUGADD(5,("\t\tmin_ver : %04x\n", q
->sa_rq
.min_ver
));
659 DEBUGADD(5,("\t\tmaj_ver : %04x\n", q
->sa_rq
.maj_ver
));
662 DEBUGADD(5,("(Start Association Reply)\n"));
663 DEBUGADD(5,("\t\tassoc_ctx: %08x\n", q
->sa_rp
.assoc_ctx
));
664 DEBUGADD(5,("\t\tmin_ver : %04x\n", q
->sa_rp
.min_ver
));
665 DEBUGADD(5,("\t\tmaj_ver : %04x\n", q
->sa_rp
.maj_ver
));
668 DEBUGADD(5,("(Stop Association)\n"));
669 DEBUGADD(5,("\t\treason: %08x\n", q
->so
.reason
));
672 DEBUGADD(5,("(Replication Message)\n"));
673 dump_replicate(&q
->rep
);
682 /****************************************************************************
683 generate a stop packet
684 ****************************************************************************/
685 void stop_packet(GENERIC_PACKET
*q
, GENERIC_PACKET
*r
, int reason
)
687 r
->header
.opcode
=OPCODE_NON_NBT
;
688 r
->header
.assoc_ctx
=get_server_assoc(q
->header
.assoc_ctx
);
689 r
->header
.mess_type
=MESSAGE_TYPE_STOP_ASSOC
;