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)
44 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
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));
50 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
51 flag = fcntl(fd, F_GETFD);
53 fcntl(fd, F_SETFD, flag);
57 int __create_server_sock(int pid)
59 struct sockaddr_un saddr;
60 struct sockaddr_un p_saddr;
64 /* Create basedir for our sockets */
66 (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
69 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
70 /* support above version 2.6.27*/
72 if (errno == EINVAL) {
73 fd = socket(AF_UNIX, SOCK_STREAM, 0);
75 _E("second chance - socket create error: %d", errno);
79 _E("socket error: %d", errno);
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);
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");
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");
111 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
112 _E("bind error: %d", errno);
117 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
118 /* Flawfinder: ignore*/
119 _E("failed to change the socket permission");
124 __set_sock_option(fd, 0);
126 if (listen(fd, 128) == -1) {
127 _E("listen error: %d", errno);
132 /* support app launched by shell script */
133 if (pid != LAUNCHPAD_PID) {
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) {
141 _D("pg path - already exists");
143 _E("pg path - unknown create error");
151 int __create_client_sock(int pid)
154 struct sockaddr_un saddr = { 0, };
158 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
159 /* support above version 2.6.27*/
161 if (errno == EINVAL) {
162 fd = socket(AF_UNIX, SOCK_STREAM, 0);
164 _E("second chance - socket create error: %d", errno);
168 _E("socket error: %d", errno);
173 saddr.sun_family = AF_UNIX;
174 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
176 ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
179 _E("cannot connect the client socket: %d", errno);
181 usleep((1+2*(2-retry))*100 * 1000);
191 __set_sock_option(fd, 1);
196 static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,
205 struct timeval timeout;
207 flags = fcntl(fd, F_GETFL, 0);
208 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
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);
219 /* Do whatever we want while the connect is taking place. */
221 goto done; /* connect completed immediately */
224 FD_SET(fd, &readfds);
227 timeout.tv_usec = nsec;
229 if ((ret = select(fd + 1, &readfds, &writefds, NULL,
230 nsec ? &timeout : NULL)) == 0) {
231 _E("select timeout");
232 close(fd); /* timeout */
237 if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
239 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
240 return (-1); /* Solaris pending error */
242 return (-1); /* select error: sockfd not set*/
245 (void) fcntl(fd, F_SETFL, flags);
255 * @brief Send data (in raw) to the process with 'pid' via socket
257 int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen)
263 app_pkt_t *pkt = NULL;
265 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
266 _E("keybundle error\n");
270 _D("pid(%d) : cmd(%d)", pid, cmd);
272 fd = __create_client_sock(pid);
274 _E("cannot create a client socket: %d", fd);
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));
283 _E("setsockopt error");
287 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
289 _E("Malloc Failed!");
293 memset(pkt, 0, AUL_SOCK_MAXBUFF);
297 memcpy(pkt->data, kb_data, datalen);
299 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
300 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
302 while (len != datalen + 8) {
303 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 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);
317 _D("send() len - %d %d", len, datalen + 8);
320 if (errno == EPIPE) {
321 _E("pid:%d, fd:%d\n", pid, fd);
329 _E("send() failed: %d %s", errno, strerror(errno));
339 len = recv(fd, &res, sizeof(int), 0);
341 if (errno == EAGAIN) {
342 _E("recv timeout : cmd(%d) %s", cmd, strerror(errno));
344 } else if (errno == EINTR) {
345 _D("recv : %s", strerror(errno));
348 _E("recv error : %s", strerror(errno));
357 int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen)
363 app_pkt_t *pkt = NULL;
365 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
366 _E("keybundle error\n");
370 _D("pid(%d) : cmd(%d)", pid, cmd);
372 fd = __create_client_sock(pid);
376 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
378 _E("Malloc Failed!");
382 memset(pkt, 0, AUL_SOCK_MAXBUFF);
386 memcpy(pkt->data, kb_data, datalen);
388 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
389 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
391 while (len != datalen + 8) {
392 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 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);
406 _D("sendto() len - %d %d", len, datalen + 8);
409 if (errno == EPIPE) {
410 _E("pid:%d, fd:%d\n", pid, fd);
430 int __app_send_raw_with_delay_reply(int pid, int cmd, unsigned char *kb_data, int datalen)
435 app_pkt_t *pkt = NULL;
437 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
438 _E("keybundle error\n");
442 _D("pid(%d) : cmd(%d)", pid, cmd);
444 fd = __create_client_sock(pid);
448 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
450 _E("Malloc Failed!");
454 memset(pkt, 0, AUL_SOCK_MAXBUFF);
458 memcpy(pkt->data, kb_data, datalen);
460 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
461 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
463 while (len != datalen + 8) {
464 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 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);
478 _D("sendto() len - %d %d", len, datalen + 8);
481 if (errno == EPIPE) {
482 _E("pid:%d, fd:%d\n", pid, fd);
500 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
504 struct sockaddr_un aul_addr = { 0, };
506 app_pkt_t *pkt = NULL;
507 int pkt_header_size = offsetof(app_pkt_t, data);
508 int cl = sizeof(struct ucred);
510 sun_size = sizeof(struct sockaddr_un);
512 if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
513 (socklen_t *) &sun_size)) == -1) {
515 _E("accept error: %d", errno);
519 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
520 (socklen_t *) &cl) < 0) {
521 _E("peer information error");
526 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
531 memset(pkt, 0, AUL_SOCK_MAXBUFF);
533 __set_sock_option(*clifd, 1);
536 /* receive single packet from socket */
537 len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
539 _E("recv error: %d", errno);
544 if (len < pkt_header_size) {
545 _E("recv error %d %d", len, pkt->len);
551 if (pkt->len < 0 || pkt->len > (AUL_SOCK_MAXBUFF - pkt_header_size)) {
552 _E("package length error (%d)", pkt->len);
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);
568 _D("recv len %d %d", len, pkt->len);
574 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen)
578 app_pkt_t *pkt = NULL;
580 fd = __create_client_sock(pid);
584 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
586 _E("Malloc Failed!");
590 memset(pkt, 0, AUL_SOCK_MAXBUFF);
595 memcpy(pkt->data, kb_data, datalen);
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);
610 /* receive single packet from socket */
611 len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
613 if (errno == EAGAIN) {
614 _E("recv timeout \n");
618 } else if (errno == EINTR) {
621 _E("recv error %d %s", errno, strerror(errno));
627 _D("recv result = %d", len);