GNU Linux-libre 4.19.245-gnu1
[releases.git] / tools / testing / selftests / android / ion / ipcsocket.c
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 }