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 : #ifdef 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 : } else {
60 : const char* sock_name = basename(sock_path);
61 : if (sock_name == NULL) {
62 : dlt_log(LOG_WARNING, "dlt_daemon_unix_android_get_socket: can't get socket name from its path");
63 : ret = DLT_RETURN_ERROR;
64 : } else {
65 : *sock = android_get_control_socket(sock_name);
66 : if (*sock < 0) {
67 : dlt_log(LOG_WARNING, "dlt_daemon_unix_android_get_socket: can get socket from init");
68 : ret = DLT_RETURN_ERROR;
69 : } else {
70 : if (listen(*sock, 1) == -1) {
71 : dlt_vlog(LOG_WARNING, "unix socket: listen error: %s", strerror(errno));
72 : ret = DLT_RETURN_ERROR;
73 : }
74 : }
75 : }
76 : }
77 :
78 : return ret;
79 : }
80 : #endif
81 :
82 1 : int dlt_daemon_unix_socket_open(int* sock, char* sock_path, int type, int mask)
83 : {
84 : struct sockaddr_un addr;
85 : mode_t old_mask;
86 :
87 1 : if ((sock == NULL) || (sock_path == NULL)) {
88 0 : dlt_log(LOG_ERR, "dlt_daemon_unix_socket_open: arguments invalid");
89 0 : return -1;
90 : }
91 :
92 : #ifdef DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE
93 :
94 : char** names = NULL;
95 : const int num_fds = sd_listen_fds_with_names(0, &names);
96 : bool sd_socket_open = false;
97 : int i;
98 :
99 : if (num_fds <= 0) {
100 : dlt_vlog(LOG_WARNING, "unix socket: no sockets configured via systemd, error: %s\n", strerror(errno));
101 : } else {
102 : for (i = 0; i < num_fds; ++i) {
103 : if (strcmp(sock_path, names[i]) != 0) {
104 : continue;
105 : }
106 :
107 : if (sd_is_socket_unix(i + SD_LISTEN_FDS_START, type, 1, names[i], strlen(names[i])) < 0) {
108 : dlt_vlog(
109 : LOG_WARNING,
110 : "unix socket: socket with matching name is not of correct type or not in listen mode, error: %s\n",
111 : strerror(errno));
112 : continue;
113 : }
114 :
115 : *sock = i + SD_LISTEN_FDS_START;
116 : sd_socket_open = true;
117 : dlt_vlog(LOG_INFO, "unix socket: sock_path %s found systemd socket %s\n", sock_path, names[i]);
118 : break;
119 : }
120 :
121 : /*
122 : * The caller [of sd_listen_fds_with_names] needs to free the array
123 : * itself and each of its elements with libc's free() call after use.
124 : * */
125 : for (i = 0; i < num_fds; ++i) {
126 : free(names[i]);
127 : }
128 : free(names);
129 : }
130 :
131 : if (!sd_socket_open) {
132 : dlt_vlog(LOG_INFO, "unix socket: sock_path %s no systemd socket found\n", sock_path);
133 : #endif
134 :
135 1 : if ((*sock = socket(AF_UNIX, type, 0)) == -1) {
136 0 : dlt_log(LOG_WARNING, "unix socket: socket() error");
137 0 : return -1;
138 : }
139 :
140 : memset(&addr, 0, sizeof(addr));
141 1 : addr.sun_family = AF_UNIX;
142 : memcpy(addr.sun_path, sock_path, sizeof(addr.sun_path));
143 :
144 1 : if (unlink(sock_path) != 0) {
145 1 : dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n", __func__, strerror(errno));
146 : }
147 :
148 : /* set appropriate access permissions */
149 1 : old_mask = umask((mode_t)mask);
150 :
151 1 : if (bind(*sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
152 0 : dlt_vlog(LOG_WARNING, "%s: bind() error (%s)\n", __func__, strerror(errno));
153 0 : return -1;
154 : }
155 :
156 1 : if (listen(*sock, 1) == -1) {
157 0 : dlt_vlog(LOG_WARNING, "%s: listen error (%s)\n", __func__, strerror(errno));
158 0 : return -1;
159 : }
160 :
161 : /* restore permissions */
162 1 : umask((mode_t)old_mask);
163 :
164 : #ifdef DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE
165 : } // end of: if (!sd_socket_open) {
166 : #endif
167 :
168 :
169 1 : return 0;
170 : }
171 :
172 0 : int dlt_daemon_unix_socket_close(int sock)
173 : {
174 0 : int ret = close(sock);
175 :
176 0 : if (ret != 0) {
177 0 : dlt_vlog(LOG_WARNING, "unix socket close failed: %s", strerror(errno));
178 : }
179 :
180 0 : return ret;
181 : }
|