Initialize Tizen 2.3
[framework/appfw/aul-1.git] / src / app_sock.c
1 /*
2  *  aul
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
22
23 #include <sys/types.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <sys/smack.h>
29 #include <errno.h>
30 #include <fcntl.h>
31
32 #include "app_sock.h"
33 #include "simple_util.h"
34
35 static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen,
36                    int nsec);
37
38
39 static inline void __set_sock_option(int fd, int cli)
40 {
41         int size;
42         struct timeval tv = { 5, 200 * 1000 };  /*  5.2 sec */
43
44         size = AUL_SOCK_MAXBUFF;
45         setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
46         setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
47         if (cli)
48                 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
49 }
50
51 int __create_server_sock(int pid)
52 {
53         struct sockaddr_un saddr;
54         struct sockaddr_un p_saddr;
55         int fd;
56         mode_t orig_mask;
57
58         /* Create basedir for our sockets */
59         orig_mask = umask(0);
60         (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
61         umask(orig_mask);
62
63         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
64         /*  support above version 2.6.27*/
65         if (fd < 0) {
66                 if (errno == EINVAL) {
67                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
68                         if (fd < 0) {
69                                 _E("second chance - socket create error");
70                                 return -1;
71                         }
72                 } else {
73                         _E("socket error");
74                         return -1;
75                 }
76         }
77
78         memset(&saddr, 0, sizeof(saddr));
79         saddr.sun_family = AF_UNIX;
80         snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
81         unlink(saddr.sun_path);
82
83         /* labeling to socket for SMACK */
84         if(getuid() == 0) {     // this is meaningful iff current user is ROOT
85                 if(smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) {
86                         /* in case of unsupported filesystem on 'socket' */
87                         /* or permission error by using 'emulator', bypass*/
88                         if((errno != EOPNOTSUPP) && (errno != EPERM)) {
89                                 _E("labeling to socket(IPOUT) error");
90                                 close(fd);
91                                 return -1;
92                         }
93                 }
94                 if(smack_fsetlabel(fd, "*", SMACK_LABEL_IPIN) != 0) {
95                         /* in case of unsupported filesystem on 'socket' */
96                         /* or permission error by using 'emulator', bypass*/
97                         if((errno != EOPNOTSUPP) && (errno != EPERM)) {
98                                 _E("labeling to socket(IPIN) error");
99                                 close(fd);
100                                 return -1;
101                         }
102                 }
103         }
104
105         if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
106                 _E("bind error");
107                 close(fd);
108                 return -1;
109         }
110
111         if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
112                 /* Flawfinder: ignore*/
113                 _E("failed to change the socket permission");
114                 close(fd);
115                 return -1;
116         }
117
118         __set_sock_option(fd, 0);
119
120         if (listen(fd, 128) == -1) {
121                 _E("listen error");
122                 close(fd);
123                 return -1;
124         }
125
126         /* support app launched by shell script */
127         if (pid != LAUNCHPAD_PID) {
128                 int pgid;
129                 pgid = getpgid(pid);
130                 if (pgid > 1) {
131                         snprintf(p_saddr.sun_path, UNIX_PATH_MAX, "%s/%d",
132                                  AUL_SOCK_PREFIX, pgid);
133                         if (link(saddr.sun_path, p_saddr.sun_path) < 0) {
134                                 if (errno == EEXIST)
135                                         _D("pg path - already exists");
136                                 else
137                                         _E("pg path - unknown create error");
138                         }
139                 }
140         }
141
142         return fd;
143 }
144
145 int __create_client_sock(int pid)
146 {
147         int fd = -1;
148         struct sockaddr_un saddr = { 0, };
149         int retry = 2;
150         int ret = -1;
151
152         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);    
153         /*  support above version 2.6.27*/
154         if (fd < 0) {
155                 if (errno == EINVAL) {
156                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
157                         if (fd < 0) {
158                                 _E("second chance - socket create error");
159                                 return -1;
160                         }
161                 } else {
162                         _E("socket error");
163                         return -1;
164                 }
165         }
166
167         saddr.sun_family = AF_UNIX;
168         snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
169  retry_con:
170         ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
171                         100 * 1000);
172         if (ret < -1) {
173                 _E("maybe peer not launched or peer daed\n");
174                 if (retry > 0) {
175                         usleep((1+2*(2-retry))*100 * 1000);
176                         retry--;
177                         goto retry_con;
178                 }
179         }
180         if (ret < 0) {
181                 close(fd);
182                 return -1;
183         }
184
185         __set_sock_option(fd, 1);
186
187         return fd;
188 }
189
190 static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,
191                    int nsec)
192 {
193         int flags;
194         int ret;
195         int error;
196         socklen_t len;
197         fd_set readfds;
198         fd_set writefds;
199         struct timeval timeout;
200
201         flags = fcntl(fd, F_GETFL, 0);
202         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
203
204         error = 0;
205         if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {
206                 if (errno != EAGAIN && errno != EINPROGRESS) {
207                         fcntl(fd, F_SETFL, flags);      
208                         return (-2);
209                 }
210         }
211
212         /* Do whatever we want while the connect is taking place. */
213         if (ret == 0)
214                 goto done;      /* connect completed immediately */
215
216         FD_ZERO(&readfds);
217         FD_SET(fd, &readfds);
218         writefds = readfds;
219         timeout.tv_sec = 0;
220         timeout.tv_usec = nsec;
221
222         if ((ret = select(fd + 1, &readfds, &writefds, NULL, 
223                         nsec ? &timeout : NULL)) == 0) {
224                 close(fd);      /* timeout */
225                 errno = ETIMEDOUT;
226                 return (-1);
227         }
228
229         if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
230                 len = sizeof(error);
231                 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
232                         return (-1);    /* Solaris pending error */
233         } else
234                 return (-1);    /* select error: sockfd not set*/
235
236  done:
237         (void) fcntl(fd, F_SETFL, flags);
238         if (error) {
239                 close(fd);
240                 errno = error;
241                 return (-1);
242         }
243         return (0);
244 }
245
246 /**
247  * @brief       Send data (in raw) to the process with 'pid' via socket
248  */
249 int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen)
250 {
251         int fd;
252         int len;
253         int ret;
254         int res = 0;
255         app_pkt_t *pkt = NULL;
256
257         if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
258                 _E("keybundle error\n");
259                 return -EINVAL;
260         }
261
262         _D("pid(%d) : cmd(%d)", pid, cmd);
263
264         fd = __create_client_sock(pid);
265         if (fd < 0)
266                 return -ECOMM;
267
268         /* aul_app_is_running timeout : 25sec */
269         if(cmd == APP_IS_RUNNING) {
270                 struct timeval tv = { 25, 0 };
271                 ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
272                 if ( ret < 0 ) {
273                         _E("setsockopt error");
274                 }
275         }
276
277         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
278         if (NULL == pkt) {
279                 _E("Malloc Failed!");
280                 return -ENOMEM;
281         }
282         memset(pkt, 0, AUL_SOCK_MAXBUFF);
283
284         pkt->cmd = cmd;
285         pkt->len = datalen;
286         memcpy(pkt->data, kb_data, datalen);
287
288         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
289                 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
290                 if(len > 0) {
291                         while (len != datalen + 8) {
292                                 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
293                                 if (ret < 0) {
294                                         _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
295                                         if (errno == EPIPE) {
296                                                 _E("pid:%d, fd:%d\n", pid, fd);
297                                         }
298                                         close(fd);
299                                         if (pkt) {
300                                                 free(pkt);
301                                                 pkt = NULL;
302                                         }
303                                         return -ECOMM;
304                                 }
305                                 len += ret;
306                                 _D("sendto() len - %d %d", len, datalen + 8);
307                         }
308                 } else {
309                         if (errno == EPIPE) {
310                                 _E("pid:%d, fd:%d\n", pid, fd);
311                         }
312                         close(fd);
313                         if (pkt) {
314                                 free(pkt);
315                                 pkt = NULL;
316                         }
317                         return -ECOMM;
318                 }
319         }
320         if (pkt) {
321                 free(pkt);
322                 pkt = NULL;
323         }
324
325 retry_recv:
326         len = recv(fd, &res, sizeof(int), 0);
327         if (len == -1) {
328                 if (errno == EAGAIN) {
329                         _E("recv timeout : cmd(%d) %s", cmd, strerror(errno));
330                         res = -EAGAIN;
331                 } else if (errno == EINTR) {
332                         _D("recv : %s", strerror(errno));
333                         goto retry_recv;
334                 } else {
335                         _E("recv error : %s", strerror(errno));
336                         res = -ECOMM;
337                 }
338         }
339         close(fd);
340
341         return res;
342 }
343
344 int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen)
345 {
346         int fd;
347         int len;
348         int ret;
349         int res = 0;
350         app_pkt_t *pkt = NULL;
351
352         if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
353                 _E("keybundle error\n");
354                 return -EINVAL;
355         }
356
357         _D("pid(%d) : cmd(%d)", pid, cmd);
358
359         fd = __create_client_sock(pid);
360         if (fd < 0)
361                 return -ECOMM;
362
363         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
364         if (NULL == pkt) {
365                 _E("Malloc Failed!");
366                 return -ENOMEM;
367         }
368         memset(pkt, 0, AUL_SOCK_MAXBUFF);
369
370         pkt->cmd = cmd;
371         pkt->len = datalen;
372         memcpy(pkt->data, kb_data, datalen);
373
374         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
375                 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
376                 if(len > 0) {
377                         while (len != datalen + 8) {
378                                 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
379                                 if (ret < 0) {
380                                         _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
381                                         if (errno == EPIPE) {
382                                                 _E("pid:%d, fd:%d\n", pid, fd);
383                                         }
384                                         close(fd);
385                                         if (pkt) {
386                                                 free(pkt);
387                                                 pkt = NULL;
388                                         }
389                                         return -ECOMM;
390                                 }
391                                 len += ret;
392                                 _D("sendto() len - %d %d", len, datalen + 8);
393                         }
394                 } else {
395                         if (errno == EPIPE) {
396                                 _E("pid:%d, fd:%d\n", pid, fd);
397                         }
398                         close(fd);
399                         if (pkt) {
400                                 free(pkt);
401                                 pkt = NULL;
402                         }
403                         return -ECOMM;
404                 }
405         }
406         if (pkt) {
407                 free(pkt);
408                 pkt = NULL;
409         }
410
411         close(fd);
412
413         return res;
414 }
415
416 int __app_send_raw_with_delay_reply(int pid, int cmd, unsigned char *kb_data, int datalen)
417 {
418         int fd;
419         int len;
420         int ret;
421         app_pkt_t *pkt = NULL;
422
423         if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
424                 _E("keybundle error\n");
425                 return -EINVAL;
426         }
427
428         _D("pid(%d) : cmd(%d)", pid, cmd);
429
430         fd = __create_client_sock(pid);
431         if (fd < 0)
432                 return -ECOMM;
433
434         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
435         if (NULL == pkt) {
436                 _E("Malloc Failed!");
437                 return -ENOMEM;
438         }
439         memset(pkt, 0, AUL_SOCK_MAXBUFF);
440
441         pkt->cmd = cmd;
442         pkt->len = datalen;
443         memcpy(pkt->data, kb_data, datalen);
444
445         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
446                 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
447                 if(len > 0) {
448                         while (len != datalen + 8) {
449                                 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
450                                 if (ret < 0) {
451                                         _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
452                                         if (errno == EPIPE) {
453                                                 _E("pid:%d, fd:%d\n", pid, fd);
454                                         }
455                                         close(fd);
456                                         if (pkt) {
457                                                 free(pkt);
458                                                 pkt = NULL;
459                                         }
460                                         return -ECOMM;
461                                 }
462                                 len += ret;
463                                 _D("sendto() len - %d %d", len, datalen + 8);
464                         }
465                 } else {
466                         if (errno == EPIPE) {
467                                 _E("pid:%d, fd:%d\n", pid, fd);
468                         }
469                         close(fd);
470                         if (pkt) {
471                                 free(pkt);
472                                 pkt = NULL;
473                         }
474                         return -ECOMM;
475                 }
476         }
477         if (pkt) {
478                 free(pkt);
479                 pkt = NULL;
480         }
481
482         return fd;
483 }
484
485 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
486 {
487         int len;
488         int ret;
489         struct sockaddr_un aul_addr = { 0, };
490         int sun_size;
491         app_pkt_t *pkt = NULL;
492         int cl = sizeof(struct ucred);
493
494         sun_size = sizeof(struct sockaddr_un);
495
496         if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
497                              (socklen_t *) &sun_size)) == -1) {
498                 if (errno != EINTR)
499                         _E("accept error");
500                 return NULL;
501         }
502
503         if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
504                        (socklen_t *) &cl) < 0) {
505                 _E("peer information error");
506                 close(*clifd);
507                 return NULL;
508         }
509
510         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
511         if(pkt == NULL) {
512                 close(*clifd);
513                 return NULL;
514         }
515         memset(pkt, 0, AUL_SOCK_MAXBUFF);
516
517         __set_sock_option(*clifd, 1);
518
519  retry_recv:
520         /* receive single packet from socket */
521         len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
522         if (len < 0)
523                 if (errno == EINTR)
524                         goto retry_recv;
525
526         if (len < 8) {
527                 _E("recv error %d %d", len, pkt->len);
528                 free(pkt);
529                 close(*clifd);
530                 return NULL;
531         }
532
533         while( len != (pkt->len + 8) ) {
534                 ret = recv(*clifd, &pkt->data[len-8], AUL_SOCK_MAXBUFF, 0);
535                 if (ret < 0) {
536                         _E("recv error %d %d", len, pkt->len);
537                         free(pkt);
538                         close(*clifd);
539                         return NULL;
540                 }
541                 len += ret;
542                 _D("recv len %d %d", len, pkt->len);
543         }
544
545         return pkt;
546 }
547
548 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen)
549 {
550         int fd;
551         int len;
552         app_pkt_t *pkt = NULL;
553
554         fd = __create_client_sock(pid);
555         if (fd < 0)
556                 return NULL;
557
558         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
559         if (NULL == pkt) {
560                 _E("Malloc Failed!");
561                 return NULL;
562         }
563         memset(pkt, 0, AUL_SOCK_MAXBUFF);
564
565         pkt->cmd = cmd;
566         pkt->len = datalen;
567         if(kb_data) {
568                 memcpy(pkt->data, kb_data, datalen);
569         }
570
571         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
572                 _E("sendto() failed - %d", len);
573                 if (errno == EPIPE) {
574                         _E("pid:%d, fd:%d\n", pid, fd);
575                 }
576                 close(fd);
577
578                 free(pkt);
579                 return NULL;
580         }
581
582 retry_recv:
583        /* receive single packet from socket */
584         len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
585         if (len == -1) {
586                 if (errno == EAGAIN) {
587                         _E("recv timeout \n");
588                         free(pkt);
589                         close(fd);
590                         return NULL;
591                 } else if (errno == EINTR) {
592                         goto retry_recv;
593                 } else {
594                         _E("recv error %s\n", strerror(errno));
595                         free(pkt);
596                         close(fd);
597                         return NULL;
598                 }
599         } else
600                 _D("recv result  = %d", len);
601         close(fd);
602
603         return pkt;
604 }
605
606