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

📄 ipcsocket.c

📁 linux集群服务器软件代码包
💻 C
📖 第 1 页 / 共 4 页
字号:
  temp_ch->bytes_remaining = 0;  temp_ch->should_send_blocking = FALSE;  temp_ch->send_queue = socket_queue_new();  temp_ch->recv_queue = socket_queue_new();  temp_ch->pool = NULL;  temp_ch->high_flow_mark = temp_ch->send_queue->max_qlen;  temp_ch->low_flow_mark = -1;    return temp_ch;  }struct IPC_CHANNEL * socket_server_channel_new(int sockfd){  struct IPC_CHANNEL * temp_ch;  struct SOCKET_CH_PRIVATE* conn_info;  int flags;      temp_ch = g_new(struct IPC_CHANNEL, 1);   if (temp_ch == NULL){	  cl_log(LOG_ERR, "socket_server_channel_new:"		 " allocating memory for channel failed");	  return NULL;	    }  memset(temp_ch, 0, sizeof(struct IPC_CHANNEL));    conn_info = g_new(struct SOCKET_CH_PRIVATE, 1);    flags = fcntl(sockfd, F_GETFL, O_NONBLOCK);  if (flags == -1) {	  cl_perror("socket_server_channel_new: cannot read file descriptor flags");	  g_free(conn_info); conn_info = NULL;	  g_free(temp_ch);	  return NULL;  }  flags |= O_NONBLOCK;  if (fcntl(sockfd, F_SETFL, flags) < 0) {	  cl_perror("socket_server_channel_new: cannot set O_NONBLOCK");	  g_free(conn_info); conn_info = NULL;	  g_free(temp_ch);    return NULL;  }  conn_info->s = sockfd;  conn_info->remaining_data = 0;  conn_info->buf_msg = NULL;  conn_info->peer_addr = NULL;  strcpy(conn_info->path_name, "?");#ifdef DEBUG  cl_log(LOG_INFO, "Initializing server socket %d to DISCONNECT", sockfd);#endif  temp_ch->ch_status = IPC_DISCONNECT;  temp_ch->ch_private = (void*) conn_info;  temp_ch->ops = (struct IPC_OPS *)&socket_ops;  temp_ch->msgpad = sizeof(struct SOCKET_MSG_HEAD);  temp_ch->bytes_remaining = 0;  temp_ch->should_send_blocking = FALSE;  temp_ch->send_queue = socket_queue_new();  temp_ch->recv_queue = socket_queue_new();  temp_ch->pool = NULL;  temp_ch->high_flow_mark = temp_ch->send_queue->max_qlen;  temp_ch->low_flow_mark = -1;       return temp_ch;  }/* * Create a new pair of pre-connected IPC channels similar to * the result of pipe(2), or socketpair(2). */intipc_channel_pair(IPC_Channel* channels[2]){	int	sockets[2];	int	rc;	int	j;	if ((rc = socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets)) < 0) {		return IPC_FAIL;	}	if ((channels[0] = socket_server_channel_new(sockets[0])) == NULL) {		close(sockets[0]);		close(sockets[1]);		return IPC_FAIL;	}	if ((channels[1] = socket_server_channel_new(sockets[1])) == NULL) {		close(sockets[0]);		close(sockets[1]);		channels[0]->ops->destroy(channels[0]);		return IPC_FAIL;	}	for (j=0; j < 2; ++j) {  		struct SOCKET_CH_PRIVATE* p = channels[j]->ch_private;		channels[j]->ch_status = IPC_CONNECT;		/* Valid, but not terribly meaningful */		channels[j]->farside_pid = getpid();  		strncpy(p->path_name, "[socketpair]", sizeof(p->path_name));	}	return IPC_OK;	}/*  * create a new ipc message whose msg_body's length is msg_len.  *  * parameters : *       msg_len (IN) the length of this message body in this message. * * return : *       the pointer to the new message or NULL if the message can't be created. */static struct IPC_MESSAGE*socket_message_new(struct IPC_CHANNEL *ch, int msg_len){  struct IPC_MESSAGE * temp_msg;  temp_msg = g_new(struct IPC_MESSAGE, 1);  memset(temp_msg, 0, sizeof(struct IPC_MESSAGE));  if (msg_len != 0){	  temp_msg->msg_buf = g_malloc(msg_len + ch->msgpad);	  temp_msg->msg_body = (char*)temp_msg->msg_buf + ch->msgpad;  }else{	  temp_msg->msg_buf = temp_msg->msg_body = NULL;  }    temp_msg->msg_len = msg_len;  temp_msg->msg_private = NULL;  temp_msg->msg_ch = ch;  temp_msg->msg_done = socket_free_message;  return temp_msg;}/* brief free the memory space allocated to msg and destroy msg. */voidsocket_free_message(struct IPC_MESSAGE * msg) {#if 0	memset(msg->msg_body, 0xff, msg->msg_len);#endif       if (msg->msg_buf){               g_free(msg->msg_buf);       }else {               g_free(msg->msg_body);       }#if 0	memset(msg, 0xff, sizeof(*msg));#endif	g_free((void *)msg);}/*********************************************************************** * * IPC authentication schemes...  More machine dependent than * we'd like, but don't know any better way... * ***********************************************************************//*********************************************************************** * SO_PEERCRED VERSION... (Linux) ***********************************************************************/#ifdef USE_SO_PEERCRED/* verify the authentication information. */static int socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info){	struct SOCKET_CH_PRIVATE *	conn_info;	int				ret = IPC_FAIL;	struct ucred			cred;	socklen_t			n = sizeof(cred);  	if (ch == NULL || ch->ch_private == NULL) {		return IPC_FAIL;	}	if (auth_info == NULL	||	(auth_info->uid == NULL && auth_info->gid == NULL)) {		return IPC_OK;    /* no restriction for authentication */	  }	/* Get the credential information for our peer */	conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;	if (getsockopt(conn_info->s, SOL_SOCKET, SO_PEERCRED, &cred, &n) != 0	||	(size_t)n != sizeof(cred)) {		return IPC_FAIL;	}#if 1	cl_log(LOG_DEBUG, "SO_PEERCRED returned [%d, (%ld:%ld)]"	,	cred.pid, (long)cred.uid, (long)cred.uid);	cl_log(LOG_DEBUG, "Verifying authentication: cred.uid=%d cred.gid=%d"	,	cred.uid, cred.gid);	cl_log(LOG_DEBUG, "Verifying authentication: uidptr=0x%lx gidptr=0x%lx"	,	(unsigned long)auth_info->uid	,	(unsigned long)auth_info->gid);#endif  	/* verify the credential information. */	if (	auth_info->uid	&&	(g_hash_table_lookup(auth_info->uid		,	GUINT_TO_POINTER((guint)cred.uid)) != NULL)) {		ret = IPC_OK;	}else if (auth_info->gid	&&	(g_hash_table_lookup(auth_info->gid		,	GUINT_TO_POINTER((guint)cred.gid)) != NULL)) {		ret = IPC_OK;  	}	return ret;}/* get farside pid for our peer process */pid_tsocket_get_farside_pid(int sockfd){  socklen_t n;  struct ucred *cred;  pid_t f_pid;    /* Get the credential information from peer */  n = sizeof(struct ucred);  cred = g_new(struct ucred, 1);   if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, cred, &n) != 0) {    g_free(cred);    return -1;  }    f_pid = cred->pid;  g_free(cred);  return f_pid;}#endif /* SO_PEERCRED version */#ifdef USE_GETPEEREID/* * This is implemented in OpenBSD and FreeBSD. * * It's not a half-bad interface... * * This should probably be our standard way of doing it, and put it * as a replacement library.  That would simplify things... */static int socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info){	struct SOCKET_CH_PRIVATE *conn_info;	uid_t	euid;	gid_t	egid;	int	ret = IPC_FAIL;	if (auth_info == NULL	||	(auth_info->uid == NULL && auth_info->gid == NULL)) {		return IPC_OK;    /* no restriction for authentication */	}	conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;	if (getpeereid(conn_info->s, &euid, &egid) < 0) {		cl_perror("getpeereid() failure");		return IPC_FAIL;	}	/* Check credentials against authorization information */	if (	auth_info->uid	&&	(g_hash_table_lookup(auth_info->uid		,	GUINT_TO_POINTER((guint)euid)) != NULL)) {		ret = IPC_OK;	}else if (auth_info->gid	&&	(g_hash_table_lookup(auth_info->gid		,	GUINT_TO_POINTER((guint)egid)) != NULL)) {		ret = IPC_OK;  	}	return ret;}pid_tsocket_get_farside_pid(int sock){	return -1;}#endif /* USE_GETPEEREID *//*********************************************************************** * SCM_CREDS VERSION... (*BSD systems) ***********************************************************************/#ifdef USE_SCM_CREDS/* FIXME!  Need to implement SCM_CREDS mechanism for BSD-based systems * This isn't an emergency, but should be done in the future... * Hint: * Postgresql does both types of authentication... * see src/backend/libpq/auth.c * Not clear its SO_PEERCRED implementation works though ;-)  *//* Done.... Haven't tested yet. */static int socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info){  struct msghdr msg;  /* Credentials structure */#define	EXTRASPACE	0#ifdef HAVE_STRUCT_CMSGCRED	/* FreeBSD */  typedef struct cmsgcred Cred;#	define crRuid	cmcred_uid#	define crEuid	cmcred_euid#	define crRgid	cmcred_gid#	define crEgid	cmcred_groups[0]	/* Best guess */#	define crpid	cmcred_pid#	define crngrp	cmcred_ngroups#	define crgrps	cmcred_groups#elif HAVE_STRUCT_FCRED	/* Stevens' book */  typedef struct fcred Cred;#	define crRuid	fc_uid#	define crRgid	fc_rgid#	define crEgid	fc_gid#	define crngrp	fc_ngroups#	define crgrps	fc_groups#elif HAVE_STRUCT_SOCKCRED	/* NetBSD */  typedef struct sockcred Cred;#	define crRuid	sc_uid#	define crEuid	sc_euid#	define crRgid	sc_gid#	define crEgid	sc_egid#	define crngrp	sc_ngroups#	define crgrps	sc_groups#	define EXTRASPACE	SOCKCREDSIZE(ngroups)#elif HAVE_STRUCT_CRED  typedef struct cred Cred;#define cruid c_uid#elif HAVE_STRUCT_UCRED typedef struct ucred Cred; /* reuse this define for the moment */#  if HAVE_STRUCT_UCRED_DARWIN#	define crEuid	cr_uid#	define crEgid	cr_groups[0]		/* Best guess */#	define crgrps	cr_groups#	define crngrp	cr_ngroups#  else#	define crEuid	c_uid#	define crEgid	c_gid#  endif#else#	error "No credential type found!"#endif  struct SOCKET_CH_PRIVATE *conn_info;  int ret = IPC_OK;  char         buf;    /* Compute size without padding */  #define CMSGSIZE	(sizeof(struct cmsghdr)+(sizeof(Cred))+EXTRASPACE)  union {  	char		mem[CMSGSIZE];	struct cmsghdr	hdr;	Cred		credu;  }cmsgmem;  Cred	   cred;  /* Point to start of first structure */  struct cmsghdr *cmsg = &cmsgmem.hdr;    if (auth_info == NULL  ||	(auth_info->uid == NULL && auth_info->gid == NULL)) {    return IPC_OK;    /* no restriction for authentication */  }  conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;  memset(&msg, 0, sizeof(msg));  msg.msg_iov =  g_new(struct iovec, 1);  msg.msg_iovlen = 1;  msg.msg_control = (char *) cmsg;  msg.msg_controllen = CMSGSIZE;  memset(cmsg, 0, sizeof(cmsgmem));  /*   * The one character which is received here is not meaningful; its   * purpose is only to make sure that recvmsg() blocks long enough for   * the other side to send its credentials.   */  msg.msg_iov->iov_base = &buf;  msg.msg_iov->iov_len = 1;    if (recvmsg(conn_info->s, &msg, 0) < 0       || cmsg->cmsg_len < CMSGSIZE      || cmsg->cmsg_type != SCM_CREDS) {      cl_perror("can't get credential information from peer");      return IPC_FAIL;    }  /* Avoid alignment issues - just copy it! */  memcpy(&cred, CMSG_DATA(cmsg), sizeof(cred));  if (	auth_info->uid  &&	g_hash_table_lookup(auth_info->uid, &(cred.crEuid)) == NULL) {		ret = IPC_FAIL;  }  if (	auth_info->gid  &&	g_hash_table_lookup(auth_info->gid, &(cred.crEgid)) == NULL) {		ret = IPC_FAIL;  }  return ret;}/* * FIXME!  Need to implement SCM_CREDS mechanism for BSD-based systems * this is similar to the SCM_CREDS mechanism for verify_auth() function. * here we just want to get the pid of the other side from the credential  * information. */pid_tsocket_get_farside_pid(int sock){	/* FIXME! */	return -1;}#endif /* SCM_CREDS version *//*********************************************************************** * Bind/Stat VERSION... (Supported on OSX/Darwin and 4.3+BSD at least...) * * This is for use on systems such as OSX-Darwin and maybe Solaris where *   none of the other options are available. * * This implementation has been adapted from "Advanced Programming *   in the Unix Environment", Section 15.5.2, by W. Richard Stevens. * */#ifdef USE_BINDSTAT_CREDSstatic int socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info){	int len = 0;	int ret = IPC_OK;	struct stat stat_buf;	struct sockaddr_un *peer_addr = NULL;	struct SOCKET_CH_PRIVATE *ch_private = NULL;		if(ch != NULL) {		ch_private = (struct SOCKET_CH_PRIVATE *)(ch->ch_private);		if(ch_private != NULL) {			peer_addr = ch_private->peer_addr;			}	}	if(ch == NULL) {		cl_log(LOG_ERR, "No channel to authenticate");		return IPC_FAIL;			} else if (auth_info == NULL	    ||	(auth_info->uid == NULL && auth_info->gid == NULL)) {		return IPC_OK;    /* no restriction for authentication */	} else if(ch_private == NULL) {		cl_log(LOG_ERR, "No channel private data available");		return IPC_FAIL;			} else if(peer_addr == NULL) {			cl_log(LOG_ERR, "No peer information available");		return IPC_FAIL;	}		len = SUN_LEN(peer_addr);	if(len < 1) {		cl_log(LOG_ERR, "No peer information available");		return IPC_FAIL;	}	peer_addr->sun_path[len] = 0;	stat(peer_addr->sun_path, &stat_buf);	if ((auth_info->uid == NULL || g_hash_table_size(auth_info->uid) == 0)	    && auth_info->gid != NULL	    && g_hash_table_size(auth_info->gid) != 0) {		cl_log(LOG_WARNING,		       "GID-Only IPC security is not supported"		       " on this platform.");		return IPC_BROKEN;	}		if (auth_info->uid != NULL && g_hash_table_size(auth_info->uid) > 0	    && g_hash_table_lookup(		    auth_info->uid, GUINT_TO_POINTER(stat_buf.st_uid))==NULL) {		ret = IPC_FAIL;			}	if (auth_info->gid != NULL && g_hash_table_size(auth_info->gid) > 0	    && g_hash_table_lookup(		    auth_info->gid, GUINT_TO_POINTER(stat_buf.st_gid))==NULL) {		ret = IPC_FAIL;	}	return ret;}pid_tsocket_get_farside_pid(int sock){	return -1;}#endif /* Bind/stat version *//*********************************************************************** * DUMMY VERSION... (other systems...) * * I'm afraid Solaris falls into this category :-( * Other options that seem to be out there include * SCM_CREDENTIALS and LOCAL_CREDS * Or maybe something called doors for Solaris * Unfortunately, it looks like Doors is tied to threads :-( * Can the streams credentials code be used with local domain sockets? * There are some kludgy things you can do with SCM_RIGHTS * to pass an fd which could only be opened by the user id to * validate the user id, but I don't know of a similar kludge which * would work for group ids.  And, even the uid one will fail * if normal users are allowed to give away (chown) files. * * Unfortunately, this set of authentication routines have become * very important to this API and its users (like heartbeat). * ***********************************************************************/#ifdef USE_DUMMY_CREDSstatic int socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info){	return IPC_FAIL;}pid_tsocket_get_farside_pid(int sock){	return -1;}#endif /* Dummy version */

⌨️ 快捷键说明

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