4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <sys/types.h>
29 #include <sys/smack.h>
34 #include "simple_util.h"
36 static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen,
39 char *_socket_prefix = NULL;
40 char *_root_path = NULL;
41 char *_cur_zone = NULL;
44 const char* _get_sock_prefix()
46 if (_socket_prefix == NULL)
47 return "/tmp/alaunch";
49 return _socket_prefix;
52 const char* _get_root_path()
54 if (_root_path == NULL)
60 static inline void __set_sock_option(int fd, int cli)
63 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
65 size = AUL_SOCK_MAXBUFF;
66 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
67 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
69 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
72 int __create_server_sock(int pid)
74 struct sockaddr_un saddr;
75 struct sockaddr_un p_saddr;
79 /* Create basedir for our sockets */
81 (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
84 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
85 /* support above version 2.6.27*/
87 if (errno == EINVAL) {
88 fd = socket(AF_UNIX, SOCK_STREAM, 0);
90 _E("second chance - socket create error: %d", errno);
94 _E("socket error: %d", errno);
99 memset(&saddr, 0, sizeof(saddr));
100 saddr.sun_family = AF_UNIX;
101 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
102 unlink(saddr.sun_path);
104 /* labeling to socket for SMACK */
105 if(getuid() == 0) { // this is meaningful iff current user is ROOT
106 if(smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) {
107 /* in case of unsupported filesystem on 'socket' */
108 /* or permission error by using 'emulator', bypass*/
109 if((errno != EOPNOTSUPP) && (errno != EPERM)) {
110 _E("labeling to socket(IPOUT) error");
115 if(smack_fsetlabel(fd, "*", SMACK_LABEL_IPIN) != 0) {
116 /* in case of unsupported filesystem on 'socket' */
117 /* or permission error by using 'emulator', bypass*/
118 if((errno != EOPNOTSUPP) && (errno != EPERM)) {
119 _E("labeling to socket(IPIN) error");
126 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
127 _E("bind error: %d", errno);
132 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
133 /* Flawfinder: ignore*/
134 _E("failed to change the socket permission");
139 __set_sock_option(fd, 0);
141 if (listen(fd, 128) == -1) {
142 _E("listen error: %d", errno);
147 /* support app launched by shell script */
148 if (pid > 0 || pid == WEB_LAUNCHPAD_PID) {
152 snprintf(p_saddr.sun_path, UNIX_PATH_MAX, "%s/%d",
153 AUL_SOCK_PREFIX, pgid);
154 if (link(saddr.sun_path, p_saddr.sun_path) < 0) {
156 _D("pg path - already exists");
158 _E("pg path - unknown create error");
166 int __create_client_sock(int pid)
169 struct sockaddr_un saddr = { 0, };
173 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
174 /* support above version 2.6.27*/
176 if (errno == EINVAL) {
177 fd = socket(AF_UNIX, SOCK_STREAM, 0);
179 _E("second chance - socket create error: %d", errno);
183 _E("socket error: %d", errno);
188 saddr.sun_family = AF_UNIX;
189 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
191 ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
194 _E("cannot connect the client socket: %d", errno);
196 usleep((1+2*(2-retry))*100 * 1000);
206 __set_sock_option(fd, 1);
211 static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,
220 struct timeval timeout;
222 flags = fcntl(fd, F_GETFL, 0);
223 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
226 if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {
227 if (errno != EAGAIN && errno != EINPROGRESS) {
228 _E("connect error: %d", errno);
229 fcntl(fd, F_SETFL, flags);
234 /* Do whatever we want while the connect is taking place. */
236 goto done; /* connect completed immediately */
239 FD_SET(fd, &readfds);
242 timeout.tv_usec = nsec;
244 if ((ret = select(fd + 1, &readfds, &writefds, NULL,
245 nsec ? &timeout : NULL)) == 0) {
246 _E("select timeout");
247 close(fd); /* timeout */
252 if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
254 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
255 return (-1); /* Solaris pending error */
257 return (-1); /* select error: sockfd not set*/
260 (void) fcntl(fd, F_SETFL, flags);
270 * @brief Send data (in raw) to the process with 'pid' via socket
272 int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen)
278 app_pkt_t *pkt = NULL;
280 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
281 _E("keybundle error\n");
285 _D("pid(%d) : cmd(%d)", pid, cmd);
287 fd = __create_client_sock(pid);
289 _E("cannot create a client socket: %d", fd);
293 /* aul_app_is_running timeout : 25sec */
294 if(cmd == APP_IS_RUNNING) {
295 struct timeval tv = { 25, 0 };
296 ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
298 _E("setsockopt error");
302 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
304 _E("Malloc Failed!");
307 memset(pkt, 0, AUL_SOCK_MAXBUFF);
311 memcpy(pkt->data, kb_data, datalen);
313 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
314 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
316 while (len != datalen + 8) {
317 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
319 _E("second send() failed - %d %d (errno: %d)", ret, datalen + 8, errno);
320 if (errno == EPIPE) {
321 _E("pid:%d, fd:%d\n", pid, fd);
331 _D("send() len - %d %d", len, datalen + 8);
334 if (errno == EPIPE) {
335 _E("pid:%d, fd:%d\n", pid, fd);
343 _E("send() failed: %d %s", errno, strerror(errno));
353 len = recv(fd, &res, sizeof(int), 0);
355 if (errno == EAGAIN) {
356 _E("recv timeout : cmd(%d) %s", cmd, strerror(errno));
358 } else if (errno == EINTR) {
359 _D("recv : %s", strerror(errno));
362 _E("recv error : %s", strerror(errno));
371 int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen)
377 app_pkt_t *pkt = NULL;
379 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
380 _E("keybundle error\n");
384 _D("pid(%d) : cmd(%d)", pid, cmd);
386 fd = __create_client_sock(pid);
390 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
392 _E("Malloc Failed!");
395 memset(pkt, 0, AUL_SOCK_MAXBUFF);
399 memcpy(pkt->data, kb_data, datalen);
401 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
402 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
404 while (len != datalen + 8) {
405 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
407 _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
408 if (errno == EPIPE) {
409 _E("pid:%d, fd:%d\n", pid, fd);
419 _D("sendto() len - %d %d", len, datalen + 8);
422 if (errno == EPIPE) {
423 _E("pid:%d, fd:%d\n", pid, fd);
443 int __app_send_raw_with_delay_reply(int pid, int cmd, unsigned char *kb_data, int datalen)
448 app_pkt_t *pkt = NULL;
450 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
451 _E("keybundle error\n");
455 _D("pid(%d) : cmd(%d)", pid, cmd);
457 fd = __create_client_sock(pid);
461 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
463 _E("Malloc Failed!");
466 memset(pkt, 0, AUL_SOCK_MAXBUFF);
470 memcpy(pkt->data, kb_data, datalen);
472 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
473 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
475 while (len != datalen + 8) {
476 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
478 _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
479 if (errno == EPIPE) {
480 _E("pid:%d, fd:%d\n", pid, fd);
490 _D("sendto() len - %d %d", len, datalen + 8);
493 if (errno == EPIPE) {
494 _E("pid:%d, fd:%d\n", pid, fd);
512 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
516 struct sockaddr_un aul_addr = { 0, };
518 app_pkt_t *pkt = NULL;
519 int pkt_header_size = offsetof(app_pkt_t, data);
520 int cl = sizeof(struct ucred);
522 sun_size = sizeof(struct sockaddr_un);
524 if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
525 (socklen_t *) &sun_size)) == -1) {
526 if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)
527 _E("accept error: %d", errno);
531 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
532 (socklen_t *) &cl) < 0) {
533 _E("peer information error");
539 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
545 memset(pkt, 0, AUL_SOCK_MAXBUFF);
547 __set_sock_option(*clifd, 1);
550 /* receive single packet from socket */
551 len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
553 _E("recv error: %d", errno);
558 if (len < pkt_header_size) {
559 _E("recv error %d %d", len, pkt->len);
566 if (pkt->len < 0 || pkt->len > (AUL_SOCK_MAXBUFF - pkt_header_size)) {
567 _E("package length error (%d)", pkt->len);
574 while (len < (pkt->len + pkt_header_size)) {
575 ret = recv(*clifd, &pkt->data[len - pkt_header_size],
576 (pkt->len + pkt_header_size) - len, 0);
578 _E("recv error: %d %d %d", errno, len, pkt->len);
585 _D("recv len %d %d", len, pkt->len);
591 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen)
595 app_pkt_t *pkt = NULL;
597 fd = __create_client_sock(pid);
601 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
603 _E("Malloc Failed!");
606 memset(pkt, 0, AUL_SOCK_MAXBUFF);
611 memcpy(pkt->data, kb_data, datalen);
614 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
615 _E("send() failed: %d len: %d", errno, len);
616 if (errno == EPIPE) {
617 _E("pid:%d, fd:%d\n", pid, fd);
626 /* receive single packet from socket */
627 len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
629 if (errno == EAGAIN) {
630 _E("recv timeout \n");
634 } else if (errno == EINTR) {
637 _E("recv error %d %s", errno, strerror(errno));
643 _D("recv result = %d", len);