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