parser.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 760 行 · 第 1/2 页

C
760
字号
/*  *  Unix SMB/CIFS implementation. *  RPC Pipe client / server routines *  Copyright (C) Jean Fran鏾is Micouleau      1998-2002. *   *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. *   *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "includes.h"#include "wins_repl.h"extern TALLOC_CTX *mem_ctx;/****************************************************************************grow the send buffer if necessary****************************************************************************/BOOL grow_buffer(struct BUFFER *buffer, int more){	char *temp;	DEBUG(10,("grow_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more));		/* grow by at least 256 bytes */	if (more<256)		more=256;	if (buffer->offset+more >= buffer->length) {		temp=talloc_realloc(mem_ctx, buffer->buffer, char, buffer->length + more);		if (temp==NULL) {			DEBUG(0,("grow_buffer: can't grow buffer\n"));			return False;		}		buffer->length+=more;		buffer->buffer=temp;	}	return True;}/****************************************************************************check if the buffer has that much data****************************************************************************/static BOOL check_buffer(struct BUFFER *buffer, int more){	DEBUG(10,("check_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more));		if (buffer->offset+more > buffer->length) {		DEBUG(10,("check_buffer: buffer smaller than requested, size is: %d needed: %d\n", buffer->length, buffer->offset+more));		return False;	}	return True;}/****************************************************************************decode a WINS_OWNER struct****************************************************************************/static void decode_wins_owner(struct BUFFER *inbuf, WINS_OWNER *wins_owner){	if(!check_buffer(inbuf, 24))		return;	wins_owner->address.s_addr=IVAL(inbuf->buffer, inbuf->offset);	wins_owner->max_version=((SMB_BIG_UINT)RIVAL(inbuf->buffer, inbuf->offset+4))<<32;	wins_owner->max_version|=RIVAL(inbuf->buffer, inbuf->offset+8);	wins_owner->min_version=((SMB_BIG_UINT)RIVAL(inbuf->buffer, inbuf->offset+12))<<32;	wins_owner->min_version|=RIVAL(inbuf->buffer, inbuf->offset+16);	wins_owner->type=RIVAL(inbuf->buffer, inbuf->offset+20);	inbuf->offset+=24;}/****************************************************************************decode a WINS_NAME struct****************************************************************************/static void decode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name){		char *p;	int i;	if(!check_buffer(outbuf, 40))		return;	wins_name->name_len=RIVAL(outbuf->buffer, outbuf->offset);	outbuf->offset+=4;	memcpy(wins_name->name,outbuf->buffer+outbuf->offset, 15);	wins_name->name[15]='\0';	if((p = strchr(wins_name->name,' ')) != NULL)		*p = 0;	outbuf->offset+=15;	wins_name->type=(int)outbuf->buffer[outbuf->offset++];		/*	 * fix to bug in WINS replication,	 * present in all versions including W2K SP2 !	 */	if (wins_name->name[0]==0x1B) {		wins_name->name[0]=(char)wins_name->type;		wins_name->type=0x1B;	}		wins_name->empty=RIVAL(outbuf->buffer, outbuf->offset);	outbuf->offset+=4;		wins_name->name_flag=RIVAL(outbuf->buffer, outbuf->offset);	outbuf->offset+=4;	wins_name->group_flag=RIVAL(outbuf->buffer, outbuf->offset);	outbuf->offset+=4;	wins_name->id=((SMB_BIG_UINT)RIVAL(outbuf->buffer, outbuf->offset))<<32;	outbuf->offset+=4;	wins_name->id|=RIVAL(outbuf->buffer, outbuf->offset);	outbuf->offset+=4;		/* special groups have multiple address */	if (wins_name->name_flag & 2) {		if(!check_buffer(outbuf, 4))			return;		wins_name->num_ip=IVAL(outbuf->buffer, outbuf->offset);		outbuf->offset+=4;	}	else		wins_name->num_ip=1;	if(!check_buffer(outbuf, 4))		return;	wins_name->owner.s_addr=IVAL(outbuf->buffer, outbuf->offset);	outbuf->offset+=4;	if (wins_name->name_flag & 2) {		wins_name->others=talloc_array(mem_ctx, struct in_addr, wins_name->num_ip);		if (wins_name->others==NULL)			return;		if(!check_buffer(outbuf, 4*wins_name->num_ip))			return;		for (i=0; i<wins_name->num_ip; i++) {			wins_name->others[i].s_addr=IVAL(outbuf->buffer, outbuf->offset);			outbuf->offset+=4;		}	}	if(!check_buffer(outbuf, 4))		return;	wins_name->foo=RIVAL(outbuf->buffer, outbuf->offset);	outbuf->offset+=4;}/****************************************************************************decode a update notification request****************************************************************************/static void decode_update_notify_request(struct BUFFER *inbuf, UPDATE_NOTIFY_REQUEST *un_rq){	int i;	if(!check_buffer(inbuf, 4))		return;	un_rq->partner_count=RIVAL(inbuf->buffer, inbuf->offset);	inbuf->offset+=4;	un_rq->wins_owner=talloc_array(mem_ctx, WINS_OWNER, un_rq->partner_count);	if (un_rq->wins_owner==NULL)		return;	for (i=0; i<un_rq->partner_count; i++)		decode_wins_owner(inbuf, &un_rq->wins_owner[i]);	if(!check_buffer(inbuf, 4))		return;	un_rq->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset);	inbuf->offset+=4;}/****************************************************************************decode a send entries request****************************************************************************/static void decode_send_entries_request(struct BUFFER *inbuf, SEND_ENTRIES_REQUEST *se_rq){	decode_wins_owner(inbuf, &se_rq->wins_owner);}/****************************************************************************decode a send entries reply****************************************************************************/static void decode_send_entries_reply(struct BUFFER *inbuf, SEND_ENTRIES_REPLY *se_rp){	int i;	if(!check_buffer(inbuf, 4))		return;	se_rp->max_names = RIVAL(inbuf->buffer, inbuf->offset);	inbuf->offset+=4;	se_rp->wins_name=talloc_array(mem_ctx, WINS_NAME, se_rp->max_names);	if (se_rp->wins_name==NULL)		return;	for (i=0; i<se_rp->max_names; i++)		decode_wins_name(inbuf, &se_rp->wins_name[i]);}/****************************************************************************decode a add version number map table reply****************************************************************************/static void decode_add_version_number_map_table_reply(struct BUFFER *inbuf, AVMT_REP *avmt_rep){	int i;	if(!check_buffer(inbuf, 4))		return;	avmt_rep->partner_count=RIVAL(inbuf->buffer, inbuf->offset);	inbuf->offset+=4;	avmt_rep->wins_owner=talloc_array(mem_ctx, WINS_OWNER, avmt_rep->partner_count);	if (avmt_rep->wins_owner==NULL)		return;	for (i=0; i<avmt_rep->partner_count; i++)		decode_wins_owner(inbuf, &avmt_rep->wins_owner[i]);	if(!check_buffer(inbuf, 4))		return;	avmt_rep->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset);	inbuf->offset+=4;}/****************************************************************************decode a replicate packet and fill a structure****************************************************************************/static void decode_replicate(struct BUFFER *inbuf, REPLICATE *rep){	if(!check_buffer(inbuf, 4))		return;	rep->msg_type = RIVAL(inbuf->buffer, inbuf->offset);	inbuf->offset+=4;	switch (rep->msg_type) {		case 0:			break;		case 1:			/* add version number map table reply */			decode_add_version_number_map_table_reply(inbuf, &rep->avmt_rep);			break;		case 2:			/* send entry request */			decode_send_entries_request(inbuf, &rep->se_rq);			break;		case 3:			/* send entry request */			decode_send_entries_reply(inbuf, &rep->se_rp);			break;		case 4:			/* update notification request */			decode_update_notify_request(inbuf, &rep->un_rq);			break;		default:			DEBUG(0,("decode_replicate: unknown message type:%d\n", rep->msg_type));			break;	}}/****************************************************************************read the generic header and fill the struct.****************************************************************************/static void read_generic_header(struct BUFFER *inbuf, generic_header *q){	if(!check_buffer(inbuf, 16))		return;	q->data_size = RIVAL(inbuf->buffer, inbuf->offset+0);	q->opcode    = RIVAL(inbuf->buffer, inbuf->offset+4);	q->assoc_ctx = RIVAL(inbuf->buffer, inbuf->offset+8);	q->mess_type = RIVAL(inbuf->buffer, inbuf->offset+12);}/*******************************************************************decode a start association request********************************************************************/static void decode_start_assoc_request(struct BUFFER *inbuf, START_ASSOC_REQUEST *q){	if(!check_buffer(inbuf, 8))		return;	q->assoc_ctx = RIVAL(inbuf->buffer, inbuf->offset+0);	q->min_ver = RSVAL(inbuf->buffer, inbuf->offset+4);	q->maj_ver = RSVAL(inbuf->buffer, inbuf->offset+6);}/*******************************************************************decode a start association reply********************************************************************/static void decode_start_assoc_reply(struct BUFFER *inbuf, START_ASSOC_REPLY *r){	if(!check_buffer(inbuf, 8))		return;	r->assoc_ctx=RIVAL(inbuf->buffer, inbuf->offset+0);	r->min_ver = RSVAL(inbuf->buffer, inbuf->offset+4);	r->maj_ver = RSVAL(inbuf->buffer, inbuf->offset+6);}/*******************************************************************decode a start association reply********************************************************************/static void decode_stop_assoc(struct BUFFER *inbuf, STOP_ASSOC *r){	if(!check_buffer(inbuf, 4))		return;	r->reason=RIVAL(inbuf->buffer, inbuf->offset);}/****************************************************************************decode a packet and fill a generic structure****************************************************************************/void decode_generic_packet(struct BUFFER *inbuf, GENERIC_PACKET *q){	read_generic_header(inbuf, &q->header);	inbuf->offset+=16;	switch (q->header.mess_type) {		case 0:			decode_start_assoc_request(inbuf, &q->sa_rq);			break;		case 1:			decode_start_assoc_reply(inbuf, &q->sa_rp);			break;		case 2:			decode_stop_assoc(inbuf, &q->so);			break;		case 3:			decode_replicate(inbuf, &q->rep);			break;		default:			DEBUG(0,("decode_generic_packet: unknown message type:%d\n", q->header.mess_type));			break;	}}/****************************************************************************encode a WINS_OWNER struct****************************************************************************/static void encode_wins_owner(struct BUFFER *outbuf, WINS_OWNER *wins_owner){	if (!grow_buffer(outbuf, 24))		return;	SIVAL(outbuf->buffer, outbuf->offset, wins_owner->address.s_addr);	outbuf->offset+=4;	RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version>>32));	outbuf->offset+=4;	RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version&0xffffffff));	outbuf->offset+=4;	RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version>>32);	outbuf->offset+=4;	RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version&0xffffffff);	outbuf->offset+=4;	RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->type);	outbuf->offset+=4;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?