⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nmbd_packets.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Ensure we don't re-send the request. */	rrec->repeat_count = 0;  	/* Call the response received function for this packet. */	(*rrec->resp_fn)(subrec, rrec, p);}/*******************************************************************  Run elements off the packet queue till its empty******************************************************************/void run_packet_queue(void){	struct packet_struct *p;	while ((p = packet_queue)) {		packet_queue = p->next;		if (packet_queue)			packet_queue->prev = NULL;		p->next = p->prev = NULL;		switch (p->packet_type) {			case NMB_PACKET:				if(p->packet.nmb.header.response)					process_nmb_response(p);				else					process_nmb_request(p);				break;			case DGRAM_PACKET:				process_dgram(p);				break;		}		free_packet(p);	}} /******************************************************************* Retransmit or timeout elements from all the outgoing subnet response record queues. NOTE that this code must also check the WINS server subnet for response records to timeout as the WINS server code can send requests to check if a client still owns a name. (Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>).******************************************************************/void retransmit_or_expire_response_records(time_t t){	struct subnet_record *subrec;	for (subrec = FIRST_SUBNET; subrec; subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) {		struct response_record *rrec, *nextrrec;		for (rrec = subrec->responselist; rrec; rrec = nextrrec) {			nextrrec = rrec->next;   			if (rrec->repeat_time <= t) {				if (rrec->repeat_count > 0) {					/* Resend while we have a non-zero repeat_count. */					if(!send_packet(rrec->packet)) {						DEBUG(0,("retransmit_or_expire_response_records: Failed to resend packet id %hu \to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_name));					}					rrec->repeat_time = t + rrec->repeat_interval;					rrec->repeat_count--;				} else {					DEBUG(4,("retransmit_or_expire_response_records: timeout for packet id %hu to IP %s \on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_name));					/*					 * Check the flag in this record to prevent recursion if we end					 * up in this function again via the timeout function call.					 */					if(!rrec->in_expiration_processing) {						/*						 * Set the recursion protection flag in this record.						 */						rrec->in_expiration_processing = True;						/* Call the timeout function. This will deal with removing the								timed out packet. */						if(rrec->timeout_fn) {							(*rrec->timeout_fn)(subrec, rrec);						} else {							/* We must remove the record ourself if there is									no timeout function. */							remove_response_record(subrec, rrec);						}					} /* !rrec->in_expitation_processing */				} /* rrec->repeat_count > 0 */			} /* rrec->repeat_time <= t */		} /* end for rrec */	} /* end for subnet */}/****************************************************************************  Create an fd_set containing all the sockets in the subnet structures,  plus the broadcast sockets.***************************************************************************/static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number, int *maxfd){	int *sock_array = NULL;	struct subnet_record *subrec = NULL;	int count = 0;	int num = 0;	fd_set *pset = SMB_MALLOC_P(fd_set);	if(pset == NULL) {		DEBUG(0,("create_listen_fdset: malloc fail !\n"));		return True;	}	/* Check that we can add all the fd's we need. */	for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))		count++;	if((count*2) + 2 > FD_SETSIZE) {		DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \only use %d.\n", (count*2) + 2, FD_SETSIZE));		return True;	}	if((sock_array = SMB_MALLOC_ARRAY(int, (count*2) + 2)) == NULL) {		DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n"));		return True;	}	FD_ZERO(pset);	/* Add in the broadcast socket on 137. */	FD_SET(ClientNMB,pset);	sock_array[num++] = ClientNMB;	*maxfd = MAX( *maxfd, ClientNMB);	/* Add in the 137 sockets on all the interfaces. */	for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {		FD_SET(subrec->nmb_sock,pset);		sock_array[num++] = subrec->nmb_sock;		*maxfd = MAX( *maxfd, subrec->nmb_sock);	}	/* Add in the broadcast socket on 138. */	FD_SET(ClientDGRAM,pset);	sock_array[num++] = ClientDGRAM;	*maxfd = MAX( *maxfd, ClientDGRAM);	/* Add in the 138 sockets on all the interfaces. */	for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {		FD_SET(subrec->dgram_sock,pset);		sock_array[num++] = subrec->dgram_sock;		*maxfd = MAX( *maxfd, subrec->dgram_sock);	}	*listen_number = (count*2) + 2;	SAFE_FREE(*ppset);	SAFE_FREE(*psock_array);	*ppset = pset;	*psock_array = sock_array; 	return False;}/****************************************************************************  Listens for NMB or DGRAM packets, and queues them.  return True if the socket is dead***************************************************************************/BOOL listen_for_packets(BOOL run_election){	static fd_set *listen_set = NULL;	static int listen_number = 0;	static int *sock_array = NULL;	int i;	static int maxfd = 0;	fd_set fds;	int selrtn;	struct timeval timeout;#ifndef SYNC_DNS	int dns_fd;#endif	if(listen_set == NULL || rescan_listen_set) {		if(create_listen_fdset(&listen_set, &sock_array, &listen_number, &maxfd)) {			DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));			return True;		}		rescan_listen_set = False;	}	memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));#ifndef SYNC_DNS	dns_fd = asyncdns_fd();	if (dns_fd != -1) {		FD_SET(dns_fd, &fds);		maxfd = MAX( maxfd, dns_fd);	}#endif	/* 	 * During elections and when expecting a netbios response packet we	 * need to send election packets at tighter intervals.	 * Ideally it needs to be the interval (in ms) between time now and	 * the time we are expecting the next netbios packet.	 */	timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;	timeout.tv_usec = 0;	/* Prepare for the select - allow certain signals. */	BlockSignals(False, SIGTERM);	selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&timeout);	/* We can only take signals when we are in the select - block them again here. */	BlockSignals(True, SIGTERM);	if(selrtn == -1) {		return False;	}#ifndef SYNC_DNS	if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) {		run_dns_queue();	}#endif	for(i = 0; i < listen_number; i++) {		if (i < (listen_number/2)) {			/* Processing a 137 socket. */			if (FD_ISSET(sock_array[i],&fds)) {				struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET);				if (packet) {					/*					 * If we got a packet on the broadcast socket and interfaces					 * only is set then check it came from one of our local nets. 					 */					if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) && 								(!is_local_net(packet->ip))) {						DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n",							inet_ntoa(packet->ip),packet->port));	  						free_packet(packet);					} else if ((ip_equal(loopback_ip, packet->ip) || 								ismyip(packet->ip)) && packet->port == global_nmb_port &&								packet->packet.nmb.header.nm_flags.bcast) {						DEBUG(7,("discarding own bcast packet from %s:%d\n",							inet_ntoa(packet->ip),packet->port));	  						free_packet(packet);					} else {						/* Save the file descriptor this packet came in on. */						packet->fd = sock_array[i];						queue_packet(packet);					}				}			}		} else {			/* Processing a 138 socket. */				if (FD_ISSET(sock_array[i],&fds)) {				struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET);				if (packet) {					/*					 * If we got a packet on the broadcast socket and interfaces					 * only is set then check it came from one of our local nets. 					 */					if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) && 								(!is_local_net(packet->ip))) {						DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n",						inet_ntoa(packet->ip),packet->port));	  						free_packet(packet);					} else if ((ip_equal(loopback_ip, packet->ip) || 							ismyip(packet->ip)) && packet->port == DGRAM_PORT) {						DEBUG(7,("discarding own dgram packet from %s:%d\n",							inet_ntoa(packet->ip),packet->port));	  						free_packet(packet);					} else {						/* Save the file descriptor this packet came in on. */						packet->fd = sock_array[i];						queue_packet(packet);					}				}			}		} /* end processing 138 socket. */	} /* end for */	return False;}/****************************************************************************  Construct and send a netbios DGRAM.**************************************************************************/BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len,                   const char *srcname, int src_type,                   const char *dstname, int dest_type,                   struct in_addr dest_ip,struct in_addr src_ip,		   int dest_port){	BOOL loopback_this_packet = False;	struct packet_struct p;	struct dgram_packet *dgram = &p.packet.dgram;	char *ptr,*p2;	char tmp[4];	memset((char *)&p,'\0',sizeof(p));	if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */		loopback_this_packet = True;	/* generate_name_trn_id(); */ /* Not used, so gone, RJS */	/* DIRECT GROUP or UNIQUE datagram. */	dgram->header.msg_type = unique ? 0x10 : 0x11; 	dgram->header.flags.node_type = M_NODE;	dgram->header.flags.first = True;	dgram->header.flags.more = False;	dgram->header.dgm_id = generate_name_trn_id();	dgram->header.source_ip = src_ip;	dgram->header.source_port = DGRAM_PORT;	dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */	dgram->header.packet_offset = 0;  	make_nmb_name(&dgram->source_name,srcname,src_type);	make_nmb_name(&dgram->dest_name,dstname,dest_type);	ptr = &dgram->data[0];	/* Setup the smb part. */	ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */	memcpy(tmp,ptr,4);	set_message(ptr,17,strlen(mailslot) + 1 + len,True);	memcpy(ptr,tmp,4);	SCVAL(ptr,smb_com,SMBtrans);	SSVAL(ptr,smb_vwv1,len);	SSVAL(ptr,smb_vwv11,len);	SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));	SSVAL(ptr,smb_vwv13,3);	SSVAL(ptr,smb_vwv14,1);	SSVAL(ptr,smb_vwv15,1);	SSVAL(ptr,smb_vwv16,2);	p2 = smb_buf(ptr);	safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data));	p2 = skip_string(p2,1);  	if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) {		DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n"));		return False;	} else {		memcpy(p2,buf,len);		p2 += len;	}	dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */	p.ip = dest_ip;	p.port = dest_port;	p.fd = find_subnet_mailslot_fd_for_address( src_ip );	p.timestamp = time(NULL);	p.packet_type = DGRAM_PACKET;	DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot,			nmb_namestr(&dgram->source_name), inet_ntoa(src_ip)));	DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip)));	debug_browse_data(buf, len);	if(loopback_this_packet) {		struct packet_struct *lo_packet = NULL;		DEBUG(5,("send_mailslot: sending packet to ourselves.\n"));		if((lo_packet = copy_packet(&p)) == NULL)			return False;		queue_packet(lo_packet);		return True;	} else {		return(send_packet(&p));	}}

⌨️ 快捷键说明

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