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 
opensocket(int * sockfd,const char * name,int connecttype)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 
sendtosocket(int sockfd,struct socketdata * skdata)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 
receivefromsocket(int sockfd,struct socketdata * skdata)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 
closesocket(int sockfd,char * name)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