Beginning of kdbus support
[platform/upstream/dbus.git] / dbus / dbus-transport-kdbus.c
1 /*
2  * dbus-transport-kdbus.c
3  *
4  * Transport layer using kdbus
5  *
6  *  Created on: Jun 20, 2013
7  *      Author: r.pajak
8  *
9  *
10  */
11
12 #include "dbus-transport.h"
13 #include "dbus-transport-kdbus.h"
14 #include <kdbus.h>
15 #include "dbus-errors.h"
16 #include <fcntl.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <sys/ioctl.h>
20 #include <stdio.h>
21
22 //todo poniższe do wywalenia po zaimplementowaniu vtable (_dbus_transport_new_for_socket)
23 #include "dbus-transport-socket.h"
24
25 int _dbus_connect_kdbus (const char *path, DBusError *error);
26 DBusTransport* _dbus_transport_new_for_kdbus (const char *path, DBusError *error);
27
28
29 /**
30  * Creates a connection to the kdbus bus
31   *
32  * This will set FD_CLOEXEC for the socket returned.
33  *
34  * @param path the path to UNIX domain socket
35  * @param error return location for error code
36  * @returns connection file descriptor or -1 on error
37  */
38 int _dbus_connect_kdbus (const char *path, DBusError *error)
39 {
40         int fd;
41
42         _DBUS_ASSERT_ERROR_IS_CLEAR (error);
43         _dbus_verbose ("connecting to kdbus bus %s\n", path);
44
45         fd = open(path, O_RDWR|O_CLOEXEC|O_NONBLOCK); //[RP] | O_NONBLOCK added here, in dbus added separately in section commented out below
46         if (fd < 0)
47         {
48                 dbus_set_error(error, _dbus_error_from_errno (errno), "Failed to open file descriptor: %s", _dbus_strerror (errno));
49                 _DBUS_ASSERT_ERROR_IS_SET(error);
50                 return -1;  //[RP] not needed here if commented block below is removed
51         }
52
53         /*if (!_dbus_set_fd_nonblocking (fd, error))
54     {
55                 _DBUS_ASSERT_ERROR_IS_SET (error);
56                 _dbus_close (fd, NULL);
57                 return -1;
58     }*/
59
60         return fd;
61 }
62
63
64 /**
65  * Creates a new transport for kdbus.
66  * This creates a client-side of a transport.
67  *
68  * @param path the path to the domain socket.
69  * @param error address where an error can be returned.
70  * @returns a new transport, or #NULL on failure.
71  */
72 DBusTransport* _dbus_transport_new_for_kdbus (const char *path, DBusError *error)
73 {
74         int fd;
75         DBusTransport *transport;
76         DBusString address;
77
78         _DBUS_ASSERT_ERROR_IS_CLEAR (error);
79
80         if (!_dbus_string_init (&address))
81     {
82                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
83                 return NULL;
84     }
85
86         fd = -1;
87
88         if (!_dbus_string_append (&address, path))
89     {
90                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
91                 goto failed_0;
92     }
93
94         fd = _dbus_connect_kdbus (path, error);
95 //      fd = _dbus_connect_unix_socket (path, error);
96         if (fd < 0)
97     {
98                 _DBUS_ASSERT_ERROR_IS_SET (error);
99                 goto failed_0;
100     }
101
102         _dbus_verbose ("Successfully connected to kdbus bus %s\n", path);
103
104         transport = _dbus_transport_new_for_socket (fd, NULL, &address);  //todo
105         if (transport == NULL)
106     {
107                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
108                 goto failed_1;
109     }
110
111         _dbus_string_free (&address);
112
113         return transport;
114
115         failed_1:
116                 _dbus_close_socket (fd, NULL);
117         failed_0:
118                 _dbus_string_free (&address);
119         return NULL;
120 }
121
122
123 /**
124  * Opens kdbus transport.
125  *
126  * @param entry the address entry to try opening
127  * @param transport_p return location for the opened transport
128  * @param error error to be set
129  * @returns result of the attempt
130  */
131 DBusTransportOpenResult _dbus_transport_open_kdbus(DBusAddressEntry  *entry,
132                                                            DBusTransport    **transport_p,
133                                                            DBusError         *error)
134 {
135         const char *method;
136
137         method = dbus_address_entry_get_method (entry);
138         _dbus_assert (method != NULL);
139
140         if (strcmp (method, "kdbus") == 0)
141     {
142                 const char *path = dbus_address_entry_get_value (entry, "path");
143
144                 if (path == NULL)
145         {
146                         _dbus_set_bad_address (error, "kdbus", "path", NULL);
147                         return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
148         }
149
150         *transport_p = _dbus_transport_new_for_kdbus (path, error);
151
152         if (*transport_p == NULL)
153         {
154                 _DBUS_ASSERT_ERROR_IS_SET (error);
155                 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
156         }
157         else
158         {
159                 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
160                 return DBUS_TRANSPORT_OPEN_OK;
161         }
162     }
163         else
164     {
165                 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
166                 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
167     }
168 }
169
170 dbus_bool_t bus_register_kdbus(char** unique_name, DBusConnection *connection, DBusError *error)
171 {
172         dbus_bool_t retval = TRUE;
173         char name[18];
174         struct kdbus_cmd_hello hello;
175         int fd;
176
177         memset(&hello, 0, sizeof(hello));
178         hello.conn_flags = KDBUS_HELLO_ACCEPT_FD |
179                            KDBUS_HELLO_ATTACH_COMM |
180                            KDBUS_HELLO_ATTACH_EXE |
181                            KDBUS_HELLO_ATTACH_CMDLINE |
182                            KDBUS_HELLO_ATTACH_CAPS |
183                            KDBUS_HELLO_ATTACH_CGROUP |
184                            KDBUS_HELLO_ATTACH_SECLABEL |
185                            KDBUS_HELLO_ATTACH_AUDIT;
186         hello.size = sizeof(struct kdbus_cmd_hello);
187         hello.pool_size = (16 * 1024LU * 1024LU);  //todo was: #define POOL_SIZE
188
189         if(!dbus_connection_get_socket(connection, &fd))
190         {
191                 dbus_set_error (error, "failed to get fd for connection", NULL);
192                 return FALSE;
193         }
194         if (ioctl(fd, KDBUS_CMD_HELLO, &hello))
195         {
196                 dbus_set_error(error,_dbus_error_from_errno (errno), "Failed to send  hello: %s", _dbus_strerror (errno));
197                 return FALSE;
198         }
199
200         _dbus_verbose("-- Our peer ID is: %llu\n", (unsigned long long)hello.id);  //todo [RP] can be removed after development
201         sprintf(name, "%llx", (unsigned long long)hello.id);
202         *unique_name = _dbus_strdup(name);
203         if (*unique_name == NULL)
204         {
205           _DBUS_SET_OOM (error);
206           return FALSE;
207         }
208
209         return retval;
210 }