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,
40 static inline void __set_sock_option(int fd, int cli)
43 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
45 size = AUL_SOCK_MAXBUFF;
46 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
47 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
49 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
52 int __create_server_sock(int pid)
54 struct sockaddr_un saddr;
55 struct sockaddr_un p_saddr;
59 /* Create basedir for our sockets */
61 (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
64 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
65 /* support above version 2.6.27*/
67 if (errno == EINVAL) {
68 fd = socket(AF_UNIX, SOCK_STREAM, 0);
70 _E("second chance - socket create error: %d", errno);
74 _E("socket error: %d", errno);
79 memset(&saddr, 0, sizeof(saddr));
80 saddr.sun_family = AF_UNIX;
81 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
82 unlink(saddr.sun_path);
84 /* labeling to socket for SMACK */
85 if(getuid() == 0) { // this is meaningful iff current user is ROOT
86 if(smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) {
87 /* in case of unsupported filesystem on 'socket' */
88 /* or permission error by using 'emulator', bypass*/
89 if((errno != EOPNOTSUPP) && (errno != EPERM)) {
90 _E("labeling to socket(IPOUT) error");
95 if(smack_fsetlabel(fd, "*", SMACK_LABEL_IPIN) != 0) {
96 /* in case of unsupported filesystem on 'socket' */
97 /* or permission error by using 'emulator', bypass*/
98 if((errno != EOPNOTSUPP) && (errno != EPERM)) {
99 _E("labeling to socket(IPIN) error");
106 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
107 _E("bind error: %d", errno);
112 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
113 /* Flawfinder: ignore*/
114 _E("failed to change the socket permission");
119 __set_sock_option(fd, 0);
121 if (listen(fd, 128) == -1) {
122 _E("listen error: %d", errno);
127 /* support app launched by shell script */
128 if (pid != LAUNCHPAD_PID) {
132 snprintf(p_saddr.sun_path, UNIX_PATH_MAX, "%s/%d",
133 AUL_SOCK_PREFIX, pgid);
134 if (link(saddr.sun_path, p_saddr.sun_path) < 0) {
136 _D("pg path - already exists");
138 _E("pg path - unknown create error");
146 int __create_client_sock(int pid)
149 struct sockaddr_un saddr = { 0, };
153 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
154 /* support above version 2.6.27*/
156 if (errno == EINVAL) {
157 fd = socket(AF_UNIX, SOCK_STREAM, 0);
159 _E("second chance - socket create error: %d", errno);
163 _E("socket error: %d", errno);
168 saddr.sun_family = AF_UNIX;
169 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
171 ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
174 _E("cannot connect the client socket: %d", errno);
176 usleep((1+2*(2-retry))*100 * 1000);
186 __set_sock_option(fd, 1);
191 static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,
200 struct timeval timeout;
202 flags = fcntl(fd, F_GETFL, 0);
203 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
206 if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {
207 if (errno != EAGAIN && errno != EINPROGRESS) {
208 _E("connect error: %d", errno);
209 fcntl(fd, F_SETFL, flags);
214 /* Do whatever we want while the connect is taking place. */
216 goto done; /* connect completed immediately */
219 FD_SET(fd, &readfds);
222 timeout.tv_usec = nsec;
224 if ((ret = select(fd + 1, &readfds, &writefds, NULL,
225 nsec ? &timeout : NULL)) == 0) {
226 _E("select timeout");
227 close(fd); /* timeout */
232 if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
234 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
235 return (-1); /* Solaris pending error */
237 return (-1); /* select error: sockfd not set*/
240 (void) fcntl(fd, F_SETFL, flags);
250 * @brief Send data (in raw) to the process with 'pid' via socket
252 int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen)
258 app_pkt_t *pkt = NULL;
260 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
261 _E("keybundle error\n");
265 _D("pid(%d) : cmd(%d)", pid, cmd);
267 fd = __create_client_sock(pid);
269 _E("cannot create a client socket: %d", fd);
273 /* aul_app_is_running timeout : 25sec */
274 if(cmd == APP_IS_RUNNING) {
275 struct timeval tv = { 25, 0 };
276 ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
278 _E("setsockopt error");
282 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
284 _E("Malloc Failed!");
287 memset(pkt, 0, AUL_SOCK_MAXBUFF);
291 memcpy(pkt->data, kb_data, datalen);
293 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
294 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
296 while (len != datalen + 8) {
297 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
299 _E("second send() failed - %d %d (errno: %d)", ret, datalen + 8, errno);
300 if (errno == EPIPE) {
301 _E("pid:%d, fd:%d\n", pid, fd);
311 _D("send() len - %d %d", len, datalen + 8);
314 if (errno == EPIPE) {
315 _E("pid:%d, fd:%d\n", pid, fd);
323 _E("send() failed: %d %s", errno, strerror(errno));
333 len = recv(fd, &res, sizeof(int), 0);
335 if (errno == EAGAIN) {
336 _E("recv timeout : cmd(%d) %s", cmd, strerror(errno));
338 } else if (errno == EINTR) {
339 _D("recv : %s", strerror(errno));
342 _E("recv error : %s", strerror(errno));
351 int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen)
357 app_pkt_t *pkt = NULL;
359 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
360 _E("keybundle error\n");
364 _D("pid(%d) : cmd(%d)", pid, cmd);
366 fd = __create_client_sock(pid);
370 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
372 _E("Malloc Failed!");
375 memset(pkt, 0, AUL_SOCK_MAXBUFF);
379 memcpy(pkt->data, kb_data, datalen);
381 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
382 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
384 while (len != datalen + 8) {
385 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
387 _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
388 if (errno == EPIPE) {
389 _E("pid:%d, fd:%d\n", pid, fd);
399 _D("sendto() len - %d %d", len, datalen + 8);
402 if (errno == EPIPE) {
403 _E("pid:%d, fd:%d\n", pid, fd);
423 int __app_send_raw_with_delay_reply(int pid, int cmd, unsigned char *kb_data, int datalen)
428 app_pkt_t *pkt = NULL;
430 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
431 _E("keybundle error\n");
435 _D("pid(%d) : cmd(%d)", pid, cmd);
437 fd = __create_client_sock(pid);
441 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
443 _E("Malloc Failed!");
446 memset(pkt, 0, AUL_SOCK_MAXBUFF);
450 memcpy(pkt->data, kb_data, datalen);
452 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
453 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
455 while (len != datalen + 8) {
456 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
458 _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
459 if (errno == EPIPE) {
460 _E("pid:%d, fd:%d\n", pid, fd);
470 _D("sendto() len - %d %d", len, datalen + 8);
473 if (errno == EPIPE) {
474 _E("pid:%d, fd:%d\n", pid, fd);
492 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
496 struct sockaddr_un aul_addr = { 0, };
498 app_pkt_t *pkt = NULL;
499 int pkt_header_size = offsetof(app_pkt_t, data);
500 int cl = sizeof(struct ucred);
502 sun_size = sizeof(struct sockaddr_un);
504 if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
505 (socklen_t *) &sun_size)) == -1) {
507 _E("accept error: %d", errno);
511 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
512 (socklen_t *) &cl) < 0) {
513 _E("peer information error");
518 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
523 memset(pkt, 0, AUL_SOCK_MAXBUFF);
525 __set_sock_option(*clifd, 1);
528 /* receive single packet from socket */
529 len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
531 _E("recv error: %d", errno);
536 if (len < pkt_header_size) {
537 _E("recv error %d %d", len, pkt->len);
543 if (pkt->len < 0 || pkt->len > (AUL_SOCK_MAXBUFF - pkt_header_size)) {
544 _E("package length error (%d)", pkt->len);
550 while (len < (pkt->len + pkt_header_size)) {
551 ret = recv(*clifd, &pkt->data[len - pkt_header_size],
552 (pkt->len + pkt_header_size) - len, 0);
553 if (ret <= 0) { /* ret may be 0 when the peer has performed an orderly shutdown */
554 _E("recv error: %d %d %d", errno, len, pkt->len);
560 _D("recv len %d %d", len, pkt->len);
566 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen)
570 app_pkt_t *pkt = NULL;
572 fd = __create_client_sock(pid);
576 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
578 _E("Malloc Failed!");
581 memset(pkt, 0, AUL_SOCK_MAXBUFF);
586 memcpy(pkt->data, kb_data, datalen);
589 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
590 _E("send() failed: %d len: %d", errno, len);
591 if (errno == EPIPE) {
592 _E("pid:%d, fd:%d\n", pid, fd);
601 /* receive single packet from socket */
602 len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
604 if (errno == EAGAIN) {
605 _E("recv timeout \n");
609 } else if (errno == EINTR) {
612 _E("recv error %d %s", errno, strerror(errno));
618 _D("recv result = %d", len);