merge from APPLIANCE_HEAD
[Samba.git] / source / wrepld / parser.c
blob61d8a604cee02baad6634ec2c077fd4f8d8e59ae
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.
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.
21 #include "includes.h"
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)
31 char *temp;
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) );
37 if (temp==NULL) {
38 DEBUG(0,("grow_buffer: can't grow buffer\n"));
39 return False;
41 buffer->length+=256;
42 buffer->buffer=temp;
45 return True;
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);
54 offset+=4;
55 wins_owner->max_version=((SMB_BIG_UINT)RIVAL(inbuf, offset))<<32;
56 offset+=4;
57 wins_owner->max_version|=RIVAL(inbuf, offset);
58 offset+=4;
59 wins_owner->min_version=((SMB_BIG_UINT)RIVAL(inbuf, offset))<<32;
60 offset+=4;
61 wins_owner->min_version|=RIVAL(inbuf, offset);
62 offset+=4;
63 wins_owner->type=RIVAL(inbuf, offset);
64 offset+=4;
66 return offset;
69 /****************************************************************************
70 decode a WINS_NAME struct
71 ****************************************************************************/
72 static int decode_wins_name(char *outbuf, int offset, WINS_NAME *wins_name)
74 char *p;
75 int i;
77 wins_name->name_len=RIVAL(outbuf, offset);
78 offset+=4;
79 memcpy(wins_name->name,outbuf+offset, 15);
80 wins_name->name[16]='\0';
81 if((p = strchr(wins_name->name,' ')) != NULL)
82 *p = 0;
84 offset+=15;
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;
94 wins_name->type=0x1B;
97 wins_name->empty=RIVAL(outbuf, offset);
98 offset+=4;
100 wins_name->name_flag=RIVAL(outbuf, offset);
101 offset+=4;
102 wins_name->group_flag=RIVAL(outbuf, offset);
103 offset+=4;
104 wins_name->id=((SMB_BIG_UINT)RIVAL(outbuf, offset))<<32;
105 offset+=4;
106 wins_name->id|=RIVAL(outbuf, offset);
107 offset+=4;
109 /* special groups have multiple address */
110 if (wins_name->name_flag & 2) {
111 wins_name->num_ip=IVAL(outbuf, offset);
112 offset+=4;
114 else
115 wins_name->num_ip=1;
117 wins_name->owner.s_addr=IVAL(outbuf, offset);
118 offset+=4;
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)
123 return offset;
125 for (i=0; i<wins_name->num_ip; i++) {
126 wins_name->others[i].s_addr=IVAL(outbuf, offset);
127 offset+=4;
131 wins_name->foo=RIVAL(outbuf, offset);
132 offset+=4;
134 return offset;
137 /****************************************************************************
138 decode a update notification request
139 ****************************************************************************/
140 static void decode_update_notify_request(char *inbuf, UPDATE_NOTIFY_REQUEST *un_rq)
142 int i;
143 int offset=4;
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)
149 return;
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)
162 int offset;
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)
171 int i, offset=4;
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)
176 return;
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)
187 int i;
188 int offset=4;
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)
194 return;
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) {
210 case 0:
211 break;
212 case 1:
213 /* add version number map table reply */
214 decode_add_version_number_map_table_reply(inbuf+4, &rep->avmt_rep);
215 break;
216 case 2:
217 /* send entry request */
218 decode_send_entries_request(inbuf+4, &rep->se_rq);
219 break;
220 case 3:
221 /* send entry request */
222 decode_send_entries_reply(inbuf+4, &rep->se_rp);
223 break;
224 case 4:
225 /* update notification request */
226 decode_update_notify_request(inbuf+4, &rep->un_rq);
227 break;
228 default:
229 DEBUG(0,("decode_replicate: unknown message type:%d\n", rep->msg_type));
230 break;
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) {
281 case 0:
282 decode_start_assoc_request(inbuf+16, &q->sa_rq);
283 break;
284 case 1:
285 decode_start_assoc_reply(inbuf+16, &q->sa_rp);
286 break;
287 case 2:
288 decode_stop_assoc(inbuf+16, &q->so);
289 break;
290 case 3:
291 decode_replicate(inbuf+16, &q->rep);
292 break;
293 default:
294 DEBUG(0,("decode_generic_packet: unknown message type:%d\n", q->header.mess_type));
295 break;
299 static void encode_wins_owner(struct BUFFER *outbuf, WINS_OWNER *wins_owner)
301 if (!grow_buffer(outbuf, 24))
302 return;
304 SIVAL(outbuf->buffer, outbuf->offset, wins_owner->address.s_addr);
305 outbuf->offset+=4;
306 RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version>>32));
307 outbuf->offset+=4;
308 RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version&0xffffffff));
309 outbuf->offset+=4;
310 RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version>>32);
311 outbuf->offset+=4;
312 RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version&0xffffffff);
313 outbuf->offset+=4;
314 RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->type);
315 outbuf->offset+=4;
319 static void encode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name)
321 int i;
323 if (!grow_buffer(outbuf, 48+(4*wins_name->num_ip)))
324 return;
326 RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_len);
327 outbuf->offset+=4;
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));
333 outbuf->offset+=15;
335 outbuf->buffer[outbuf->offset++]=(char)wins_name->type;
337 RSIVAL(outbuf->buffer, outbuf->offset, wins_name->empty);
338 outbuf->offset+=4;
340 RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_flag);
341 outbuf->offset+=4;
342 RSIVAL(outbuf->buffer, outbuf->offset, wins_name->group_flag);
343 outbuf->offset+=4;
344 RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id>>32);
345 outbuf->offset+=4;
346 RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id);
347 outbuf->offset+=4;
349 if (wins_name->name_flag & 2) {
350 SIVAL(outbuf->buffer, outbuf->offset, wins_name->num_ip);
351 outbuf->offset+=4;
354 SIVAL(outbuf->buffer, outbuf->offset, wins_name->owner.s_addr);
355 outbuf->offset+=4;
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);
360 outbuf->offset+=4;
364 RSIVAL(outbuf->buffer, outbuf->offset, wins_name->foo);
365 outbuf->offset+=4;
368 /****************************************************************************
369 decode a update notification request
370 ****************************************************************************/
371 static void encode_update_notify_request(struct BUFFER *outbuf, UPDATE_NOTIFY_REQUEST *un_rq)
373 int i;
375 if (!grow_buffer(outbuf, 8))
376 return;
378 RSIVAL(outbuf->buffer, outbuf->offset, un_rq->partner_count);
379 outbuf->offset+=4;
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);
385 outbuf->offset+=4;
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)
402 int i;
404 if (!grow_buffer(outbuf, 4))
405 return;
407 RSIVAL(outbuf->buffer, outbuf->offset, se_rp->max_names);
408 outbuf->offset+=4;
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)
420 int i;
422 if (!grow_buffer(outbuf, 8))
423 return;
425 RSIVAL(outbuf->buffer, outbuf->offset, avmt_rep->partner_count);
426 outbuf->offset+=4;
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);
432 outbuf->offset+=4;
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))
442 return;
444 RSIVAL(outbuf->buffer, outbuf->offset, rep->msg_type);
445 outbuf->offset+=4;
447 switch (rep->msg_type) {
448 case 0:
449 break;
450 case 1:
451 /* add version number map table reply */
452 encode_add_version_number_map_table_reply(outbuf, &rep->avmt_rep);
453 break;
454 case 2:
455 /* send entry request */
456 encode_send_entries_request(outbuf, &rep->se_rq);
457 break;
458 case 3:
459 /* send entry request */
460 encode_send_entries_reply(outbuf, &rep->se_rp);
461 break;
462 case 4:
463 /* update notification request */
464 encode_update_notify_request(outbuf, &rep->un_rq);
465 break;
466 default:
467 DEBUG(0,("decode_replicate: unknown message type:%d\n", rep->msg_type));
468 break;
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))
489 return;
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);
495 outbuf->offset=45;
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))
504 return;
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);
510 outbuf->offset=45;
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))
519 return;
521 RSIVAL(outbuf->buffer, outbuf->offset, r->reason);
523 outbuf->offset=44;
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 */
532 r->data_size=size-4;
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))
541 return;
543 outbuf->offset=16;
545 switch (q->header.mess_type) {
546 case 0:
547 encode_start_assoc_request(outbuf, &q->sa_rq);
548 break;
549 case 1:
550 encode_start_assoc_reply(outbuf, &q->sa_rp);
551 break;
552 case 2:
553 encode_stop_assoc(outbuf, &q->so);
554 break;
555 case 3:
556 encode_replicate(outbuf, &q->rep);
557 break;
558 default:
559 DEBUG(0,("encode_generic_packet: unknown message type:%d\n", q->header.mess_type));
560 break;
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)
584 fstring name;
585 int i;
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])));
597 DEBUGADD(10,("\n"));
600 /****************************************************************************
601 dump a replicate structure
602 ****************************************************************************/
603 static void dump_replicate(REPLICATE *rep)
605 int i;
607 DEBUGADD(5,("\t\tmsg_type: %d ", rep->msg_type));
609 switch (rep->msg_type) {
610 case 0:
611 DEBUGADD(5,("(Add Version Map Table Request)\n"));
612 break;
613 case 1:
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)));
619 break;
620 case 2:
621 DEBUGADD(5,("(Send Entries Request)\n"));
622 dump_wins_owner(&rep->se_rq.wins_owner);
623 break;
624 case 3:
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]);
629 break;
630 case 4:
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)));
636 break;
637 default:
638 DEBUG(5,("\n"));
639 break;
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) {
655 case 0:
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));
660 break;
661 case 1:
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));
666 break;
667 case 2:
668 DEBUGADD(5,("(Stop Association)\n"));
669 DEBUGADD(5,("\t\treason: %08x\n", q->so.reason));
670 break;
671 case 3:
672 DEBUGADD(5,("(Replication Message)\n"));
673 dump_replicate(&q->rep);
674 break;
675 default:
676 DEBUG(5,("\n"));
677 break;
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;
690 r->so.reason=reason;