Line data Source code
1 : /*
2 : * SPDX license identifier: MPL-2.0
3 : *
4 : * Copyright (C) 2015, Advanced Driver Information Technology
5 : * Copyright of Advanced Driver Information Technology, Bosch and Denso
6 : *
7 : * This file is part of COVESA Project DLT - Diagnostic Log and Trace.
8 : *
9 : * This Source Code Form is subject to the terms of the
10 : * Mozilla Public License (MPL), v. 2.0.
11 : * If a copy of the MPL was not distributed with this file,
12 : * You can obtain one at http://mozilla.org/MPL/2.0/.
13 : *
14 : * For further information see http://www.covesa.org/.
15 : */
16 :
17 : /*!
18 : * \author
19 : * Christoph Lipka <clipka@jp.adit-jv.com>
20 : *
21 : * \copyright Copyright © 2015 ADIT. \n
22 : * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
23 : *
24 : * \file dlt_daemon_unix_socket.c
25 : */
26 :
27 : #include <stdio.h>
28 : #include <stdlib.h>
29 : #include <string.h>
30 : #include <sys/un.h>
31 : #if defined(ANDROID)
32 : # include <cutils/sockets.h> /* for android_get_control_socket() */
33 : # include <libgen.h> /* for basename() */
34 : #else
35 : # include <sys/socket.h> /* for socket(), connect(), (), and recv() */
36 : #endif
37 : #include <sys/types.h>
38 : #include <sys/stat.h>
39 : #include <syslog.h>
40 : #include <errno.h>
41 : #if DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE
42 : #include <systemd/sd-daemon.h>
43 : #endif
44 :
45 : #include "dlt-daemon.h"
46 : #include "dlt_common.h"
47 : #include "dlt-daemon_cfg.h"
48 : #include "dlt_daemon_socket.h"
49 : #include "dlt_daemon_unix_socket.h"
50 :
51 : #ifdef ANDROID
52 : DltReturnValue dlt_daemon_unix_android_get_socket(int *sock, const char *sock_path)
53 : {
54 : DltReturnValue ret = DLT_RETURN_OK;
55 :
56 : if ((sock == NULL) || (sock_path == NULL)) {
57 : dlt_log(LOG_ERR, "dlt_daemon_unix_android_get_socket: arguments invalid");
58 : ret = DLT_RETURN_WRONG_PARAMETER;
59 : }
60 : else {
61 : const char* sock_name = basename(sock_path);
62 : if (sock_name == NULL) {
63 : dlt_log(LOG_WARNING,
64 : "dlt_daemon_unix_android_get_socket: can't get socket name from its path");
65 : ret = DLT_RETURN_ERROR;
66 : }
67 : else {
68 : *sock = android_get_control_socket(sock_name);
69 : if (*sock < 0) {
70 : dlt_log(LOG_WARNING,
71 : "dlt_daemon_unix_android_get_socket: can get socket from init");
72 : ret = DLT_RETURN_ERROR;
73 : }
74 : else {
75 : if (listen(*sock, 1) == -1) {
76 : dlt_vlog(LOG_WARNING, "unix socket: listen error: %s", strerror(errno));
77 : ret = DLT_RETURN_ERROR;
78 : }
79 : }
80 : }
81 : }
82 :
83 : return ret;
84 : }
85 : #endif
86 :
87 9 : int dlt_daemon_unix_socket_open(int *sock, char *sock_path, int type, int mask)
88 : {
89 : struct sockaddr_un addr;
90 : int old_mask;
91 :
92 9 : if ((sock == NULL) || (sock_path == NULL)) {
93 0 : dlt_log(LOG_ERR, "dlt_daemon_unix_socket_open: arguments invalid");
94 0 : return -1;
95 : }
96 :
97 : #ifdef DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE
98 :
99 : char **names = NULL;
100 : const int num_fds = sd_listen_fds_with_names(0, &names);
101 : bool sd_socket_open = false;
102 : int i;
103 :
104 : if (num_fds <= 0) {
105 : dlt_vlog(LOG_WARNING, "unix socket: no sockets configured via systemd, error: %s\n", strerror(errno));
106 : } else {
107 : for (i = 0; i < num_fds; ++i) {
108 : if (strcmp(sock_path, names[i]) != 0) {
109 : continue;
110 : }
111 :
112 : if (sd_is_socket_unix(i + SD_LISTEN_FDS_START, type, 1, names[i], strlen(names[i])) < 0) {
113 : dlt_vlog(LOG_WARNING,
114 : "unix socket: socket with matching name is not of correct type or not in listen mode, error: %s\n",
115 : strerror(errno));
116 : continue;
117 : }
118 :
119 : *sock = i + SD_LISTEN_FDS_START;
120 : sd_socket_open = true;
121 : dlt_vlog(LOG_INFO, "unix socket: sock_path %s found systemd socket %s\n", sock_path, names[i]);
122 : break;
123 : }
124 :
125 : /*
126 : * The caller [of sd_listen_fds_with_names] needs to free the array
127 : * itself and each of its elements with libc's free() call after use.
128 : * */
129 : for (i = 0; i < num_fds; ++i) {
130 : free(names[i]);
131 : }
132 : free(names);
133 : }
134 :
135 : if (!sd_socket_open) {
136 : dlt_vlog(LOG_INFO, "unix socket: sock_path %s no systemd socket found\n", sock_path);
137 : #endif
138 :
139 9 : if ((*sock = socket(AF_UNIX, type, 0)) == -1) {
140 0 : dlt_log(LOG_WARNING, "unix socket: socket() error");
141 0 : return -1;
142 : }
143 :
144 : memset(&addr, 0, sizeof(addr));
145 9 : addr.sun_family = AF_UNIX;
146 : memcpy(addr.sun_path, sock_path, sizeof(addr.sun_path));
147 :
148 9 : if (unlink(sock_path) != 0) {
149 8 : dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
150 8 : __func__, strerror(errno));
151 : }
152 :
153 : /* set appropriate access permissions */
154 9 : old_mask = umask(mask);
155 :
156 9 : if (bind(*sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
157 0 : dlt_vlog(LOG_WARNING, "%s: bind() error (%s)\n", __func__,
158 0 : strerror(errno));
159 0 : return -1;
160 : }
161 :
162 9 : if (listen(*sock, 1) == -1) {
163 0 : dlt_vlog(LOG_WARNING, "%s: listen error (%s)\n", __func__,
164 0 : strerror(errno));
165 0 : return -1;
166 : }
167 :
168 : /* restore permissions */
169 9 : umask(old_mask);
170 :
171 : #ifdef DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE
172 : } // end of: if (!sd_socket_open) {
173 : #endif
174 :
175 :
176 9 : return 0;
177 : }
178 :
179 0 : int dlt_daemon_unix_socket_close(int sock)
180 : {
181 0 : int ret = close(sock);
182 :
183 0 : if (ret != 0) {
184 0 : dlt_vlog(LOG_WARNING, "unix socket close failed: %s", strerror(errno));
185 : }
186 :
187 0 : return ret;
188 : }
|