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>
26 #include <systemd/sd-daemon.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;
62 memset(&saddr, 0, sizeof(saddr));
63 saddr.sun_family = AF_UNIX;
64 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
66 listen_fds = sd_listen_fds(0);
68 _E("invalid systemd environment");
70 } else if (listen_fds > 0) {
71 for (i = 0; i < listen_fds; i++) {
72 fd = SD_LISTEN_FDS_START + i;
73 if (sd_is_socket_unix(fd, SOCK_STREAM, 1, saddr.sun_path, 0))
76 _E("socket not found: %s", saddr.sun_path);
80 /* Create basedir for our sockets */
82 (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
85 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
86 /* support above version 2.6.27*/
88 if (errno == EINVAL) {
89 fd = socket(AF_UNIX, SOCK_STREAM, 0);
91 _E("second chance - socket create error");
100 unlink(saddr.sun_path);
102 /* labeling to socket for SMACK */
103 if (getuid() == 0) { // this is meaningful iff current user is ROOT
104 if (smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) {
105 /* in case of unsupported filesystem on 'socket' */
106 /* or permission error by using 'emulator', bypass*/
107 if ((errno != EOPNOTSUPP) && (errno != EPERM)) {
108 _E("labeling to socket(IPOUT) error");
113 if (smack_fsetlabel(fd, "*", SMACK_LABEL_IPIN) != 0) {
114 /* in case of unsupported filesystem on 'socket' */
115 /* or permission error by using 'emulator', bypass*/
116 if ((errno != EOPNOTSUPP) && (errno != EPERM)) {
117 _E("labeling to socket(IPIN) error");
124 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
130 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
131 /* Flawfinder: ignore*/
132 _E("failed to change the socket permission");
137 if (0 != __set_sock_option(fd, 0)) {
142 if (listen(fd, 10) == -1) {
148 /* support app launched by shell script */
149 if (pid != WRT_LAUNCHPAD_PID) {
153 snprintf(p_saddr.sun_path, UNIX_PATH_MAX, "%s/%d",
154 AUL_SOCK_PREFIX, pgid);
155 if (link(saddr.sun_path, p_saddr.sun_path) < 0) {
156 if (errno == EEXIST) {
157 _D("pg path - already exists");
160 _E("pg path - unknown create error");
169 int __create_client_sock(int pid)
172 struct sockaddr_un saddr;
176 memset(&saddr, 0x00, sizeof(struct sockaddr_un));
178 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
179 /* support above version 2.6.27*/
181 if (errno == EINVAL) {
182 fd = socket(AF_UNIX, SOCK_STREAM, 0);
184 _E("second chance - socket create error");
193 saddr.sun_family = AF_UNIX;
194 snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
196 while ((ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
198 _E("maybe peer not launched or peer daed\n");
200 struct timespec duration = { 0, 100 * 1000 * 1000 };
201 nanosleep(&duration, NULL); /* 100ms sleep*/
212 if (0 != __set_sock_option(fd, 1)) {
220 static int __connect_client_sock(int fd,
221 const struct sockaddr *saptr,
231 struct timeval timeout;
233 flags = fcntl(fd, F_GETFL, 0);
234 if (0 != fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
239 if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {
240 if (errno != EAGAIN && errno != EINPROGRESS) {
241 (void) fcntl(fd, F_SETFL, flags);
246 /* Do whatever we want while the connect is taking place. */
248 goto done; /* connect completed immediately */
251 FD_SET(fd, &readfds);
254 timeout.tv_usec = nsec;
256 if ((ret = select(fd + 1, &readfds, &writefds, NULL,
257 nsec ? &timeout : NULL)) == 0) {
258 close(fd); /* timeout */
263 if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
265 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
266 return (-1); /* Solaris pending error */
270 return (-1); /* select error: sockfd not set*/
274 (void) fcntl(fd, F_SETFL, flags);
284 * @brief Send data (in raw) to the process with 'pid' via socket
286 int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen)
291 app_pkt_t *pkt = NULL;
293 if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
294 _E("keybundle error\n");
298 fd = __create_client_sock(pid);
303 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
305 _E("Malloc Failed!");
308 memset(pkt, 0, AUL_SOCK_MAXBUFF);
312 memcpy(pkt->data, kb_data, datalen);
314 if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
315 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
316 if (errno == EPIPE) {
317 _E("pid:%d, fd:%d\n", pid, fd);
331 len = recv(fd, &res, sizeof(int), 0);
333 if (errno == EAGAIN) {
334 _E("recv timeout \n");
346 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
349 struct sockaddr_un aul_addr;
351 app_pkt_t *pkt = NULL;
352 int cl = sizeof(struct ucred);
354 memset(&aul_addr, 0x00, sizeof(struct sockaddr_un));
355 sun_size = sizeof(struct sockaddr_un);
357 if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
358 (socklen_t *) &sun_size)) == -1)
360 if (errno != EINTR) {
366 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
367 (socklen_t *) &cl) < 0)
369 _E("peer information error");
374 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
379 memset(pkt, 0, AUL_SOCK_MAXBUFF);
381 if (0 != __set_sock_option(*clifd, 1)) {
388 /* receive single packet from socket */
389 len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
391 if (errno == EINTR) {
396 if ((len < 8) || (len != (pkt->len + 8))) {
397 _E("recv error %d %d", len, pkt->len);
406 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd)
410 app_pkt_t *pkt = NULL;
412 fd = __create_client_sock(pid);
417 pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
419 _E("Malloc Failed!");
422 memset(pkt, 0, AUL_SOCK_MAXBUFF);
427 if ((len = send(fd, pkt, 8, 0)) != 8) {
428 _E("sendto() failed - %d", len);
429 if (errno == EPIPE) {
430 _E("pid:%d, fd:%d\n", pid, fd);
439 /* receive single packet from socket */
440 len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
442 if (errno == EAGAIN) {
443 _E("recv timeout \n");
446 } else if (errno == EINTR) {
449 _E("recv error %s\n", strerror(errno));
454 _D("recv result = %d", len);