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
14int 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
98err:
99	if (*sockfd)
100		close(*sockfd);
101
102	return ret;
103}
104
105int 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
161int 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
216int 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