D-Bus 1.4.0
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-server-unix.c Server implementation for Unix network protocols. 00003 * 00004 * Copyright (C) 2002, 2003, 2004 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-internals.h" 00026 #include "dbus-server-unix.h" 00027 #include "dbus-server-socket.h" 00028 #include "dbus-transport-unix.h" 00029 #include "dbus-connection-internal.h" 00030 #include "dbus-sysdeps-unix.h" 00031 #include "dbus-string.h" 00032 00052 DBusServerListenResult 00053 _dbus_server_listen_platform_specific (DBusAddressEntry *entry, 00054 DBusServer **server_p, 00055 DBusError *error) 00056 { 00057 const char *method; 00058 00059 *server_p = NULL; 00060 00061 method = dbus_address_entry_get_method (entry); 00062 00063 if (strcmp (method, "unix") == 0) 00064 { 00065 const char *path = dbus_address_entry_get_value (entry, "path"); 00066 const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); 00067 const char *abstract = dbus_address_entry_get_value (entry, "abstract"); 00068 00069 if (path == NULL && tmpdir == NULL && abstract == NULL) 00070 { 00071 _dbus_set_bad_address(error, "unix", 00072 "path or tmpdir or abstract", 00073 NULL); 00074 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00075 } 00076 00077 if ((path && tmpdir) || 00078 (path && abstract) || 00079 (tmpdir && abstract)) 00080 { 00081 _dbus_set_bad_address(error, NULL, NULL, 00082 "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time"); 00083 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00084 } 00085 00086 if (tmpdir != NULL) 00087 { 00088 DBusString full_path; 00089 DBusString filename; 00090 00091 if (!_dbus_string_init (&full_path)) 00092 { 00093 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00094 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00095 } 00096 00097 if (!_dbus_string_init (&filename)) 00098 { 00099 _dbus_string_free (&full_path); 00100 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00101 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00102 } 00103 00104 if (!_dbus_string_append (&filename, 00105 "dbus-") || 00106 !_dbus_generate_random_ascii (&filename, 10) || 00107 !_dbus_string_append (&full_path, tmpdir) || 00108 !_dbus_concat_dir_and_file (&full_path, &filename)) 00109 { 00110 _dbus_string_free (&full_path); 00111 _dbus_string_free (&filename); 00112 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00113 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00114 } 00115 00116 /* Always use abstract namespace if possible with tmpdir */ 00117 00118 *server_p = 00119 _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path), 00120 #ifdef HAVE_ABSTRACT_SOCKETS 00121 TRUE, 00122 #else 00123 FALSE, 00124 #endif 00125 error); 00126 00127 _dbus_string_free (&full_path); 00128 _dbus_string_free (&filename); 00129 } 00130 else 00131 { 00132 if (path) 00133 *server_p = _dbus_server_new_for_domain_socket (path, FALSE, error); 00134 else 00135 *server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error); 00136 } 00137 00138 if (*server_p != NULL) 00139 { 00140 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00141 return DBUS_SERVER_LISTEN_OK; 00142 } 00143 else 00144 { 00145 _DBUS_ASSERT_ERROR_IS_SET(error); 00146 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00147 } 00148 } 00149 else if (strcmp (method, "systemd") == 0) 00150 { 00151 int n, *fds; 00152 DBusString address; 00153 00154 n = _dbus_listen_systemd_sockets (&fds, error); 00155 if (n < 0) 00156 { 00157 _DBUS_ASSERT_ERROR_IS_SET (error); 00158 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00159 } 00160 00161 _dbus_string_init_const (&address, "systemd:"); 00162 00163 *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL); 00164 if (*server_p == NULL) 00165 { 00166 int i; 00167 00168 for (i = 0; i < n; i++) 00169 { 00170 _dbus_close_socket (fds[i], NULL); 00171 } 00172 dbus_free (fds); 00173 00174 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00175 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00176 } 00177 00178 dbus_free (fds); 00179 00180 return DBUS_SERVER_LISTEN_OK; 00181 } 00182 else 00183 { 00184 /* If we don't handle the method, we return NULL with the 00185 * error unset 00186 */ 00187 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00188 return DBUS_SERVER_LISTEN_NOT_HANDLED; 00189 } 00190 } 00191 00200 DBusServer* 00201 _dbus_server_new_for_domain_socket (const char *path, 00202 dbus_bool_t abstract, 00203 DBusError *error) 00204 { 00205 DBusServer *server; 00206 int listen_fd; 00207 DBusString address; 00208 char *path_copy; 00209 DBusString path_str; 00210 00211 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00212 00213 if (!_dbus_string_init (&address)) 00214 { 00215 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00216 return NULL; 00217 } 00218 00219 _dbus_string_init_const (&path_str, path); 00220 if ((abstract && 00221 !_dbus_string_append (&address, "unix:abstract=")) || 00222 (!abstract && 00223 !_dbus_string_append (&address, "unix:path=")) || 00224 !_dbus_address_append_escaped (&address, &path_str)) 00225 { 00226 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00227 goto failed_0; 00228 } 00229 00230 path_copy = _dbus_strdup (path); 00231 if (path_copy == NULL) 00232 { 00233 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00234 goto failed_0; 00235 } 00236 00237 listen_fd = _dbus_listen_unix_socket (path, abstract, error); 00238 00239 if (listen_fd < 0) 00240 { 00241 _DBUS_ASSERT_ERROR_IS_SET (error); 00242 goto failed_1; 00243 } 00244 00245 server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0); 00246 if (server == NULL) 00247 { 00248 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00249 goto failed_2; 00250 } 00251 00252 _dbus_server_socket_own_filename(server, path_copy); 00253 00254 _dbus_string_free (&address); 00255 00256 return server; 00257 00258 failed_2: 00259 _dbus_close_socket (listen_fd, NULL); 00260 failed_1: 00261 dbus_free (path_copy); 00262 failed_0: 00263 _dbus_string_free (&address); 00264 00265 return NULL; 00266 } 00267