1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport-unix.c UNIX socket subclasses of DBusTransport
3 *
4 * Copyright (C) 2002, 2003, 2004 Red Hat Inc.
5 *
6 * Licensed under the Academic Free License version 2.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24 #include <config.h>
25 #include "dbus-internals.h"
26 #include "dbus-connection-internal.h"
27 #include "dbus-transport-unix.h"
28 #include "dbus-transport-socket.h"
29 #include "dbus-transport-protected.h"
30 #include "dbus-watch.h"
31 #include "dbus-sysdeps-unix.h"
32
33 /**
34 * @defgroup DBusTransportUnix DBusTransport implementations for UNIX
35 * @ingroup DBusInternals
36 * @brief Implementation details of DBusTransport on UNIX
37 *
38 * @{
39 */
40
41 /**
42 * Creates a new transport for the given Unix domain socket
43 * path. This creates a client-side of a transport.
44 *
45 * @todo once we add a way to escape paths in a dbus
46 * address, this function needs to do escaping.
47 *
48 * @param path the path to the domain socket.
49 * @param abstract #TRUE to use abstract socket namespace
50 * @param error address where an error can be returned.
51 * @returns a new transport, or #NULL on failure.
52 */
53 DBusTransport*
_dbus_transport_new_for_domain_socket(const char * path,dbus_bool_t abstract,DBusError * error)54 _dbus_transport_new_for_domain_socket (const char *path,
55 dbus_bool_t abstract,
56 DBusError *error)
57 {
58 int fd;
59 DBusTransport *transport;
60 DBusString address;
61
62 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
63
64 if (!_dbus_string_init (&address))
65 {
66 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
67 return NULL;
68 }
69
70 fd = -1;
71
72 if ((abstract &&
73 !_dbus_string_append (&address, "unix:abstract=")) ||
74 (!abstract &&
75 !_dbus_string_append (&address, "unix:path=")) ||
76 !_dbus_string_append (&address, path))
77 {
78 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
79 goto failed_0;
80 }
81
82 fd = _dbus_connect_unix_socket (path, abstract, error);
83 if (fd < 0)
84 {
85 _DBUS_ASSERT_ERROR_IS_SET (error);
86 goto failed_0;
87 }
88
89 _dbus_verbose ("Successfully connected to unix socket %s\n",
90 path);
91
92 transport = _dbus_transport_new_for_socket (fd, NULL, &address);
93 if (transport == NULL)
94 {
95 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
96 goto failed_1;
97 }
98
99 _dbus_string_free (&address);
100
101 return transport;
102
103 failed_1:
104 _dbus_close_socket (fd, NULL);
105 failed_0:
106 _dbus_string_free (&address);
107 return NULL;
108 }
109
110 /**
111 * Opens platform specific transport types.
112 *
113 * @param entry the address entry to try opening
114 * @param transport_p return location for the opened transport
115 * @param error error to be set
116 * @returns result of the attempt
117 */
118 DBusTransportOpenResult
_dbus_transport_open_platform_specific(DBusAddressEntry * entry,DBusTransport ** transport_p,DBusError * error)119 _dbus_transport_open_platform_specific (DBusAddressEntry *entry,
120 DBusTransport **transport_p,
121 DBusError *error)
122 {
123 const char *method;
124
125 method = dbus_address_entry_get_method (entry);
126 _dbus_assert (method != NULL);
127
128 if (strcmp (method, "unix") == 0)
129 {
130 const char *path = dbus_address_entry_get_value (entry, "path");
131 const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
132 const char *abstract = dbus_address_entry_get_value (entry, "abstract");
133
134 if (tmpdir != NULL)
135 {
136 _dbus_set_bad_address (error, NULL, NULL,
137 "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on");
138 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
139 }
140
141 if (path == NULL && abstract == NULL)
142 {
143 _dbus_set_bad_address (error, "unix",
144 "path or abstract",
145 NULL);
146 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
147 }
148
149 if (path != NULL && abstract != NULL)
150 {
151 _dbus_set_bad_address (error, NULL, NULL,
152 "can't specify both \"path\" and \"abstract\" options in an address");
153 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
154 }
155
156 if (path)
157 *transport_p = _dbus_transport_new_for_domain_socket (path, FALSE,
158 error);
159 else
160 *transport_p = _dbus_transport_new_for_domain_socket (abstract, TRUE,
161 error);
162 if (*transport_p == NULL)
163 {
164 _DBUS_ASSERT_ERROR_IS_SET (error);
165 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
166 }
167 else
168 {
169 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
170 return DBUS_TRANSPORT_OPEN_OK;
171 }
172 }
173 else
174 {
175 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
176 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
177 }
178 }
179
180 /** @} */
181