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>
28 #include <sys/smack.h>
33 #include "simple_util.h"
35 static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen,
39 static inline void __set_sock_option(int fd, int cli)
42 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
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));
48 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
51 int __create_server_sock(int pid)
53 struct sockaddr_un saddr;
54 struct sockaddr_un p_saddr;
58 /* Create basedir for our sockets */
60 (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
63 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
64 /* support above version 2.6.27*/
66 if (errno == EINVAL) {
67 fd = socket(AF_UNIX, SOCK_STREAM, 0);
69 _E("second chance - socket create error");
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);
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");
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");
105 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
111 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
112 /* Flawfinder: ignore*/
113 _E("failed to change the socket permission");
118 __set_sock_option(fd, 0);
120 if (listen(fd, 128) == -1) {
126 /* support app launched by shell script */
127 if (pid != LAUNCHPAD_PID) {
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) {
135 _D("pg path - already exists");
137 _E("pg path - unknown create error");
145 int __create_client_sock(int pid)
148 struct sockaddr_un saddr = { 0, };
152 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
153 /* support above version 2.6.27*/
155 if (errno == EINVAL) {
156 fd = socket(AF_UNIX, SOCK_STREAM, 0);
158 _E("second chance - socket create error");
167 saddr.sun_family = AF_UNIX;
168 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
170 ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
173 _E("maybe peer not launched or peer daed\n");
175 usleep((1+2*(2-retry))*100 * 1000);
185 __set_sock_option(fd, 1);
190 static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,
199 struct timeval timeout;
201 flags = fcntl(fd, F_GETFL, 0);
202 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
205 if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {
206 if (errno != EAGAIN && errno != EINPROGRESS) {
207 fcntl(fd, F_SETFL, flags);
212 /* Do whatever we want while the connect is taking place. */
214 goto done; /* connect completed immediately */
217 FD_SET(fd, &readfds);
220 timeout.tv_usec = nsec;
222 if ((ret = select(fd + 1, &readfds, &writefds, NULL,
223 nsec ? &timeout : NULL)) == 0) {
224 close(fd); /* timeout */
229 if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
231 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
232 return (-1); /* Solaris pending error */
234 return (-1); /* select error: sockfd not set*/
237 (void) fcntl(fd, F_SETFL, flags);
247 * @brief Send data (in raw) to the process with 'pid' via socket
249 int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen)
255 app_pkt_t *pkt = NULL;
257 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
258 _E("keybundle error\n");
262 _D("pid(%d) : cmd(%d)", pid, cmd);
264 fd = __create_client_sock(pid);
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));
273 _E("setsockopt error");
277 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
279 _E("Malloc Failed!");
282 memset(pkt, 0, AUL_SOCK_MAXBUFF);
286 memcpy(pkt->data, kb_data, datalen);
288 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
289 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
291 while (len != datalen + 8) {
292 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 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);
306 _D("sendto() len - %d %d", len, datalen + 8);
309 if (errno == EPIPE) {
310 _E("pid:%d, fd:%d\n", pid, fd);
326 len = recv(fd, &res, sizeof(int), 0);
328 if (errno == EAGAIN) {
329 _E("recv timeout : cmd(%d) %s", cmd, strerror(errno));
331 } else if (errno == EINTR) {
332 _D("recv : %s", strerror(errno));
335 _E("recv error : %s", strerror(errno));
344 int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen)
350 app_pkt_t *pkt = NULL;
352 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
353 _E("keybundle error\n");
357 _D("pid(%d) : cmd(%d)", pid, cmd);
359 fd = __create_client_sock(pid);
363 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
365 _E("Malloc Failed!");
368 memset(pkt, 0, AUL_SOCK_MAXBUFF);
372 memcpy(pkt->data, kb_data, datalen);
374 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
375 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
377 while (len != datalen + 8) {
378 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 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);
392 _D("sendto() len - %d %d", len, datalen + 8);
395 if (errno == EPIPE) {
396 _E("pid:%d, fd:%d\n", pid, fd);
416 int __app_send_raw_with_delay_reply(int pid, int cmd, unsigned char *kb_data, int datalen)
421 app_pkt_t *pkt = NULL;
423 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
424 _E("keybundle error\n");
428 _D("pid(%d) : cmd(%d)", pid, cmd);
430 fd = __create_client_sock(pid);
434 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
436 _E("Malloc Failed!");
439 memset(pkt, 0, AUL_SOCK_MAXBUFF);
443 memcpy(pkt->data, kb_data, datalen);
445 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
446 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
448 while (len != datalen + 8) {
449 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 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);
463 _D("sendto() len - %d %d", len, datalen + 8);
466 if (errno == EPIPE) {
467 _E("pid:%d, fd:%d\n", pid, fd);
485 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
489 struct sockaddr_un aul_addr = { 0, };
491 app_pkt_t *pkt = NULL;
492 int cl = sizeof(struct ucred);
494 sun_size = sizeof(struct sockaddr_un);
496 if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
497 (socklen_t *) &sun_size)) == -1) {
503 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
504 (socklen_t *) &cl) < 0) {
505 _E("peer information error");
510 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
515 memset(pkt, 0, AUL_SOCK_MAXBUFF);
517 __set_sock_option(*clifd, 1);
520 /* receive single packet from socket */
521 len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
527 _E("recv error %d %d", len, pkt->len);
533 while( len != (pkt->len + 8) ) {
534 ret = recv(*clifd, &pkt->data[len-8], AUL_SOCK_MAXBUFF, 0);
536 _E("recv error %d %d", len, pkt->len);
542 _D("recv len %d %d", len, pkt->len);
548 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen)
552 app_pkt_t *pkt = NULL;
554 fd = __create_client_sock(pid);
558 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
560 _E("Malloc Failed!");
563 memset(pkt, 0, AUL_SOCK_MAXBUFF);
568 memcpy(pkt->data, kb_data, datalen);
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);
583 /* receive single packet from socket */
584 len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
586 if (errno == EAGAIN) {
587 _E("recv timeout \n");
591 } else if (errno == EINTR) {
594 _E("recv error %s\n", strerror(errno));
600 _D("recv result = %d", len);