Blame Esm/ib/src/cs/cs_sockwrap.c

Packit Service 3470d1
/* BEGIN_ICS_COPYRIGHT5 ****************************************
Packit Service 3470d1
Packit Service 3470d1
Copyright (c) 2015-2017, Intel Corporation
Packit Service 3470d1
Packit Service 3470d1
Redistribution and use in source and binary forms, with or without
Packit Service 3470d1
modification, are permitted provided that the following conditions are met:
Packit Service 3470d1
Packit Service 3470d1
    * Redistributions of source code must retain the above copyright notice,
Packit Service 3470d1
      this list of conditions and the following disclaimer.
Packit Service 3470d1
    * Redistributions in binary form must reproduce the above copyright
Packit Service 3470d1
      notice, this list of conditions and the following disclaimer in the
Packit Service 3470d1
      documentation and/or other materials provided with the distribution.
Packit Service 3470d1
    * Neither the name of Intel Corporation nor the names of its contributors
Packit Service 3470d1
      may be used to endorse or promote products derived from this software
Packit Service 3470d1
      without specific prior written permission.
Packit Service 3470d1
Packit Service 3470d1
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit Service 3470d1
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit Service 3470d1
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit Service 3470d1
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit Service 3470d1
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit Service 3470d1
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit Service 3470d1
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit Service 3470d1
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit Service 3470d1
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 3470d1
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 3470d1
Packit Service 3470d1
 * ** END_ICS_COPYRIGHT5   ****************************************/
Packit Service 3470d1
Packit Service 3470d1
/*******************************************************************************
Packit Service 3470d1
 * @file cs_sockwrap.c
Packit Service 3470d1
 *
Packit Service 3470d1
 * @brief
Packit Service 3470d1
 * This file contains some socket creation routines for server and client
Packit Service 3470d1
 * AF_UNIX type sockets.
Packit Service 3470d1
 * The routines are supposed to be used on both Unix and Vxworks but the
Packit Service 3470d1
 * structure of the socket addresss strings passed to the routines differs
Packit Service 3470d1
 * between the operating systems.
Packit Service 3470d1
 * In UNIX the structure of the strings is supposed to be generally of the
Packit Service 3470d1
 * form "/var/tmp/<unique file name>" and in VXWORKS the string should
Packit Service 3470d1
 * take the form "/comp/socket/0xNumber" where 0xNumber is a string
Packit Service 3470d1
 * representation of a 16 bit number is hexadecimal form.
Packit Service 3470d1
 *******************************************************************************
Packit Service 3470d1
 */
Packit Service 3470d1
Packit Service 3470d1
#include <stdlib.h>
Packit Service 3470d1
#include <sys/socket.h>
Packit Service 3470d1
#include <sys/un.h>
Packit Service 3470d1
#include <sys/stat.h>
Packit Service 3470d1
#include "cs_sockwrap.h"
Packit Service 3470d1
#include <fcntl.h>
Packit Service 3470d1
#include "cs_g.h"
Packit Service 3470d1
#include <errno.h>
Packit Service 3470d1
#include <string.h>
Packit Service 3470d1
Packit Service 3470d1
#define QLEN	10
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
#define	CLI_PERM	S_IRWXU			/* rwx for user only */
Packit Service 3470d1
Packit Service 3470d1
#define MAXWAIT  30
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
/*
Packit Service 3470d1
 * @brief
Packit Service 3470d1
 *
Packit Service 3470d1
 * cs_local_comm_init --
Packit Service 3470d1
 *
Packit Service 3470d1
 * This function takes a string as an argument and creates a AF_UNIX
Packit Service 3470d1
 * socket with the string supplied to it as the address in the socket
Packit Service 3470d1
 * structure.
Packit Service 3470d1
 * This routine is to be called by a program that needs a server socket.
Packit Service 3470d1
 *
Packit Service 3470d1
 * @param[in] name	pointer to unique socket address string
Packit Service 3470d1
 *
Packit Service 3470d1
 * @return *  socket descriptor on sucess or (-1) on failure
Packit Service 3470d1
 *
Packit Service 3470d1
 * NOTE: For VxWorks socket support, please refer to the WindRiver Network Stack
Packit Service 3470d1
 * Programmer's Guide 6.9 (Section 5.3 - Working with Local Domain Sockets)
Packit Service 3470d1
 *
Packit Service 3470d1
 */
Packit Service 3470d1
int
Packit Service 3470d1
cs_local_comm_init(const char *name)
Packit Service 3470d1
{
Packit Service 3470d1
	int			fd;
Packit Service 3470d1
	int			len;
Packit Service 3470d1
	int			err;
Packit Service 3470d1
	struct sockaddr_un	un;
Packit Service 3470d1
Packit Service 3470d1
	if (strlen(name) >= (sizeof(un.sun_path) )) {
Packit Service 3470d1
		errno = ENAMETOOLONG;
Packit Service 3470d1
		return(-1);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	/* create a UNIX domain stream socket */
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	if ((fd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0) {
Packit Service 3470d1
#else
Packit Service 3470d1
	if ((fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0)) < 0) {
Packit Service 3470d1
#endif
Packit Service 3470d1
		return(fd);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	unlink(name);	/* in case it already exists */
Packit Service 3470d1
Packit Service 3470d1
	/* fill in socket address structure */
Packit Service 3470d1
	memset(&un, 0, sizeof(un));
Packit Service 3470d1
	snprintf(un.sun_path, sizeof(un.sun_path), "%s", name);
Packit Service 3470d1
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	un.sun_family = AF_UNIX;
Packit Service 3470d1
	len = offsetof(struct sockaddr_un, sun_path) + strlen(name);
Packit Service 3470d1
#else
Packit Service 3470d1
	un.sun_family = AF_LOCAL;
Packit Service 3470d1
	len = sizeof(struct sockaddr_un);
Packit Service 3470d1
	un.sun_len = len;
Packit Service 3470d1
#endif
Packit Service 3470d1
Packit Service 3470d1
	/* bind the name */
Packit Service 3470d1
	if (bind(fd, (struct sockaddr *)&un, len) < 0) {
Packit Service 3470d1
		goto errout;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	if (listen(fd, QLEN) < 0) {	/* tell kernel we're a server */
Packit Service 3470d1
		goto errout;
Packit Service 3470d1
	}
Packit Service 3470d1
	return(fd);
Packit Service 3470d1
Packit Service 3470d1
errout:
Packit Service 3470d1
	err = errno;
Packit Service 3470d1
	close(fd);
Packit Service 3470d1
	errno = err;
Packit Service 3470d1
	return(-1);
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
/*
Packit Service 3470d1
 * @brief
Packit Service 3470d1
 *
Packit Service 3470d1
 * cs_local_comm_accept --
Packit Service 3470d1
 *
Packit Service 3470d1
 * This function takes a socket descriptor as an argument and waits for
Packit Service 3470d1
 * a client connectio to arrive on it. It accepts the new connection
Packit Service 3470d1
 * checks for to see if the connection is via a socket and whether it
Packit Service 3470d1
 * is writeable and returns with the new socket descriptor if everything
Packit Service 3470d1
 * is successful
Packit Service 3470d1
 *
Packit Service 3470d1
 * @param[in] listenfd	socket to listen for a connection on
Packit Service 3470d1
 *
Packit Service 3470d1
 * @return    socket descriptor on sucess or (-1) on failure
Packit Service 3470d1
 *
Packit Service 3470d1
 */
Packit Service 3470d1
int
Packit Service 3470d1
cs_local_comm_accept(int listenfd)
Packit Service 3470d1
{
Packit Service 3470d1
	int				clifd;
Packit Service 3470d1
	socklen_t			len;
Packit Service 3470d1
	struct sockaddr_un		un;
Packit Service 3470d1
	char				*name;
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	int err;
Packit Service 3470d1
	struct stat			statbuf;
Packit Service 3470d1
#endif
Packit Service 3470d1
Packit Service 3470d1
	/* allocate enough space for longest name plus terminating null */
Packit Service 3470d1
	if ((name = malloc(sizeof(un.sun_path) + 1)) == NULL)
Packit Service 3470d1
		assert(name);
Packit Service 3470d1
	len = sizeof(un);
Packit Service 3470d1
	if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0) {
Packit Service 3470d1
		free(name);
Packit Service 3470d1
		return (clifd);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	len -= offsetof(struct sockaddr_un, sun_path); /* len of pathname */
Packit Service 3470d1
	StringCopy(name, un.sun_path, len);
Packit Service 3470d1
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	if (stat(name, &statbuf) < 0) {
Packit Service 3470d1
		goto errout;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	/* check path to make sure its a socket and writable */
Packit Service 3470d1
	if (S_ISSOCK(statbuf.st_mode) == 0) {
Packit Service 3470d1
		errno = ENOTSOCK;	/* not a socket */
Packit Service 3470d1
		goto errout;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	if ((statbuf.st_mode & (S_IRWXG | S_IRWXO)) ||
Packit Service 3470d1
		(statbuf.st_mode & S_IRWXU) != S_IRWXU) {
Packit Service 3470d1
		  errno = EPERM;
Packit Service 3470d1
		  goto errout;
Packit Service 3470d1
	}
Packit Service 3470d1
#endif
Packit Service 3470d1
Packit Service 3470d1
	unlink(name);
Packit Service 3470d1
	free(name);
Packit Service 3470d1
	return(clifd);
Packit Service 3470d1
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
errout:
Packit Service 3470d1
	err = errno;
Packit Service 3470d1
	close(clifd);
Packit Service 3470d1
	free(name);
Packit Service 3470d1
	errno = err;
Packit Service 3470d1
	return(-1);
Packit Service 3470d1
#endif
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
/*
Packit Service 3470d1
 * @brief
Packit Service 3470d1
 *
Packit Service 3470d1
 * cs_local_comm_connect --
Packit Service 3470d1
 *
Packit Service 3470d1
 * This function takes two string arguments which
Packit Service 3470d1
 * are AF_UNIX socket addresses creates a new socket
Packit Service 3470d1
 * and connects to a specified server socket.
Packit Service 3470d1
 *
Packit Service 3470d1
 * @param[in] srvaddr   Server socket address string
Packit Service 3470d1
 * @param[in] claddr    Client socket address string
Packit Service 3470d1
 *
Packit Service 3470d1
 * @return    socket descriptor on sucess or (-1) on failure
Packit Service 3470d1
 *
Packit Service 3470d1
 * NOTE: For VxWorks socket support, please refer to the WindRiver Network Stack
Packit Service 3470d1
 * Programmer's Guide 6.9 (Section 5.3 - Working with Local Domain Sockets)
Packit Service 3470d1
 *
Packit Service 3470d1
 */
Packit Service 3470d1
int
Packit Service 3470d1
cs_local_comm_connect(const char *srvaddr, const char *claddr)
Packit Service 3470d1
{
Packit Service 3470d1
	int			fd, len, err;
Packit Service 3470d1
	struct sockaddr_un	un, sun;
Packit Service 3470d1
	int			do_unlink = 0;
Packit Service 3470d1
Packit Service 3470d1
	if ((strlen(srvaddr) >= (sizeof(un.sun_path)) ||
Packit Service 3470d1
	     (strlen(claddr) >= sizeof(un.sun_path)))) {
Packit Service 3470d1
		errno = ENAMETOOLONG;
Packit Service 3470d1
		return(-1);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	/* create a UNIX domain stream socket */
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	if ((fd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0) {
Packit Service 3470d1
#else
Packit Service 3470d1
	if ((fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0)) < 0) {
Packit Service 3470d1
#endif
Packit Service 3470d1
		return(-1);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	/* fill socket address structure with our address */
Packit Service 3470d1
	memset(&un, 0, sizeof(un));
Packit Service 3470d1
	StringCopy(un.sun_path, claddr, sizeof(un.sun_path));
Packit Service 3470d1
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	un.sun_family = AF_UNIX;
Packit Service 3470d1
	len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);
Packit Service 3470d1
	unlink(un.sun_path);		/* in case it already exists */
Packit Service 3470d1
#else
Packit Service 3470d1
	un.sun_family = AF_LOCAL;
Packit Service 3470d1
	len = sizeof(struct sockaddr_un);
Packit Service 3470d1
	un.sun_len = len;
Packit Service 3470d1
#endif
Packit Service 3470d1
Packit Service 3470d1
	if (bind(fd, (struct sockaddr *)&un, len) < 0) {
Packit Service 3470d1
		goto errout;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	if (chmod(un.sun_path, CLI_PERM) < 0) {
Packit Service 3470d1
		do_unlink = 1;
Packit Service 3470d1
		goto errout;
Packit Service 3470d1
	}
Packit Service 3470d1
#endif
Packit Service 3470d1
Packit Service 3470d1
	/* fill socket address structure with server's address */
Packit Service 3470d1
	memset(&sun, 0, sizeof(sun));
Packit Service 3470d1
	StringCopy(sun.sun_path, srvaddr, sizeof(un.sun_path));
Packit Service 3470d1
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	sun.sun_family = AF_UNIX;
Packit Service 3470d1
	len = offsetof(struct sockaddr_un, sun_path) + strlen(srvaddr);
Packit Service 3470d1
#else
Packit Service 3470d1
	sun.sun_family = AF_LOCAL;
Packit Service 3470d1
	len = sizeof(struct sockaddr_un);
Packit Service 3470d1
	sun.sun_len = len;
Packit Service 3470d1
#endif
Packit Service 3470d1
	if (connect(fd, (struct sockaddr *)&sun, len) < 0) {
Packit Service 3470d1
		do_unlink = 1;
Packit Service 3470d1
		goto errout;
Packit Service 3470d1
	}
Packit Service 3470d1
	return(fd);
Packit Service 3470d1
Packit Service 3470d1
errout:
Packit Service 3470d1
	err = errno;
Packit Service 3470d1
	close(fd);
Packit Service 3470d1
	if (do_unlink)
Packit Service 3470d1
		unlink(un.sun_path);
Packit Service 3470d1
	errno = err;
Packit Service 3470d1
	return(-1);
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
/**
Packit Service 3470d1
 * @brief
Packit Service 3470d1
 * cs_comm_connect --
Packit Service 3470d1
 *
Packit Service 3470d1
 * This function creates a socket with characteristics of the type requested
Packit Service 3470d1
 * and then connects to the specified channel using that socket. An explicit
Packit Service 3470d1
 * bind by the client is not done as the connect will bind a default address.
Packit Service 3470d1
 * If the connection fails because of an unready or a busy server it retries
Packit Service 3470d1
 * the connection in an exponential  form.
Packit Service 3470d1
 *
Packit Service 3470d1
 * @param[in]  domain   Socket domain
Packit Service 3470d1
 * @param[in]  type     Socket type
Packit Service 3470d1
 * @param[in]  protocol Usually 0
Packit Service 3470d1
 * @param[in]  srv_addr     sockaddr structure of server
Packit Service 3470d1
 * @param[in]  srv_len      len of server sockaddr
Packit Service 3470d1
 *
Packit Service 3470d1
 *
Packit Service 3470d1
 * @return   socket fd is successful, -1 if not
Packit Service 3470d1
 */
Packit Service 3470d1
static int
Packit Service 3470d1
cs_comm_connect(int domain, int type, int protocol,
Packit Service 3470d1
		const struct sockaddr *srv_addr, socklen_t srv_len)
Packit Service 3470d1
{
Packit Service 3470d1
	int wait = 0;
Packit Service 3470d1
	int fd = -1;
Packit Service 3470d1
Packit Service 3470d1
	if ((fd = socket(domain, type, protocol) <0)) {
Packit Service 3470d1
	    return (-1);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	while  (wait++ < MAXWAIT) {
Packit Service 3470d1
		if (connect(fd, srv_addr, srv_len) == 0) {
Packit Service 3470d1
			return (fd);
Packit Service 3470d1
		}else {
Packit Service 3470d1
			if (errno != ETIMEDOUT &&
Packit Service 3470d1
			    errno != ECONNREFUSED) {
Packit Service 3470d1
				goto exit_func;
Packit Service 3470d1
			}
Packit Service 3470d1
		}
Packit Service 3470d1
Packit Service 3470d1
		sleep(MAXWAIT - wait);
Packit Service 3470d1
	}
Packit Service 3470d1
exit_func:
Packit Service 3470d1
	close(fd);
Packit Service 3470d1
	return (-1);
Packit Service 3470d1
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
/**
Packit Service 3470d1
 * @brief
Packit Service 3470d1
 * cs_tcp_comm_connect --
Packit Service 3470d1
 *
Packit Service 3470d1
 * This function initiates a tcp connect stream connection.
Packit Service 3470d1
 * Used for demo purposes at this point.
Packit Service 3470d1
 *
Packit Service 3470d1
 * @param[in]  srv_addr     sockaddr structure of server
Packit Service 3470d1
 * @param[in]  srv_len      len of server sockaddr
Packit Service 3470d1
 *
Packit Service 3470d1
 * @return   socket fd is successful, -1 if not
Packit Service 3470d1
 */
Packit Service 3470d1
int
Packit Service 3470d1
cs_tcp_comm_connect(const struct sockaddr *srv_addr, socklen_t srv_len)
Packit Service 3470d1
{
Packit Service 3470d1
	return (cs_comm_connect(AF_INET, SOCK_STREAM, 0, srv_addr, srv_len));
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
/**
Packit Service 3470d1
 * @brief
Packit Service 3470d1
 * cs_udp_comm_connect --
Packit Service 3470d1
 *
Packit Service 3470d1
 * This function initiates a udp connect stream connection.
Packit Service 3470d1
 * Used for demo purposes at this point.
Packit Service 3470d1
 *
Packit Service 3470d1
 * @param[in]  srv_addr     sockaddr structure of server
Packit Service 3470d1
 * @param[in]  srv_len      len of server sockaddr
Packit Service 3470d1
 *
Packit Service 3470d1
 * @return   socket fd is successful, -1 if not
Packit Service 3470d1
 */
Packit Service 3470d1
int
Packit Service 3470d1
cs_udp_comm_connect(const struct sockaddr *srv_addr, socklen_t srv_len)
Packit Service 3470d1
{
Packit Service 3470d1
	return (cs_comm_connect(AF_INET, SOCK_DGRAM, 0, srv_addr, srv_len));
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
/**
Packit Service 3470d1
 * @brief
Packit Service 3470d1
 *
Packit Service 3470d1
 * cs_set_fd_non_block --
Packit Service 3470d1
 *
Packit Service 3470d1
 * This function sets the fd passed in to non-blocking.
Packit Service 3470d1
 *
Packit Service 3470d1
 * @params[in]  fd  file descriptor
Packit Service 3470d1
 *
Packit Service 3470d1
 * @return	1 on success, (-1) on failure
Packit Service 3470d1
 *
Packit Service 3470d1
 */
Packit Service 3470d1
int
Packit Service 3470d1
cs_set_fd_non_block(int fd)
Packit Service 3470d1
{
Packit Service 3470d1
	/* TBD on vxworks */
Packit Service 3470d1
#ifdef __LINUX__
Packit Service 3470d1
	int options;
Packit Service 3470d1
Packit Service 3470d1
	if ((options = fcntl(fd, F_GETFL)) < 0) {
Packit Service 3470d1
		IB_LOG_ERROR_FMT(__func__, "fcntl get Error %s\n",
Packit Service 3470d1
						strerror(errno));
Packit Service 3470d1
		return (-1);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	options |= O_NONBLOCK;
Packit Service 3470d1
Packit Service 3470d1
	if (fcntl(fd, F_SETFL, options) < 0) {
Packit Service 3470d1
		IB_LOG_ERROR_FMT(__func__, "fcntl set Error %s\n",
Packit Service 3470d1
						strerror(errno));
Packit Service 3470d1
		return (-1);
Packit Service 3470d1
	}
Packit Service 3470d1
#endif
Packit Service 3470d1
Packit Service 3470d1
	return (1);
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1