18c2ecf20Sopenharmony_ci#include <stdio.h>
28c2ecf20Sopenharmony_ci#include <stdlib.h>
38c2ecf20Sopenharmony_ci#include <string.h>
48c2ecf20Sopenharmony_ci#include <unistd.h>
58c2ecf20Sopenharmony_ci#include <sys/types.h>
68c2ecf20Sopenharmony_ci#include <sys/socket.h>
78c2ecf20Sopenharmony_ci#include <sys/time.h>
88c2ecf20Sopenharmony_ci#include <sys/un.h>
98c2ecf20Sopenharmony_ci#include <errno.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include "ipcsocket.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciint opensocket(int *sockfd, const char *name, int connecttype)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	int ret, temp = 1;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	if (!name || strlen(name) > MAX_SOCK_NAME_LEN) {
198c2ecf20Sopenharmony_ci		fprintf(stderr, "<%s>: Invalid socket name.\n", __func__);
208c2ecf20Sopenharmony_ci		return -1;
218c2ecf20Sopenharmony_ci	}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	ret = socket(PF_LOCAL, SOCK_STREAM, 0);
248c2ecf20Sopenharmony_ci	if (ret < 0) {
258c2ecf20Sopenharmony_ci		fprintf(stderr, "<%s>: Failed socket: <%s>\n",
268c2ecf20Sopenharmony_ci			__func__, strerror(errno));
278c2ecf20Sopenharmony_ci		return ret;
288c2ecf20Sopenharmony_ci	}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	*sockfd = ret;
318c2ecf20Sopenharmony_ci	if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
328c2ecf20Sopenharmony_ci		(char *)&temp, sizeof(int)) < 0) {
338c2ecf20Sopenharmony_ci		fprintf(stderr, "<%s>: Failed setsockopt: <%s>\n",
348c2ecf20Sopenharmony_ci		__func__, strerror(errno));
358c2ecf20Sopenharmony_ci		goto err;
368c2ecf20Sopenharmony_ci	}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	sprintf(sock_name, "/tmp/%s", name);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (connecttype == 1) {
418c2ecf20Sopenharmony_ci		/* This is for Server connection */
428c2ecf20Sopenharmony_ci		struct sockaddr_un skaddr;
438c2ecf20Sopenharmony_ci		int clientfd;
448c2ecf20Sopenharmony_ci		socklen_t sklen;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci		unlink(sock_name);
478c2ecf20Sopenharmony_ci		memset(&skaddr, 0, sizeof(skaddr));
488c2ecf20Sopenharmony_ci		skaddr.sun_family = AF_LOCAL;
498c2ecf20Sopenharmony_ci		strcpy(skaddr.sun_path, sock_name);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci		ret = bind(*sockfd, (struct sockaddr *)&skaddr,
528c2ecf20Sopenharmony_ci			SUN_LEN(&skaddr));
538c2ecf20Sopenharmony_ci		if (ret < 0) {
548c2ecf20Sopenharmony_ci			fprintf(stderr, "<%s>: Failed bind: <%s>\n",
558c2ecf20Sopenharmony_ci			__func__, strerror(errno));
568c2ecf20Sopenharmony_ci			goto err;
578c2ecf20Sopenharmony_ci		}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci		ret = listen(*sockfd, 5);
608c2ecf20Sopenharmony_ci		if (ret < 0) {
618c2ecf20Sopenharmony_ci			fprintf(stderr, "<%s>: Failed listen: <%s>\n",
628c2ecf20Sopenharmony_ci			__func__, strerror(errno));
638c2ecf20Sopenharmony_ci			goto err;
648c2ecf20Sopenharmony_ci		}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci		memset(&skaddr, 0, sizeof(skaddr));
678c2ecf20Sopenharmony_ci		sklen = sizeof(skaddr);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci		ret = accept(*sockfd, (struct sockaddr *)&skaddr,
708c2ecf20Sopenharmony_ci			(socklen_t *)&sklen);
718c2ecf20Sopenharmony_ci		if (ret < 0) {
728c2ecf20Sopenharmony_ci			fprintf(stderr, "<%s>: Failed accept: <%s>\n",
738c2ecf20Sopenharmony_ci			__func__, strerror(errno));
748c2ecf20Sopenharmony_ci			goto err;
758c2ecf20Sopenharmony_ci		}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci		clientfd = ret;
788c2ecf20Sopenharmony_ci		*sockfd = clientfd;
798c2ecf20Sopenharmony_ci	} else {
808c2ecf20Sopenharmony_ci		/* This is for client connection */
818c2ecf20Sopenharmony_ci		struct sockaddr_un skaddr;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci		memset(&skaddr, 0, sizeof(skaddr));
848c2ecf20Sopenharmony_ci		skaddr.sun_family = AF_LOCAL;
858c2ecf20Sopenharmony_ci		strcpy(skaddr.sun_path, sock_name);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci		ret = connect(*sockfd, (struct sockaddr *)&skaddr,
888c2ecf20Sopenharmony_ci			SUN_LEN(&skaddr));
898c2ecf20Sopenharmony_ci		if (ret < 0) {
908c2ecf20Sopenharmony_ci			fprintf(stderr, "<%s>: Failed connect: <%s>\n",
918c2ecf20Sopenharmony_ci			__func__, strerror(errno));
928c2ecf20Sopenharmony_ci			goto err;
938c2ecf20Sopenharmony_ci		}
948c2ecf20Sopenharmony_ci	}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	return 0;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cierr:
998c2ecf20Sopenharmony_ci	if (*sockfd)
1008c2ecf20Sopenharmony_ci		close(*sockfd);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	return ret;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciint sendtosocket(int sockfd, struct socketdata *skdata)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	int ret, buffd;
1088c2ecf20Sopenharmony_ci	unsigned int len;
1098c2ecf20Sopenharmony_ci	char cmsg_b[CMSG_SPACE(sizeof(int))];
1108c2ecf20Sopenharmony_ci	struct cmsghdr *cmsg;
1118c2ecf20Sopenharmony_ci	struct msghdr msgh;
1128c2ecf20Sopenharmony_ci	struct iovec iov;
1138c2ecf20Sopenharmony_ci	struct timeval timeout;
1148c2ecf20Sopenharmony_ci	fd_set selFDs;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	if (!skdata) {
1178c2ecf20Sopenharmony_ci		fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
1188c2ecf20Sopenharmony_ci		return -1;
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	FD_ZERO(&selFDs);
1228c2ecf20Sopenharmony_ci	FD_SET(0, &selFDs);
1238c2ecf20Sopenharmony_ci	FD_SET(sockfd, &selFDs);
1248c2ecf20Sopenharmony_ci	timeout.tv_sec = 20;
1258c2ecf20Sopenharmony_ci	timeout.tv_usec = 0;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	ret = select(sockfd+1, NULL, &selFDs, NULL, &timeout);
1288c2ecf20Sopenharmony_ci	if (ret < 0) {
1298c2ecf20Sopenharmony_ci		fprintf(stderr, "<%s>: Failed select: <%s>\n",
1308c2ecf20Sopenharmony_ci		__func__, strerror(errno));
1318c2ecf20Sopenharmony_ci		return -1;
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if (FD_ISSET(sockfd, &selFDs)) {
1358c2ecf20Sopenharmony_ci		buffd = skdata->data;
1368c2ecf20Sopenharmony_ci		len = skdata->len;
1378c2ecf20Sopenharmony_ci		memset(&msgh, 0, sizeof(msgh));
1388c2ecf20Sopenharmony_ci		msgh.msg_control = &cmsg_b;
1398c2ecf20Sopenharmony_ci		msgh.msg_controllen = CMSG_LEN(len);
1408c2ecf20Sopenharmony_ci		iov.iov_base = "OK";
1418c2ecf20Sopenharmony_ci		iov.iov_len = 2;
1428c2ecf20Sopenharmony_ci		msgh.msg_iov = &iov;
1438c2ecf20Sopenharmony_ci		msgh.msg_iovlen = 1;
1448c2ecf20Sopenharmony_ci		cmsg = CMSG_FIRSTHDR(&msgh);
1458c2ecf20Sopenharmony_ci		cmsg->cmsg_level = SOL_SOCKET;
1468c2ecf20Sopenharmony_ci		cmsg->cmsg_type = SCM_RIGHTS;
1478c2ecf20Sopenharmony_ci		cmsg->cmsg_len = CMSG_LEN(len);
1488c2ecf20Sopenharmony_ci		memcpy(CMSG_DATA(cmsg), &buffd, len);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci		ret = sendmsg(sockfd, &msgh, MSG_DONTWAIT);
1518c2ecf20Sopenharmony_ci		if (ret < 0) {
1528c2ecf20Sopenharmony_ci			fprintf(stderr, "<%s>: Failed sendmsg: <%s>\n",
1538c2ecf20Sopenharmony_ci			__func__, strerror(errno));
1548c2ecf20Sopenharmony_ci			return -1;
1558c2ecf20Sopenharmony_ci		}
1568c2ecf20Sopenharmony_ci	}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	return 0;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ciint receivefromsocket(int sockfd, struct socketdata *skdata)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	int ret, buffd;
1648c2ecf20Sopenharmony_ci	unsigned int len = 0;
1658c2ecf20Sopenharmony_ci	char cmsg_b[CMSG_SPACE(sizeof(int))];
1668c2ecf20Sopenharmony_ci	struct cmsghdr *cmsg;
1678c2ecf20Sopenharmony_ci	struct msghdr msgh;
1688c2ecf20Sopenharmony_ci	struct iovec iov;
1698c2ecf20Sopenharmony_ci	fd_set recvFDs;
1708c2ecf20Sopenharmony_ci	char data[32];
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	if (!skdata) {
1738c2ecf20Sopenharmony_ci		fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
1748c2ecf20Sopenharmony_ci		return -1;
1758c2ecf20Sopenharmony_ci	}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	FD_ZERO(&recvFDs);
1788c2ecf20Sopenharmony_ci	FD_SET(0, &recvFDs);
1798c2ecf20Sopenharmony_ci	FD_SET(sockfd, &recvFDs);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	ret = select(sockfd+1, &recvFDs, NULL, NULL, NULL);
1828c2ecf20Sopenharmony_ci	if (ret < 0) {
1838c2ecf20Sopenharmony_ci		fprintf(stderr, "<%s>: Failed select: <%s>\n",
1848c2ecf20Sopenharmony_ci		__func__, strerror(errno));
1858c2ecf20Sopenharmony_ci		return -1;
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	if (FD_ISSET(sockfd, &recvFDs)) {
1898c2ecf20Sopenharmony_ci		len = sizeof(buffd);
1908c2ecf20Sopenharmony_ci		memset(&msgh, 0, sizeof(msgh));
1918c2ecf20Sopenharmony_ci		msgh.msg_control = &cmsg_b;
1928c2ecf20Sopenharmony_ci		msgh.msg_controllen = CMSG_LEN(len);
1938c2ecf20Sopenharmony_ci		iov.iov_base = data;
1948c2ecf20Sopenharmony_ci		iov.iov_len = sizeof(data)-1;
1958c2ecf20Sopenharmony_ci		msgh.msg_iov = &iov;
1968c2ecf20Sopenharmony_ci		msgh.msg_iovlen = 1;
1978c2ecf20Sopenharmony_ci		cmsg = CMSG_FIRSTHDR(&msgh);
1988c2ecf20Sopenharmony_ci		cmsg->cmsg_level = SOL_SOCKET;
1998c2ecf20Sopenharmony_ci		cmsg->cmsg_type = SCM_RIGHTS;
2008c2ecf20Sopenharmony_ci		cmsg->cmsg_len = CMSG_LEN(len);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci		ret = recvmsg(sockfd, &msgh, MSG_DONTWAIT);
2038c2ecf20Sopenharmony_ci		if (ret < 0) {
2048c2ecf20Sopenharmony_ci			fprintf(stderr, "<%s>: Failed recvmsg: <%s>\n",
2058c2ecf20Sopenharmony_ci			__func__, strerror(errno));
2068c2ecf20Sopenharmony_ci			return -1;
2078c2ecf20Sopenharmony_ci		}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci		memcpy(&buffd, CMSG_DATA(cmsg), len);
2108c2ecf20Sopenharmony_ci		skdata->data = buffd;
2118c2ecf20Sopenharmony_ci		skdata->len = len;
2128c2ecf20Sopenharmony_ci	}
2138c2ecf20Sopenharmony_ci	return 0;
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ciint closesocket(int sockfd, char *name)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	char sockname[MAX_SOCK_NAME_LEN];
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	if (sockfd)
2218c2ecf20Sopenharmony_ci		close(sockfd);
2228c2ecf20Sopenharmony_ci	sprintf(sockname, "/tmp/%s", name);
2238c2ecf20Sopenharmony_ci	unlink(sockname);
2248c2ecf20Sopenharmony_ci	shutdown(sockfd, 2);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	return 0;
2278c2ecf20Sopenharmony_ci}
228