00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
00121
00122
00123
00124 connection = _dbus_connection_new_for_transport (transport);
00125 _dbus_transport_unref (transport);
00126 transport = NULL;
00127
00128 if (connection == NULL)
00129 {
00130 SERVER_UNLOCK (server);
00131 return FALSE;
00132 }
00133
00134
00135
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
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
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