Home | History | Annotate | Download | only in ion
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <unistd.h>
      5 #include <sys/types.h>
      6 #include <sys/socket.h>
      7 #include <sys/time.h>
      8 #include <sys/un.h>
      9 #include <errno.h>
     10 
     11 #include "ipcsocket.h"
     12 
     13 
     14 int opensocket(int *sockfd, const char *name, int connecttype)
     15 {
     16 	int ret, temp = 1;
     17 
     18 	if (!name || strlen(name) > MAX_SOCK_NAME_LEN) {
     19 		fprintf(stderr, "<%s>: Invalid socket name.\n", __func__);
     20 		return -1;
     21 	}
     22 
     23 	ret = socket(PF_LOCAL, SOCK_STREAM, 0);
     24 	if (ret < 0) {
     25 		fprintf(stderr, "<%s>: Failed socket: <%s>\n",
     26 			__func__, strerror(errno));
     27 		return ret;
     28 	}
     29 
     30 	*sockfd = ret;
     31 	if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
     32 		(char *)&temp, sizeof(int)) < 0) {
     33 		fprintf(stderr, "<%s>: Failed setsockopt: <%s>\n",
     34 		__func__, strerror(errno));
     35 		goto err;
     36 	}
     37 
     38 	sprintf(sock_name, "/tmp/%s", name);
     39 
     40 	if (connecttype == 1) {
     41 		/* This is for Server connection */
     42 		struct sockaddr_un skaddr;
     43 		int clientfd;
     44 		socklen_t sklen;
     45 
     46 		unlink(sock_name);
     47 		memset(&skaddr, 0, sizeof(skaddr));
     48 		skaddr.sun_family = AF_LOCAL;
     49 		strcpy(skaddr.sun_path, sock_name);
     50 
     51 		ret = bind(*sockfd, (struct sockaddr *)&skaddr,
     52 			SUN_LEN(&skaddr));
     53 		if (ret < 0) {
     54 			fprintf(stderr, "<%s>: Failed bind: <%s>\n",
     55 			__func__, strerror(errno));
     56 			goto err;
     57 		}
     58 
     59 		ret = listen(*sockfd, 5);
     60 		if (ret < 0) {
     61 			fprintf(stderr, "<%s>: Failed listen: <%s>\n",
     62 			__func__, strerror(errno));
     63 			goto err;
     64 		}
     65 
     66 		memset(&skaddr, 0, sizeof(skaddr));
     67 		sklen = sizeof(skaddr);
     68 
     69 		ret = accept(*sockfd, (struct sockaddr *)&skaddr,
     70 			(socklen_t *)&sklen);
     71 		if (ret < 0) {
     72 			fprintf(stderr, "<%s>: Failed accept: <%s>\n",
     73 			__func__, strerror(errno));
     74 			goto err;
     75 		}
     76 
     77 		clientfd = ret;
     78 		*sockfd = clientfd;
     79 	} else {
     80 		/* This is for client connection */
     81 		struct sockaddr_un skaddr;
     82 
     83 		memset(&skaddr, 0, sizeof(skaddr));
     84 		skaddr.sun_family = AF_LOCAL;
     85 		strcpy(skaddr.sun_path, sock_name);
     86 
     87 		ret = connect(*sockfd, (struct sockaddr *)&skaddr,
     88 			SUN_LEN(&skaddr));
     89 		if (ret < 0) {
     90 			fprintf(stderr, "<%s>: Failed connect: <%s>\n",
     91 			__func__, strerror(errno));
     92 			goto err;
     93 		}
     94 	}
     95 
     96 	return 0;
     97 
     98 err:
     99 	if (*sockfd)
    100 		close(*sockfd);
    101 
    102 	return ret;
    103 }
    104 
    105 int sendtosocket(int sockfd, struct socketdata *skdata)
    106 {
    107 	int ret, buffd;
    108 	unsigned int len;
    109 	char cmsg_b[CMSG_SPACE(sizeof(int))];
    110 	struct cmsghdr *cmsg;
    111 	struct msghdr msgh;
    112 	struct iovec iov;
    113 	struct timeval timeout;
    114 	fd_set selFDs;
    115 
    116 	if (!skdata) {
    117 		fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
    118 		return -1;
    119 	}
    120 
    121 	FD_ZERO(&selFDs);
    122 	FD_SET(0, &selFDs);
    123 	FD_SET(sockfd, &selFDs);
    124 	timeout.tv_sec = 20;
    125 	timeout.tv_usec = 0;
    126 
    127 	ret = select(sockfd+1, NULL, &selFDs, NULL, &timeout);
    128 	if (ret < 0) {
    129 		fprintf(stderr, "<%s>: Failed select: <%s>\n",
    130 		__func__, strerror(errno));
    131 		return -1;
    132 	}
    133 
    134 	if (FD_ISSET(sockfd, &selFDs)) {
    135 		buffd = skdata->data;
    136 		len = skdata->len;
    137 		memset(&msgh, 0, sizeof(msgh));
    138 		msgh.msg_control = &cmsg_b;
    139 		msgh.msg_controllen = CMSG_LEN(len);
    140 		iov.iov_base = "OK";
    141 		iov.iov_len = 2;
    142 		msgh.msg_iov = &iov;
    143 		msgh.msg_iovlen = 1;
    144 		cmsg = CMSG_FIRSTHDR(&msgh);
    145 		cmsg->cmsg_level = SOL_SOCKET;
    146 		cmsg->cmsg_type = SCM_RIGHTS;
    147 		cmsg->cmsg_len = CMSG_LEN(len);
    148 		memcpy(CMSG_DATA(cmsg), &buffd, len);
    149 
    150 		ret = sendmsg(sockfd, &msgh, MSG_DONTWAIT);
    151 		if (ret < 0) {
    152 			fprintf(stderr, "<%s>: Failed sendmsg: <%s>\n",
    153 			__func__, strerror(errno));
    154 			return -1;
    155 		}
    156 	}
    157 
    158 	return 0;
    159 }
    160 
    161 int receivefromsocket(int sockfd, struct socketdata *skdata)
    162 {
    163 	int ret, buffd;
    164 	unsigned int len = 0;
    165 	char cmsg_b[CMSG_SPACE(sizeof(int))];
    166 	struct cmsghdr *cmsg;
    167 	struct msghdr msgh;
    168 	struct iovec iov;
    169 	fd_set recvFDs;
    170 	char data[32];
    171 
    172 	if (!skdata) {
    173 		fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
    174 		return -1;
    175 	}
    176 
    177 	FD_ZERO(&recvFDs);
    178 	FD_SET(0, &recvFDs);
    179 	FD_SET(sockfd, &recvFDs);
    180 
    181 	ret = select(sockfd+1, &recvFDs, NULL, NULL, NULL);
    182 	if (ret < 0) {
    183 		fprintf(stderr, "<%s>: Failed select: <%s>\n",
    184 		__func__, strerror(errno));
    185 		return -1;
    186 	}
    187 
    188 	if (FD_ISSET(sockfd, &recvFDs)) {
    189 		len = sizeof(buffd);
    190 		memset(&msgh, 0, sizeof(msgh));
    191 		msgh.msg_control = &cmsg_b;
    192 		msgh.msg_controllen = CMSG_LEN(len);
    193 		iov.iov_base = data;
    194 		iov.iov_len = sizeof(data)-1;
    195 		msgh.msg_iov = &iov;
    196 		msgh.msg_iovlen = 1;
    197 		cmsg = CMSG_FIRSTHDR(&msgh);
    198 		cmsg->cmsg_level = SOL_SOCKET;
    199 		cmsg->cmsg_type = SCM_RIGHTS;
    200 		cmsg->cmsg_len = CMSG_LEN(len);
    201 
    202 		ret = recvmsg(sockfd, &msgh, MSG_DONTWAIT);
    203 		if (ret < 0) {
    204 			fprintf(stderr, "<%s>: Failed recvmsg: <%s>\n",
    205 			__func__, strerror(errno));
    206 			return -1;
    207 		}
    208 
    209 		memcpy(&buffd, CMSG_DATA(cmsg), len);
    210 		skdata->data = buffd;
    211 		skdata->len = len;
    212 	}
    213 	return 0;
    214 }
    215 
    216 int closesocket(int sockfd, char *name)
    217 {
    218 	char sockname[MAX_SOCK_NAME_LEN];
    219 
    220 	if (sockfd)
    221 		close(sockfd);
    222 	sprintf(sockname, "/tmp/%s", name);
    223 	unlink(sockname);
    224 	shutdown(sockfd, 2);
    225 
    226 	return 0;
    227 }
    228