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