bd17a7cd0c8b05acf6de8ca7a8d71aaf5e6b3ac9
[framework/appfw/app-checker.git] / src / ac_sock.c
1 /*
2  *  app-checker
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 \r
22 \r
23 #include <sys/types.h>\r
24 #include <stdio.h>\r
25 #include <stdlib.h>\r
26 #include <string.h>\r
27 #include <sys/stat.h>\r
28 #include <errno.h>\r
29 #include <fcntl.h>\r
30 \r
31 \r
32 #include "ac_sock.h"\r
33 #include "internal.h"\r
34 \r
35 static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen,\r
36                    int nsec);\r
37 \r
38 static inline void __set_sock_option(int fd, int cli)\r
39 {\r
40         int size;\r
41         struct timeval tv = { 5, 200 * 1000 };  /*  5.2 sec */\r
42 \r
43         size = AC_SOCK_MAXBUFF;\r
44         setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));\r
45         setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));\r
46         if (cli)\r
47                 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));\r
48 }\r
49 \r
50 int _create_server_sock()\r
51 {\r
52         struct sockaddr_un saddr;\r
53         struct sockaddr_un p_saddr;\r
54         int fd;\r
55 \r
56         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);\r
57         /*  support above version 2.6.27*/\r
58         if (fd < 0) {\r
59                 if(errno == EINVAL) {\r
60                         fd = socket(AF_UNIX, SOCK_STREAM, 0);\r
61                         if(fd < 0) {\r
62                                 _E("second chance - socket create error");\r
63                                 return -1;\r
64                         }\r
65                 } else {\r
66                         _E("socket error");\r
67                         return -1;\r
68                 }\r
69         }\r
70 \r
71         bzero(&saddr, sizeof(saddr));\r
72         saddr.sun_family = AF_UNIX;\r
73         snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s",AC_SOCK_NAME);\r
74         unlink(saddr.sun_path);\r
75         \r
76         if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {\r
77                 _E("bind error");\r
78                 return -1;\r
79         }\r
80 \r
81         if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {\r
82                 /* Flawfinder: ignore*/\r
83                 _E("failed to change the socket permission");\r
84                 return -1;\r
85         }\r
86 \r
87         __set_sock_option(fd, 0);\r
88 \r
89         if (listen(fd, 10) == -1) {\r
90                 _E("listen error");\r
91                 return -1;\r
92         }       \r
93 \r
94         return fd;\r
95 }\r
96 \r
97 int _create_client_sock()\r
98 {\r
99         int fd = -1;\r
100         struct sockaddr_un saddr = { 0, };\r
101         int retry = 1;\r
102         int ret = -1;\r
103 \r
104         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);    \r
105         /*  support above version 2.6.27*/\r
106         if (fd < 0) {\r
107                 if (errno == EINVAL) {\r
108                         fd = socket(AF_UNIX, SOCK_STREAM, 0);\r
109                         if (fd < 0) {\r
110                                 _E("second chance - socket create error");\r
111                                 return -1;\r
112                         }\r
113                 } else {\r
114                         _E("socket error");\r
115                         return -1;\r
116                 }\r
117         }\r
118 \r
119         saddr.sun_family = AF_UNIX;\r
120         snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s", AC_SOCK_NAME);\r
121  retry_con:\r
122         ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),\r
123                         100 * 1000);\r
124         if (ret < -1) {\r
125                 _E("maybe peer not launched or peer daed\n");\r
126                 if (retry > 0) {\r
127                         usleep(100 * 1000);\r
128                         retry--;\r
129                         goto retry_con;\r
130                 }\r
131         }\r
132         if (ret < 0) {\r
133                 close(fd);\r
134                 return -1;\r
135         }\r
136 \r
137         __set_sock_option(fd, 1);\r
138 \r
139         return fd;\r
140 }\r
141 \r
142 static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,\r
143                    int nsec)\r
144 {\r
145         int flags;\r
146         int ret;\r
147         int error;\r
148         socklen_t len;\r
149         fd_set readfds;\r
150         fd_set writefds;\r
151         struct timeval timeout;\r
152 \r
153         flags = fcntl(fd, F_GETFL, 0);\r
154         fcntl(fd, F_SETFL, flags | O_NONBLOCK);\r
155 \r
156         error = 0;\r
157         if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {\r
158                 if (errno != EAGAIN && errno != EINPROGRESS) {\r
159                         fcntl(fd, F_SETFL, flags);      \r
160                         return (-2);\r
161                 }\r
162         }\r
163 \r
164         /* Do whatever we want while the connect is taking place. */\r
165         if (ret == 0)\r
166                 goto done;      /* connect completed immediately */\r
167 \r
168         FD_ZERO(&readfds);\r
169         FD_SET(fd, &readfds);\r
170         writefds = readfds;\r
171         timeout.tv_sec = 0;\r
172         timeout.tv_usec = nsec;\r
173 \r
174         if ((ret = select(fd + 1, &readfds, &writefds, NULL, \r
175                         nsec ? &timeout : NULL)) == 0) {\r
176                 close(fd);      /* timeout */\r
177                 errno = ETIMEDOUT;\r
178                 return (-1);\r
179         }\r
180 \r
181         if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {\r
182                 len = sizeof(error);\r
183                 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)\r
184                         return (-1);    /* Solaris pending error */\r
185         } else\r
186                 return (-1);    /* select error: sockfd not set*/\r
187 \r
188  done:\r
189         fcntl(fd, F_SETFL, flags);      \r
190         if (error) {\r
191                 close(fd);      \r
192                 errno = error;\r
193                 return (-1);\r
194         }\r
195         return (0);\r
196 }\r
197 \r
198 /**\r
199  * @brief       Send data (in raw) to the process with 'pid' via socket\r
200  */\r
201 int _app_send_raw(int cmd, unsigned char *data, int datalen)\r
202 {\r
203         int fd;\r
204         int len;\r
205         int res = 0;\r
206         ac_pkt_t *pkt = NULL;\r
207 \r
208         if (data == NULL || datalen > AC_SOCK_MAXBUFF - 8) {\r
209                 _E("keybundle error\n");\r
210                 return -EINVAL;\r
211         }\r
212 \r
213         fd = _create_client_sock();\r
214         if (fd < 0)\r
215                 return -ECOMM;\r
216 \r
217         pkt = (ac_pkt_t *) malloc(sizeof(char) * AC_SOCK_MAXBUFF);\r
218         if (NULL == pkt) {\r
219                 _E("Malloc Failed!");\r
220                 return -ENOMEM;\r
221         }\r
222         memset(pkt, 0, AC_SOCK_MAXBUFF);\r
223 \r
224         pkt->cmd = cmd;\r
225         pkt->len = datalen;\r
226         memcpy(pkt->data, data, datalen);\r
227 \r
228         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {\r
229                 _E("sendto() failed - %d %d", len, datalen + 8);\r
230                 if (errno == EPIPE) {\r
231                         _E("fd:%d\n", fd);\r
232                 }\r
233                 close(fd);\r
234                 if (pkt) {\r
235                         free(pkt);\r
236                         pkt = NULL;\r
237                 }\r
238                 return -ECOMM;\r
239         }\r
240         if (pkt) {\r
241                 free(pkt);\r
242                 pkt = NULL;\r
243         }\r
244 \r
245         len = recv(fd, &res, sizeof(int), 0);\r
246         if (len == -1) {\r
247                 if (errno == EAGAIN) {\r
248                         _E("recv timeout \n");\r
249                         res = -EAGAIN;\r
250                 } else {\r
251                         _E("recv error\n");\r
252                         res = -ECOMM;\r
253                 }\r
254         } else\r
255                 _D("recv result  = %d (%d)", res, len);\r
256         close(fd);\r
257 \r
258         return res;\r
259 }\r
260 \r
261 ac_pkt_t *_app_recv_raw(int fd, int *clifd, struct ucred *cr)\r
262 {\r
263         int len;\r
264         struct sockaddr_un aul_addr = { 0, };\r
265         int sun_size;\r
266         ac_pkt_t *pkt = NULL;\r
267         int cl = sizeof(struct ucred);\r
268 \r
269         sun_size = sizeof(struct sockaddr_un);\r
270 \r
271         if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,\r
272                              (socklen_t *) &sun_size)) == -1) {\r
273                 if (errno != EINTR)\r
274                         _E("accept error");\r
275                 return NULL;\r
276         }\r
277 \r
278         if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,\r
279                        (socklen_t *) &cl) < 0) {\r
280                 _E("peer information error");\r
281                 close(*clifd);\r
282                 return NULL;\r
283         }\r
284 \r
285         pkt = (ac_pkt_t *) malloc(sizeof(char) * AC_SOCK_MAXBUFF);\r
286         if(pkt == NULL) {\r
287                 close(*clifd);\r
288                 return NULL;\r
289         }\r
290         memset(pkt, 0, AC_SOCK_MAXBUFF);\r
291 \r
292         __set_sock_option(*clifd, 1);\r
293 \r
294  retry_recv:\r
295         /* receive single packet from socket */\r
296         len = recv(*clifd, pkt, AC_SOCK_MAXBUFF, 0);\r
297         if (len < 0)\r
298                 if (errno == EINTR)\r
299                         goto retry_recv;\r
300 \r
301         if ((len < 8) || (len != (pkt->len + 8))) {\r
302                 _E("recv error %d %d", len, pkt->len);\r
303                 free(pkt);\r
304                 close(*clifd);\r
305                 return NULL;\r
306         }\r
307 \r
308         return pkt;\r
309 }\r
310 \r
311 int _send_result_to_server(int fd, int res)\r
312 {\r
313         if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {\r
314                 if (errno == EPIPE)\r
315                         _E("send failed due to EPIPE.\n");\r
316                 _E("send fail to client");\r
317         }\r
318         close(fd);\r
319         return 0;\r
320 }\r