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

📄 socket_wrapper.c

📁 samba服务器!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org> * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org> * * All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. *  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. *  * 3. Neither the name of the author nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *//*   Socket wrapper library. Passes all socket communication over   unix domain sockets if the environment variable SOCKET_WRAPPER_DIR   is set.*/#ifdef _SAMBA_BUILD_#define SOCKET_WRAPPER_NOT_REPLACE#include "includes.h"#include "system/network.h"#include "system/filesys.h"#ifdef malloc#undef malloc#endif#ifdef calloc#undef calloc#endif#ifdef strdup#undef strdup#endif#else /* _SAMBA_BUILD_ */#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <errno.h>#include <sys/un.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <fcntl.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <stdio.h>#define _PUBLIC_#endif#define SWRAP_DLIST_ADD(list,item) do { \	if (!(list)) { \		(item)->prev	= NULL; \		(item)->next	= NULL; \		(list)		= (item); \	} else { \		(item)->prev	= NULL; \		(item)->next	= (list); \		(list)->prev	= (item); \		(list)		= (item); \	} \} while (0)#define SWRAP_DLIST_REMOVE(list,item) do { \	if ((list) == (item)) { \		(list)		= (item)->next; \		if (list) { \			(list)->prev	= NULL; \		} \	} else { \		if ((item)->prev) { \			(item)->prev->next	= (item)->next; \		} \		if ((item)->next) { \			(item)->next->prev	= (item)->prev; \		} \	} \	(item)->prev	= NULL; \	(item)->next	= NULL; \} while (0)/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support * for now */#define REWRITE_CALLS #ifdef REWRITE_CALLS#define real_accept accept#define real_connect connect#define real_bind bind#define real_listen listen#define real_getpeername getpeername#define real_getsockname getsockname#define real_getsockopt getsockopt#define real_setsockopt setsockopt#define real_recvfrom recvfrom#define real_sendto sendto#define real_ioctl ioctl#define real_recv recv#define real_send send#define real_socket socket#define real_close close#endif#ifdef HAVE_GETTIMEOFDAY_TZ#define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)#else#define swrapGetTimeOfDay(tval)	gettimeofday(tval)#endif/* we need to use a very terse format here as IRIX 6.4 silently   truncates names to 16 chars, so if we use a longer name then we   can't tell which port a packet came from with recvfrom()       with this format we have 8 chars left for the directory name*/#define SOCKET_FORMAT "%c%02X%04X"#define SOCKET_TYPE_CHAR_TCP		'T'#define SOCKET_TYPE_CHAR_UDP		'U'#define MAX_WRAPPED_INTERFACES 16static struct sockaddr *sockaddr_dup(const void *data, socklen_t len){	struct sockaddr *ret = (struct sockaddr *)malloc(len);	memcpy(ret, data, len);	return ret;}struct socket_info{	int fd;	int family;	int type;	int protocol;	int bound;	int bcast;	int is_server;	char *path;	char *tmp_path;	struct sockaddr *myname;	socklen_t myname_len;	struct sockaddr *peername;	socklen_t peername_len;	struct {		unsigned long pck_snd;		unsigned long pck_rcv;	} io;	struct socket_info *prev, *next;};static struct socket_info *sockets;static const char *socket_wrapper_dir(void){	const char *s = getenv("SOCKET_WRAPPER_DIR");	if (s == NULL) {		return NULL;	}	if (strncmp(s, "./", 2) == 0) {		s += 2;	}	return s;}static unsigned int socket_wrapper_default_iface(void){	const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");	if (s) {		unsigned int iface;		if (sscanf(s, "%u", &iface) == 1) {			if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {				return iface;			}		}	}	return 1;/* 127.0.0.1 */}static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len){	unsigned int iface;	unsigned int prt;	const char *p;	char type;	if ((*len) < sizeof(struct sockaddr_in)) {		return 0;	}	p = strrchr(un->sun_path, '/');	if (p) p++; else p = un->sun_path;	if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {		errno = EINVAL;		return -1;	}	if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {		errno = EINVAL;		return -1;	}	if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {		errno = EINVAL;		return -1;	}	if (prt > 0xFFFF) {		errno = EINVAL;		return -1;	}	in->sin_family = AF_INET;	in->sin_addr.s_addr = htonl((127<<24) | iface);	in->sin_port = htons(prt);	*len = sizeof(struct sockaddr_in);	return 0;}static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,				int *bcast){	char u_type = '\0';	char b_type = '\0';	char a_type = '\0';	char type = '\0';	unsigned int addr= ntohl(in->sin_addr.s_addr);	unsigned int prt = ntohs(in->sin_port);	unsigned int iface;	int is_bcast = 0;	if (bcast) *bcast = 0;	if (prt == 0) {		errno = EINVAL;		return -1;	}	switch (si->type) {	case SOCK_STREAM:		u_type = SOCKET_TYPE_CHAR_TCP;		break;	case SOCK_DGRAM:		u_type = SOCKET_TYPE_CHAR_UDP;		a_type = SOCKET_TYPE_CHAR_UDP;		b_type = SOCKET_TYPE_CHAR_UDP;		break;	}	if (a_type && addr == 0xFFFFFFFF) {		/* 255.255.255.255 only udp */		is_bcast = 2;		type = a_type;		iface = socket_wrapper_default_iface();	} else if (b_type && addr == 0x7FFFFFFF) {		/* 127.255.255.255 only udp */		is_bcast = 1;		type = b_type;		iface = socket_wrapper_default_iface();	} else if ((addr & 0xFFFFFF00) == 0x7F000000) {		/* 127.0.0.X */		is_bcast = 0;		type = u_type;		iface = (addr & 0x000000FF);	} else {		errno = ENETUNREACH;		return -1;	}	if (bcast) *bcast = is_bcast;	if (is_bcast) {		snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 			 socket_wrapper_dir());		/* the caller need to do more processing */		return 0;	}	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 		 socket_wrapper_dir(), type, iface, prt);	return 0;}static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,			       int *bcast){	char u_type = '\0';	char d_type = '\0';	char b_type = '\0';	char a_type = '\0';	char type = '\0';	unsigned int addr= ntohl(in->sin_addr.s_addr);	unsigned int prt = ntohs(in->sin_port);	unsigned int iface;	struct stat st;	int is_bcast = 0;	if (bcast) *bcast = 0;	switch (si->type) {	case SOCK_STREAM:		u_type = SOCKET_TYPE_CHAR_TCP;		d_type = SOCKET_TYPE_CHAR_TCP;		break;	case SOCK_DGRAM:		u_type = SOCKET_TYPE_CHAR_UDP;		d_type = SOCKET_TYPE_CHAR_UDP;		a_type = SOCKET_TYPE_CHAR_UDP;		b_type = SOCKET_TYPE_CHAR_UDP;		break;	}	if (addr == 0) {		/* 0.0.0.0 */		is_bcast = 0;		type = d_type;		iface = socket_wrapper_default_iface();	} else if (a_type && addr == 0xFFFFFFFF) {		/* 255.255.255.255 only udp */		is_bcast = 2;		type = a_type;		iface = socket_wrapper_default_iface();	} else if (b_type && addr == 0x7FFFFFFF) {		/* 127.255.255.255 only udp */		is_bcast = 1;		type = b_type;		iface = socket_wrapper_default_iface();	} else if ((addr & 0xFFFFFF00) == 0x7F000000) {		/* 127.0.0.X */		is_bcast = 0;		type = u_type;		iface = (addr & 0x000000FF);	} else {		errno = EADDRNOTAVAIL;		return -1;	}	if (bcast) *bcast = is_bcast;	if (prt == 0) {		/* handle auto-allocation of ephemeral ports */		for (prt = 5001; prt < 10000; prt++) {			snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 				 socket_wrapper_dir(), type, iface, prt);			if (stat(un->sun_path, &st) == 0) continue;			((struct sockaddr_in *)si->myname)->sin_port = htons(prt);			return 0;		}		errno = ENFILE;		return -1;	}	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 		 socket_wrapper_dir(), type, iface, prt);	return 0;}static struct socket_info *find_socket_info(int fd){	struct socket_info *i;	for (i = sockets; i; i = i->next) {		if (i->fd == fd) 			return i;	}	return NULL;}static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, 				  struct sockaddr_un *out_addr, int alloc_sock, int *bcast){	if (!out_addr)		return 0;	out_addr->sun_family = AF_UNIX;	switch (in_addr->sa_family) {	case AF_INET:		switch (si->type) {		case SOCK_STREAM:		case SOCK_DGRAM:			break;		default:			errno = ESOCKTNOSUPPORT;			return -1;		}		if (alloc_sock) {			return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);		} else {			return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);		}	default:		break;	}		errno = EAFNOSUPPORT;	return -1;}static int sockaddr_convert_from_un(const struct socket_info *si, 				    const struct sockaddr_un *in_addr, 				    socklen_t un_addrlen,				    int family,				    struct sockaddr *out_addr,				    socklen_t *_out_addrlen){	socklen_t out_addrlen;	if (out_addr == NULL || _out_addrlen == NULL) 		return 0;	if (un_addrlen == 0) {		*_out_addrlen = 0;		return 0;	}	out_addrlen = *_out_addrlen;	if (out_addrlen > un_addrlen) {		out_addrlen = un_addrlen;	}	switch (family) {	case AF_INET:		switch (si->type) {		case SOCK_STREAM:		case SOCK_DGRAM:			break;		default:			errno = ESOCKTNOSUPPORT;			return -1;		}		return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);	default:		break;	}	errno = EAFNOSUPPORT;	return -1;}enum swrap_packet_type {	SWRAP_CONNECT_SEND,	SWRAP_CONNECT_UNREACH,	SWRAP_CONNECT_RECV,	SWRAP_CONNECT_ACK,	SWRAP_ACCEPT_SEND,	SWRAP_ACCEPT_RECV,	SWRAP_ACCEPT_ACK,	SWRAP_RECVFROM,	SWRAP_SENDTO,	SWRAP_SENDTO_UNREACH,	SWRAP_PENDING_RST,	SWRAP_RECV,	SWRAP_RECV_RST,	SWRAP_SEND,	SWRAP_SEND_RST,	SWRAP_CLOSE_SEND,	SWRAP_CLOSE_RECV,	SWRAP_CLOSE_ACK};struct swrap_file_hdr {	unsigned long	magic;	unsigned short	version_major;		unsigned short	version_minor;	long		timezone;	unsigned long	sigfigs;	unsigned long	frame_max_len;#define SWRAP_FRAME_LENGTH_MAX 0xFFFF	unsigned long	link_type;};#define SWRAP_FILE_HDR_SIZE 24struct swrap_packet {	struct {		unsigned long seconds;		unsigned long micro_seconds;		unsigned long recorded_length;		unsigned long full_length;	} frame;#define SWRAP_PACKET__FRAME_SIZE 16	struct {		struct {			unsigned char	ver_hdrlen;			unsigned char	tos;			unsigned short	packet_length;			unsigned short	identification;			unsigned char	flags;			unsigned char	fragment;			unsigned char	ttl;			unsigned char	protocol;			unsigned short	hdr_checksum;			unsigned long	src_addr;

⌨️ 快捷键说明

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