2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <sys/types.h>
22 #include <sys/smack.h>
29 #include "simple_util.h"
31 static int __connect_client_sock(int sockfd,
32 const struct sockaddr *saptr,
36 static inline int __set_sock_option(int fd, int cli)
39 struct timeval tv = { 3, 200 * 1000 }; /* 3.2 sec */
41 size = AUL_SOCK_MAXBUFF;
42 if (0 != setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) ||
43 0 != setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)))
47 if (cli && 0 != setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) {
53 int __create_server_sock(int pid)
55 struct sockaddr_un saddr;
56 struct sockaddr_un p_saddr;
60 /* Create basedir for our sockets */
62 (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
65 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
66 /* support above version 2.6.27*/
68 if (errno == EINVAL) {
69 fd = socket(AF_UNIX, SOCK_STREAM, 0);
71 _E("second chance - socket create error");
80 memset(&saddr, 0, sizeof(saddr));
81 saddr.sun_family = AF_UNIX;
82 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
83 unlink(saddr.sun_path);
85 /* labeling to socket for SMACK */
86 if (getuid() == 0) { // this is meaningful iff current user is ROOT
87 if (smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) {
88 /* in case of unsupported filesystem on 'socket' */
89 /* or permission error by using 'emulator', bypass*/
90 if ((errno != EOPNOTSUPP) && (errno != EPERM)) {
91 _E("labeling to socket(IPOUT) error");
96 if (smack_fsetlabel(fd, "*", SMACK_LABEL_IPIN) != 0) {
97 /* in case of unsupported filesystem on 'socket' */
98 /* or permission error by using 'emulator', bypass*/
99 if ((errno != EOPNOTSUPP) && (errno != EPERM)) {
100 _E("labeling to socket(IPIN) error");
107 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
113 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
114 /* Flawfinder: ignore*/
115 _E("failed to change the socket permission");
120 if (0 != __set_sock_option(fd, 0)) {
125 if (listen(fd, 10) == -1) {
131 /* support app launched by shell script */
132 if (pid != WRT_LAUNCHPAD_PID) {
136 snprintf(p_saddr.sun_path, UNIX_PATH_MAX, "%s/%d",
137 AUL_SOCK_PREFIX, pgid);
138 if (link(saddr.sun_path, p_saddr.sun_path) < 0) {
139 if (errno == EEXIST) {
140 _D("pg path - already exists");
143 _E("pg path - unknown create error");
152 int __create_client_sock(int pid)
155 struct sockaddr_un saddr;
159 memset(&saddr, 0x00, sizeof(struct sockaddr_un));
161 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
162 /* support above version 2.6.27*/
164 if (errno == EINVAL) {
165 fd = socket(AF_UNIX, SOCK_STREAM, 0);
167 _E("second chance - socket create error");
176 saddr.sun_family = AF_UNIX;
177 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
179 while ((ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
181 _E("maybe peer not launched or peer daed\n");
183 struct timespec duration = { 0, 100 * 1000 * 1000 };
184 nanosleep(&duration, NULL); /* 100ms sleep*/
195 if (0 != __set_sock_option(fd, 1)) {
203 static int __connect_client_sock(int fd,
204 const struct sockaddr *saptr,
214 struct timeval timeout;
216 flags = fcntl(fd, F_GETFL, 0);
217 if (0 != fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
222 if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {
223 if (errno != EAGAIN && errno != EINPROGRESS) {
224 (void) fcntl(fd, F_SETFL, flags);
229 /* Do whatever we want while the connect is taking place. */
231 goto done; /* connect completed immediately */
234 FD_SET(fd, &readfds);
237 timeout.tv_usec = nsec;
239 if ((ret = select(fd + 1, &readfds, &writefds, NULL,
240 nsec ? &timeout : NULL)) == 0) {
241 close(fd); /* timeout */
246 if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
248 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
249 return (-1); /* Solaris pending error */
253 return (-1); /* select error: sockfd not set*/
257 (void) fcntl(fd, F_SETFL, flags);
267 * @brief Send data (in raw) to the process with 'pid' via socket
269 int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen)
274 app_pkt_t *pkt = NULL;
276 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
277 _E("keybundle error\n");
281 fd = __create_client_sock(pid);
286 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
288 _E("Malloc Failed!");
291 memset(pkt, 0, AUL_SOCK_MAXBUFF);
295 memcpy(pkt->data, kb_data, datalen);
297 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
298 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
299 if (errno == EPIPE) {
300 _E("pid:%d, fd:%d\n", pid, fd);
314 len = recv(fd, &res, sizeof(int), 0);
316 if (errno == EAGAIN) {
317 _E("recv timeout \n");
329 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
332 struct sockaddr_un aul_addr;
334 app_pkt_t *pkt = NULL;
335 int cl = sizeof(struct ucred);
337 memset(&aul_addr, 0x00, sizeof(struct sockaddr_un));
338 sun_size = sizeof(struct sockaddr_un);
340 if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
341 (socklen_t *) &sun_size)) == -1)
343 if (errno != EINTR) {
349 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
350 (socklen_t *) &cl) < 0)
352 _E("peer information error");
357 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
362 memset(pkt, 0, AUL_SOCK_MAXBUFF);
364 if (0 != __set_sock_option(*clifd, 1)) {
371 /* receive single packet from socket */
372 len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
374 if (errno == EINTR) {
379 if ((len < 8) || (len != (pkt->len + 8))) {
380 _E("recv error %d %d", len, pkt->len);
389 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd)
393 app_pkt_t *pkt = NULL;
395 fd = __create_client_sock(pid);
400 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
402 _E("Malloc Failed!");
405 memset(pkt, 0, AUL_SOCK_MAXBUFF);
410 if ((len = send(fd, pkt, 8, 0)) != 8) {
411 _E("sendto() failed - %d", len);
412 if (errno == EPIPE) {
413 _E("pid:%d, fd:%d\n", pid, fd);
422 /* receive single packet from socket */
423 len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
425 if (errno == EAGAIN) {
426 _E("recv timeout \n");
429 } else if (errno == EINTR) {
432 _E("recv error %s\n", strerror(errno));
437 _D("recv result = %d", len);