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/xattr.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)
43 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
44 _D("time out : 5.2 sec");
46 struct timeval tv = { 1, 200 * 1000 }; /* 1.2 sec */
47 _D("time out : 1.2 sec");
50 size = AUL_SOCK_MAXBUFF;
51 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
52 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
54 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
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 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");
84 bzero(&saddr, 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((fsetxattr(fd, "security.SMACK64IPOUT", "@", 2, 0)) < 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");
99 if((fsetxattr(fd, "security.SMACK64IPIN", "*", 2, 0)) < 0) {
100 /* in case of unsupported filesystem on 'socket' */
101 /* or permission error by using 'emulator', bypass*/
102 if((errno != EOPNOTSUPP) && (errno != EPERM)) {
103 _E("labeling to socket(IPIN) error");
109 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
114 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
115 /* Flawfinder: ignore*/
116 _E("failed to change the socket permission");
120 __set_sock_option(fd, 0);
122 if (listen(fd, 10) == -1) {
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");
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("maybe peer not launched or peer daed\n");
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 fcntl(fd, F_SETFL, flags);
213 /* Do whatever we want while the connect is taking place. */
215 goto done; /* connect completed immediately */
218 FD_SET(fd, &readfds);
221 timeout.tv_usec = nsec;
223 if ((ret = select(fd + 1, &readfds, &writefds, NULL,
224 nsec ? &timeout : NULL)) == 0) {
225 close(fd); /* timeout */
230 if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
232 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
233 return (-1); /* Solaris pending error */
235 return (-1); /* select error: sockfd not set*/
238 fcntl(fd, F_SETFL, flags);
248 * @brief Send data (in raw) to the process with 'pid' via socket
250 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 fd = __create_client_sock(pid);
266 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
268 _E("Malloc Failed!");
271 memset(pkt, 0, AUL_SOCK_MAXBUFF);
275 memcpy(pkt->data, kb_data, datalen);
277 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
278 _E("sendto() failed - %d %d", len, datalen + 8);
279 if (errno == EPIPE) {
280 _E("pid:%d, fd:%d\n", pid, fd);
294 len = recv(fd, &res, sizeof(int), 0);
296 if (errno == EAGAIN) {
297 _E("recv timeout \n");
304 _D("recv result = %d (%d)", res, len);
310 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
313 struct sockaddr_un aul_addr = { 0, };
315 app_pkt_t *pkt = NULL;
316 int cl = sizeof(struct ucred);
318 sun_size = sizeof(struct sockaddr_un);
320 if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
321 (socklen_t *) &sun_size)) == -1) {
327 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
328 (socklen_t *) &cl) < 0) {
329 _E("peer information error");
334 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
339 memset(pkt, 0, AUL_SOCK_MAXBUFF);
341 __set_sock_option(*clifd, 1);
344 /* receive single packet from socket */
345 len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
350 if ((len < 8) || (len != (pkt->len + 8))) {
351 _E("recv error %d %d", len, pkt->len);
360 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd)
364 app_pkt_t *pkt = NULL;
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);
380 if ((len = send(fd, pkt, 8, 0)) != 8) {
381 _E("sendto() failed - %d", len);
382 if (errno == EPIPE) {
383 _E("pid:%d, fd:%d\n", pid, fd);
391 len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
393 if (errno == EAGAIN) {
394 _E("recv timeout \n");
403 _D("recv result = %d", len);