D-Bus 1.6.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-server-socket.c Server implementation for sockets 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2006 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-socket.h" 00027 #include "dbus-transport-socket.h" 00028 #include "dbus-connection-internal.h" 00029 #include "dbus-memory.h" 00030 #include "dbus-nonce.h" 00031 #include "dbus-string.h" 00032 00044 typedef struct DBusServerSocket DBusServerSocket; 00045 00050 struct DBusServerSocket 00051 { 00052 DBusServer base; 00053 int n_fds; 00054 int *fds; 00055 DBusWatch **watch; 00056 char *socket_name; 00057 DBusNonceFile *noncefile; 00058 }; 00059 00060 static void 00061 socket_finalize (DBusServer *server) 00062 { 00063 DBusServerSocket *socket_server = (DBusServerSocket*) server; 00064 int i; 00065 00066 _dbus_server_finalize_base (server); 00067 00068 for (i = 0 ; i < socket_server->n_fds ; i++) 00069 if (socket_server->watch[i]) 00070 { 00071 _dbus_watch_unref (socket_server->watch[i]); 00072 socket_server->watch[i] = NULL; 00073 } 00074 00075 dbus_free (socket_server->fds); 00076 dbus_free (socket_server->watch); 00077 dbus_free (socket_server->socket_name); 00078 if (socket_server->noncefile) 00079 _dbus_noncefile_delete (socket_server->noncefile, NULL); 00080 dbus_free (socket_server->noncefile); 00081 dbus_free (server); 00082 } 00083 00084 /* Return value is just for memory, not other failures. */ 00085 static dbus_bool_t 00086 handle_new_client_fd_and_unlock (DBusServer *server, 00087 int client_fd) 00088 { 00089 DBusConnection *connection; 00090 DBusTransport *transport; 00091 DBusNewConnectionFunction new_connection_function; 00092 void *new_connection_data; 00093 00094 _dbus_verbose ("Creating new client connection with fd %d\n", client_fd); 00095 00096 HAVE_LOCK_CHECK (server); 00097 00098 if (!_dbus_set_fd_nonblocking (client_fd, NULL)) 00099 { 00100 SERVER_UNLOCK (server); 00101 return TRUE; 00102 } 00103 00104 transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, FALSE); 00105 if (transport == NULL) 00106 { 00107 _dbus_close_socket (client_fd, NULL); 00108 SERVER_UNLOCK (server); 00109 return FALSE; 00110 } 00111 00112 if (!_dbus_transport_set_auth_mechanisms (transport, 00113 (const char **) server->auth_mechanisms)) 00114 { 00115 _dbus_transport_unref (transport); 00116 SERVER_UNLOCK (server); 00117 return FALSE; 00118 } 00119 00120 /* note that client_fd is now owned by the transport, and will be 00121 * closed on transport disconnection/finalization 00122 */ 00123 00124 connection = _dbus_connection_new_for_transport (transport); 00125 _dbus_transport_unref (transport); 00126 transport = NULL; /* now under the connection lock */ 00127 00128 if (connection == NULL) 00129 { 00130 SERVER_UNLOCK (server); 00131 return FALSE; 00132 } 00133 00134 /* See if someone wants to handle this new connection, self-referencing 00135 * for paranoia. 00136 */ 00137 new_connection_function = server->new_connection_function; 00138 new_connection_data = server->new_connection_data; 00139 00140 _dbus_server_ref_unlocked (server); 00141 SERVER_UNLOCK (server); 00142 00143 if (new_connection_function) 00144 { 00145 (* new_connection_function) (server, connection, 00146 new_connection_data); 00147 } 00148 dbus_server_unref (server); 00149 00150 /* If no one grabbed a reference, the connection will die. */ 00151 _dbus_connection_close_if_only_one_ref (connection); 00152 dbus_connection_unref (connection); 00153 00154 return TRUE; 00155 } 00156 00157 static dbus_bool_t 00158 socket_handle_watch (DBusWatch *watch, 00159 unsigned int flags, 00160 void *data) 00161 { 00162 DBusServer *server = data; 00163 DBusServerSocket *socket_server = data; 00164 00165 #ifndef DBUS_DISABLE_ASSERT 00166 int i; 00167 dbus_bool_t found = FALSE; 00168 #endif 00169 00170 SERVER_LOCK (server); 00171 00172 #ifndef DBUS_DISABLE_ASSERT 00173 for (i = 0 ; i < socket_server->n_fds ; i++) 00174 { 00175 if (socket_server->watch[i] == watch) 00176 found = TRUE; 00177 } 00178 _dbus_assert (found); 00179 #endif 00180 00181 _dbus_verbose ("Handling client connection, flags 0x%x\n", flags); 00182 00183 if (flags & DBUS_WATCH_READABLE) 00184 { 00185 int client_fd; 00186 int listen_fd; 00187 00188 listen_fd = dbus_watch_get_socket (watch); 00189 00190 if (socket_server->noncefile) 00191 client_fd = _dbus_accept_with_noncefile (listen_fd, socket_server->noncefile); 00192 else 00193 client_fd = _dbus_accept (listen_fd); 00194 00195 if (client_fd < 0) 00196 { 00197 /* EINTR handled for us */ 00198 00199 if (_dbus_get_is_errno_eagain_or_ewouldblock ()) 00200 _dbus_verbose ("No client available to accept after all\n"); 00201 else 00202 _dbus_verbose ("Failed to accept a client connection: %s\n", 00203 _dbus_strerror_from_errno ()); 00204 00205 SERVER_UNLOCK (server); 00206 } 00207 else 00208 { 00209 if (!handle_new_client_fd_and_unlock (server, client_fd)) 00210 _dbus_verbose ("Rejected client connection due to lack of memory\n"); 00211 } 00212 } 00213 00214 if (flags & DBUS_WATCH_ERROR) 00215 _dbus_verbose ("Error on server listening socket\n"); 00216 00217 if (flags & DBUS_WATCH_HANGUP) 00218 _dbus_verbose ("Hangup on server listening socket\n"); 00219 00220 return TRUE; 00221 } 00222 00223 static void 00224 socket_disconnect (DBusServer *server) 00225 { 00226 DBusServerSocket *socket_server = (DBusServerSocket*) server; 00227 int i; 00228 00229 HAVE_LOCK_CHECK (server); 00230 00231 for (i = 0 ; i < socket_server->n_fds ; i++) 00232 { 00233 if (socket_server->watch[i]) 00234 { 00235 _dbus_server_remove_watch (server, 00236 socket_server->watch[i]); 00237 _dbus_watch_invalidate (socket_server->watch[i]); 00238 _dbus_watch_unref (socket_server->watch[i]); 00239 socket_server->watch[i] = NULL; 00240 } 00241 00242 _dbus_close_socket (socket_server->fds[i], NULL); 00243 socket_server->fds[i] = -1; 00244 } 00245 00246 if (socket_server->socket_name != NULL) 00247 { 00248 DBusString tmp; 00249 _dbus_string_init_const (&tmp, socket_server->socket_name); 00250 _dbus_delete_file (&tmp, NULL); 00251 } 00252 00253 if (server->published_address) 00254 _dbus_daemon_unpublish_session_bus_address(); 00255 00256 HAVE_LOCK_CHECK (server); 00257 } 00258 00259 static const DBusServerVTable socket_vtable = { 00260 socket_finalize, 00261 socket_disconnect 00262 }; 00263 00279 DBusServer* 00280 _dbus_server_new_for_socket (int *fds, 00281 int n_fds, 00282 const DBusString *address, 00283 DBusNonceFile *noncefile) 00284 { 00285 DBusServerSocket *socket_server; 00286 DBusServer *server; 00287 int i; 00288 00289 socket_server = dbus_new0 (DBusServerSocket, 1); 00290 if (socket_server == NULL) 00291 return NULL; 00292 00293 socket_server->noncefile = noncefile; 00294 00295 socket_server->fds = dbus_new (int, n_fds); 00296 if (!socket_server->fds) 00297 goto failed_0; 00298 00299 socket_server->watch = dbus_new0 (DBusWatch *, n_fds); 00300 if (!socket_server->watch) 00301 goto failed_1; 00302 00303 for (i = 0 ; i < n_fds ; i++) 00304 { 00305 DBusWatch *watch; 00306 00307 watch = _dbus_watch_new (fds[i], 00308 DBUS_WATCH_READABLE, 00309 TRUE, 00310 socket_handle_watch, socket_server, 00311 NULL); 00312 if (watch == NULL) 00313 goto failed_2; 00314 00315 socket_server->n_fds++; 00316 socket_server->fds[i] = fds[i]; 00317 socket_server->watch[i] = watch; 00318 } 00319 00320 if (!_dbus_server_init_base (&socket_server->base, 00321 &socket_vtable, address)) 00322 goto failed_2; 00323 00324 server = (DBusServer*)socket_server; 00325 00326 SERVER_LOCK (server); 00327 00328 for (i = 0 ; i < n_fds ; i++) 00329 { 00330 if (!_dbus_server_add_watch (&socket_server->base, 00331 socket_server->watch[i])) 00332 { 00333 int j; 00334 for (j = 0 ; j < i ; j++) 00335 _dbus_server_remove_watch (server, 00336 socket_server->watch[j]); 00337 00338 SERVER_UNLOCK (server); 00339 _dbus_server_finalize_base (&socket_server->base); 00340 goto failed_2; 00341 } 00342 } 00343 00344 SERVER_UNLOCK (server); 00345 00346 _dbus_server_trace_ref (&socket_server->base, 0, 1, "new_for_socket"); 00347 return (DBusServer*) socket_server; 00348 00349 failed_2: 00350 for (i = 0 ; i < n_fds ; i++) 00351 { 00352 if (socket_server->watch[i] != NULL) 00353 { 00354 _dbus_watch_unref (socket_server->watch[i]); 00355 socket_server->watch[i] = NULL; 00356 } 00357 } 00358 dbus_free (socket_server->watch); 00359 00360 failed_1: 00361 dbus_free (socket_server->fds); 00362 00363 failed_0: 00364 dbus_free (socket_server); 00365 return NULL; 00366 } 00367 00387 DBusServer* 00388 _dbus_server_new_for_tcp_socket (const char *host, 00389 const char *bind, 00390 const char *port, 00391 const char *family, 00392 DBusError *error, 00393 dbus_bool_t use_nonce) 00394 { 00395 DBusServer *server; 00396 int *listen_fds = NULL; 00397 int nlisten_fds = 0, i; 00398 DBusString address; 00399 DBusString host_str; 00400 DBusString port_str; 00401 DBusNonceFile *noncefile; 00402 00403 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00404 00405 noncefile = NULL; 00406 00407 if (!_dbus_string_init (&address)) 00408 { 00409 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00410 return NULL; 00411 } 00412 00413 if (!_dbus_string_init (&port_str)) 00414 { 00415 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00416 goto failed_0; 00417 } 00418 00419 if (host == NULL) 00420 host = "localhost"; 00421 00422 if (port == NULL) 00423 port = "0"; 00424 00425 if (bind == NULL) 00426 bind = host; 00427 else if (strcmp (bind, "*") == 0) 00428 bind = NULL; 00429 00430 nlisten_fds =_dbus_listen_tcp_socket (bind, port, family, 00431 &port_str, 00432 &listen_fds, error); 00433 if (nlisten_fds <= 0) 00434 { 00435 _DBUS_ASSERT_ERROR_IS_SET(error); 00436 goto failed_1; 00437 } 00438 00439 _dbus_string_init_const (&host_str, host); 00440 if (!_dbus_string_append (&address, use_nonce ? "nonce-tcp:host=" : "tcp:host=") || 00441 !_dbus_address_append_escaped (&address, &host_str) || 00442 !_dbus_string_append (&address, ",port=") || 00443 !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str))) 00444 { 00445 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00446 goto failed_2; 00447 } 00448 if (family && 00449 (!_dbus_string_append (&address, ",family=") || 00450 !_dbus_string_append (&address, family))) 00451 { 00452 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00453 goto failed_2; 00454 } 00455 00456 if (use_nonce) 00457 { 00458 noncefile = dbus_new0 (DBusNonceFile, 1); 00459 if (noncefile == NULL) 00460 { 00461 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00462 goto failed_2; 00463 } 00464 00465 if (!_dbus_noncefile_create (noncefile, error)) 00466 goto failed_3; 00467 00468 if (!_dbus_string_append (&address, ",noncefile=") || 00469 !_dbus_address_append_escaped (&address, _dbus_noncefile_get_path (noncefile))) 00470 { 00471 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00472 goto failed_4; 00473 } 00474 00475 } 00476 00477 server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address, noncefile); 00478 if (server == NULL) 00479 { 00480 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00481 goto failed_4; 00482 } 00483 00484 _dbus_string_free (&port_str); 00485 _dbus_string_free (&address); 00486 dbus_free(listen_fds); 00487 00488 return server; 00489 00490 failed_4: 00491 _dbus_noncefile_delete (noncefile, NULL); 00492 00493 failed_3: 00494 dbus_free (noncefile); 00495 00496 failed_2: 00497 for (i = 0 ; i < nlisten_fds ; i++) 00498 _dbus_close_socket (listen_fds[i], NULL); 00499 dbus_free(listen_fds); 00500 00501 failed_1: 00502 _dbus_string_free (&port_str); 00503 00504 failed_0: 00505 _dbus_string_free (&address); 00506 00507 return NULL; 00508 } 00509 00522 DBusServerListenResult 00523 _dbus_server_listen_socket (DBusAddressEntry *entry, 00524 DBusServer **server_p, 00525 DBusError *error) 00526 { 00527 const char *method; 00528 00529 *server_p = NULL; 00530 00531 method = dbus_address_entry_get_method (entry); 00532 00533 if (strcmp (method, "tcp") == 0 || strcmp (method, "nonce-tcp") == 0) 00534 { 00535 const char *host; 00536 const char *port; 00537 const char *bind; 00538 const char *family; 00539 00540 host = dbus_address_entry_get_value (entry, "host"); 00541 bind = dbus_address_entry_get_value (entry, "bind"); 00542 port = dbus_address_entry_get_value (entry, "port"); 00543 family = dbus_address_entry_get_value (entry, "family"); 00544 00545 *server_p = _dbus_server_new_for_tcp_socket (host, bind, port, 00546 family, error, strcmp (method, "nonce-tcp") == 0 ? TRUE : FALSE); 00547 00548 if (*server_p) 00549 { 00550 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00551 return DBUS_SERVER_LISTEN_OK; 00552 } 00553 else 00554 { 00555 _DBUS_ASSERT_ERROR_IS_SET(error); 00556 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00557 } 00558 } 00559 else 00560 { 00561 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00562 return DBUS_SERVER_LISTEN_NOT_HANDLED; 00563 } 00564 } 00565 00575 void 00576 _dbus_server_socket_own_filename (DBusServer *server, 00577 char *filename) 00578 { 00579 DBusServerSocket *socket_server = (DBusServerSocket*) server; 00580 00581 socket_server->socket_name = filename; 00582 } 00583 00584