Comments added and corrected
[platform/upstream/dbus.git] / dbus / kdbus-common.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* kdbus-common.c  kdbus related utils for daemon and libdbus
3  *
4  * Copyright (C) 2013  Samsung Electronics
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 and under the terms of the GNU
12  * Lesser General Public License as published by the
13  * Free Software Foundation; either version 2.1 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24  *
25  */
26 #include "kdbus.h"
27 #include "kdbus-common.h"
28 #include <string.h>
29 #include <stddef.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <dbus/dbus-internals.h>
34 #include <dbus/dbus-shared.h>
35
36 static struct kdbus_policy *make_policy_name(const char *name)
37 {
38         struct kdbus_policy *p;
39         __u64 size;
40
41         size = offsetof(struct kdbus_policy, name) + strlen(name) + 1;
42         p = malloc(size);
43         if (!p)
44                 return NULL;
45         memset(p, 0, size);
46         p->size = size;
47         p->type = KDBUS_POLICY_NAME;
48         strcpy(p->name, name);
49
50         return p;
51 }
52
53 static struct kdbus_policy *make_policy_access(__u64 type, __u64 bits, __u64 id)
54 {
55         struct kdbus_policy *p;
56         __u64 size = sizeof(*p);
57
58         p = malloc(size);
59         if (!p)
60                 return NULL;
61
62         memset(p, 0, size);
63         p->size = size;
64         p->type = KDBUS_POLICY_ACCESS;
65         p->access.type = type;
66         p->access.bits = bits;
67         p->access.id = id;
68
69         return p;
70 }
71
72 static void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_policy *policy, __u64 max_size)
73 {
74         struct kdbus_policy *dst = (struct kdbus_policy *) ((char *) cmd_policy + cmd_policy->size);
75
76         if (cmd_policy->size + policy->size > max_size)
77                 return;
78
79         memcpy(dst, policy, policy->size);
80         cmd_policy->size += KDBUS_ALIGN8(policy->size);
81         free(policy);
82 }
83
84 /**
85  * Registers kdbus policy for given connection.
86  *
87  * Policy sets rights of the name (unique or well known) on the bus. Without policy it is
88  * not possible to send or receive messages. It must be set separately for unique id and
89  * well known name of the connection. It is set after registering on the bus, but before
90  * requesting for name. The policy is valid for the given name, not for the connection.
91  *
92  * Name of the policy equals name on the bus.
93  *
94  * @param name name of the policy = name of the connection
95  * @param fd - file descriptor of the connection
96  *
97  * @returns #TRUE on success
98  */
99 dbus_bool_t register_kdbus_policy(const char* name, int fd)
100 {
101         struct kdbus_cmd_policy *cmd_policy;
102         struct kdbus_policy *policy;
103         int size = 0xffff;
104
105         cmd_policy = alloca(size);
106         memset(cmd_policy, 0, size);
107
108         policy = (struct kdbus_policy *) cmd_policy->policies;
109         cmd_policy->size = offsetof(struct kdbus_cmd_policy, policies);
110
111         policy = make_policy_name(name);
112         append_policy(cmd_policy, policy, size);
113
114         policy = make_policy_access(KDBUS_POLICY_ACCESS_USER, KDBUS_POLICY_OWN, getuid());
115         append_policy(cmd_policy, policy, size);
116
117         policy = make_policy_access(KDBUS_POLICY_ACCESS_WORLD, KDBUS_POLICY_RECV, 0);
118         append_policy(cmd_policy, policy, size);
119
120         policy = make_policy_access(KDBUS_POLICY_ACCESS_WORLD, KDBUS_POLICY_SEND, 0);
121         append_policy(cmd_policy, policy, size);
122
123         if (ioctl(fd, KDBUS_CMD_EP_POLICY_SET, cmd_policy) < 0)
124         {
125                 _dbus_verbose ("Error setting policy: %m, %d\n", errno);
126                 return FALSE;
127         }
128
129         _dbus_verbose("Policy %s set correctly\n", name);
130         return TRUE;
131 }
132
133 /*
134  * Asks kdbus for well-known names registered on the bus
135  */
136 dbus_bool_t list_kdbus_names(int fd, char ***listp, int *array_len)
137 {
138         struct kdbus_cmd_names* pCmd;
139         __u64 cmd_size;
140         dbus_bool_t ret_val = FALSE;
141         char** list;
142         int list_len = 0;
143         int i = 0;
144         int j;
145
146         cmd_size = sizeof(struct kdbus_cmd_names) + KDBUS_ITEM_SIZE(1);
147         pCmd = malloc(cmd_size);
148         if(pCmd == NULL)
149                 goto out;
150         pCmd->size = cmd_size;
151
152 again:
153         cmd_size = 0;
154         if(ioctl(fd, KDBUS_CMD_NAME_LIST, pCmd))
155         {
156                 if(errno == EINTR)
157                         goto again;
158                 if(errno == ENOBUFS)                    //buffer to small to put all names into it
159                         cmd_size = pCmd->size;          //here kernel tells how much memory it needs
160                 else
161                 {
162                         _dbus_verbose("kdbus error asking for name list: err %d (%m)\n",errno);
163                         goto out;
164                 }
165         }
166         if(cmd_size)  //kernel needs more memory
167         {
168                 pCmd = realloc(pCmd, cmd_size);  //prepare memory
169                 if(pCmd == NULL)
170                         return FALSE;
171                 goto again;                                             //and try again
172         }
173         else
174         {
175                 struct kdbus_cmd_name* pCmd_name;
176
177                 for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
178                         list_len++;
179
180                 list = malloc(sizeof(char*) * (list_len + 1));
181                 if(list == NULL)
182                         goto out;
183
184                 for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
185                 {
186                         list[i] = strdup(pCmd_name->name);
187                         if(list[i] == NULL)
188                         {
189                                 for(j=0; j<i; j++)
190                                         free(list[j]);
191                                 free(list);
192                                 goto out;
193                         }
194                         _dbus_verbose ("Name %d: %s\n", i, list[i]);
195                         ++i;
196                 }
197                 list[i] = NULL;
198         }
199
200         *array_len = list_len;
201         *listp = list;
202         ret_val = TRUE;
203
204 out:
205         if(pCmd)
206                 free(pCmd);
207         return ret_val;
208 }
209
210 /**
211  *
212  * Asks the bus to assign the given name to the connection.
213  *
214  * Use same flags as original dbus version with one exception below.
215  * Result flag #DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER is currently
216  * never returned by kdbus, instead DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
217  * is returned by kdbus.
218  *
219  * @param fd - file descriptor of the connection
220  * @param name the name to request
221  * @param flags flags
222  * @param id unique id of the connection for which the name is being registered
223  * @returns a DBus result code on success, -errno on error
224  */
225 int request_kdbus_name(int fd, const char *name, const __u64 flags, __u64 id)
226 {
227         struct kdbus_cmd_name *cmd_name;
228
229         __u64 size = sizeof(*cmd_name) + strlen(name) + 1;
230         __u64 flags_kdbus = 0;
231
232         cmd_name = alloca(size);
233
234         strcpy(cmd_name->name, name);
235         cmd_name->size = size;
236
237         if(flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)
238                 flags_kdbus |= KDBUS_NAME_ALLOW_REPLACEMENT;
239         if(!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE))
240                 flags_kdbus |= KDBUS_NAME_QUEUE;
241         if(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
242                 flags_kdbus |= KDBUS_NAME_REPLACE_EXISTING;
243         if(flags & KDBUS_NAME_STARTER)
244             flags_kdbus |= KDBUS_NAME_STARTER;
245
246         cmd_name->flags = flags_kdbus;
247         cmd_name->id = id;
248 //      cmd_name->conn_flags = 0;
249
250         _dbus_verbose("Request name - flags sent: 0x%llx       !!!!!!!!!\n", cmd_name->flags);
251
252         if (ioctl(fd, KDBUS_CMD_NAME_ACQUIRE, cmd_name))
253         {
254                 _dbus_verbose ("error acquiring name '%s': %m, %d\n", name, errno);
255                 if(errno == EEXIST)
256                         return DBUS_REQUEST_NAME_REPLY_EXISTS;
257                 return -errno;
258         }
259
260         _dbus_verbose("Request name - received flag: 0x%llx       !!!!!!!!!\n", cmd_name->flags);
261
262         if(cmd_name->flags & KDBUS_NAME_IN_QUEUE)
263                 return DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
264         else
265                 return DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
266         /*todo now 1 code is never returned -  DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
267          * because kdbus never returns it now
268          */
269 }
270
271 /**
272  *
273  * Releases well-known name - the connections resign from the name
274  * which can be then assigned to another connection or the connection
275  * is being removed from the queue for that name
276  *
277  * @param fd - file descriptor of the connection
278  * @param name the name to request
279  * @param id unique id of the connection for which the name is being released
280  * @returns a DBus result code on success, -errno on error
281  */
282 int release_kdbus_name(int fd, const char *name, __u64 id)
283 {
284         struct kdbus_cmd_name *cmd_name;
285
286         __u64 size = sizeof(*cmd_name) + strlen(name) + 1;
287
288         cmd_name = alloca(size);
289         cmd_name->id = id;
290         strcpy(cmd_name->name, name);
291         cmd_name->size = size;
292
293         if (ioctl(fd, KDBUS_CMD_NAME_RELEASE, cmd_name))
294         {
295                 if(errno == ESRCH)
296                         return DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
297                 else if (errno == EPERM)
298                         return DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
299                 _dbus_verbose ("error releasing name '%s' for id:%llu. Error: %m, %d\n", name, (unsigned long long)id, errno);
300                 return -errno;
301         }
302
303         _dbus_verbose("Name '%s' released\n", name);
304
305         return DBUS_RELEASE_NAME_REPLY_RELEASED;
306 }