4a5d7f2e22b8787fe4a4c13374d9c845e083d533
[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 "dbus-transport-kdbus.h"
29 #include <string.h>
30 #include <stddef.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <dbus/dbus-internals.h>
35 #include <dbus/dbus-shared.h>
36
37 static struct kdbus_policy *make_policy_name(const char *name)
38 {
39         struct kdbus_policy *p;
40         __u64 size;
41
42         size = offsetof(struct kdbus_policy, name) + strlen(name) + 1;
43         p = malloc(size);
44         if (!p)
45                 return NULL;
46         memset(p, 0, size);
47         p->size = size;
48         p->type = KDBUS_POLICY_NAME;
49         strcpy(p->name, name);
50
51         return p;
52 }
53
54 static struct kdbus_policy *make_policy_access(__u64 type, __u64 bits, __u64 id)
55 {
56         struct kdbus_policy *p;
57         __u64 size = sizeof(*p);
58
59         p = malloc(size);
60         if (!p)
61                 return NULL;
62
63         memset(p, 0, size);
64         p->size = size;
65         p->type = KDBUS_POLICY_ACCESS;
66         p->access.type = type;
67         p->access.bits = bits;
68         p->access.id = id;
69
70         return p;
71 }
72
73 static void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_policy *policy, __u64 max_size)
74 {
75         struct kdbus_policy *dst = (struct kdbus_policy *) ((char *) cmd_policy + cmd_policy->size);
76
77         if (cmd_policy->size + policy->size > max_size)
78                 return;
79
80         memcpy(dst, policy, policy->size);
81         cmd_policy->size += KDBUS_ALIGN8(policy->size);
82         free(policy);
83 }
84
85 /**
86  * Registers kdbus policy for given connection.
87  *
88  * Policy sets rights of the name (unique or well known) on the bus. Without policy it is
89  * not possible to send or receive messages. It must be set separately for unique id and
90  * well known name of the connection. It is set after registering on the bus, but before
91  * requesting for name. The policy is valid for the given name, not for the connection.
92  *
93  * Name of the policy equals name on the bus.
94  *
95  * @param name name of the policy = name of the connection
96  * @param fd - file descriptor of the connection
97  *
98  * @returns #TRUE on success
99  */
100 dbus_bool_t register_kdbus_policy(const char* name, int fd)
101 {
102         struct kdbus_cmd_policy *cmd_policy;
103         struct kdbus_policy *policy;
104         int size = 0xffff;
105
106         cmd_policy = alloca(size);
107         memset(cmd_policy, 0, size);
108
109         policy = (struct kdbus_policy *) cmd_policy->policies;
110         cmd_policy->size = offsetof(struct kdbus_cmd_policy, policies);
111
112         policy = make_policy_name(name);
113         append_policy(cmd_policy, policy, size);
114
115         policy = make_policy_access(KDBUS_POLICY_ACCESS_USER, KDBUS_POLICY_OWN, getuid());
116         append_policy(cmd_policy, policy, size);
117
118         policy = make_policy_access(KDBUS_POLICY_ACCESS_WORLD, KDBUS_POLICY_RECV, 0);
119         append_policy(cmd_policy, policy, size);
120
121         policy = make_policy_access(KDBUS_POLICY_ACCESS_WORLD, KDBUS_POLICY_SEND, 0);
122         append_policy(cmd_policy, policy, size);
123
124         if (ioctl(fd, KDBUS_CMD_EP_POLICY_SET, cmd_policy) < 0)
125         {
126                 _dbus_verbose ("Error setting policy: %m, %d\n", errno);
127                 return FALSE;
128         }
129
130         _dbus_verbose("Policy %s set correctly\n", name);
131         return TRUE;
132 }
133
134 /**
135  *
136  * Asks the bus to assign the given name to the connection.
137  *
138  * Use same flags as original dbus version with one exception below.
139  * Result flag #DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER is currently
140  * never returned by kdbus, instead DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
141  * is returned by kdbus.
142  *
143  * @param fd - file descriptor of the connection
144  * @param name the name to request
145  * @param flags flags
146  * @param id unique id of the connection for which the name is being registered
147  * @returns a DBus result code on success, -errno on error
148  */
149 int request_kdbus_name(int fd, const char *name, const __u64 flags, __u64 id)
150 {
151         struct kdbus_cmd_name *cmd_name;
152
153         __u64 size = sizeof(*cmd_name) + strlen(name) + 1;
154         __u64 flags_kdbus = 0;
155
156         cmd_name = alloca(size);
157
158         strcpy(cmd_name->name, name);
159         cmd_name->size = size;
160
161         if(flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)
162                 flags_kdbus |= KDBUS_NAME_ALLOW_REPLACEMENT;
163         if(!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE))
164                 flags_kdbus |= KDBUS_NAME_QUEUE;
165         if(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
166                 flags_kdbus |= KDBUS_NAME_REPLACE_EXISTING;
167         if(flags & KDBUS_NAME_STARTER)
168             flags_kdbus |= KDBUS_NAME_STARTER;
169
170         cmd_name->flags = flags_kdbus;
171         cmd_name->id = id;
172 //      cmd_name->conn_flags = 0;
173
174         _dbus_verbose("Request name - flags sent: 0x%llx       !!!!!!!!!\n", cmd_name->flags);
175
176         if (ioctl(fd, KDBUS_CMD_NAME_ACQUIRE, cmd_name))
177         {
178                 _dbus_verbose ("error acquiring name '%s': %m, %d\n", name, errno);
179                 if(errno == EEXIST)
180                         return DBUS_REQUEST_NAME_REPLY_EXISTS;
181                 return -errno;
182         }
183
184         _dbus_verbose("Request name - received flag: 0x%llx       !!!!!!!!!\n", cmd_name->flags);
185
186         if(cmd_name->flags & KDBUS_NAME_IN_QUEUE)
187                 return DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
188         else
189                 return DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
190         /*todo now 1 code is never returned -  DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
191          * because kdbus never returns it now
192          */
193 }
194
195 /**
196  *
197  * Releases well-known name - the connections resign from the name
198  * which can be then assigned to another connection or the connection
199  * is being removed from the queue for that name
200  *
201  * @param fd - file descriptor of the connection
202  * @param name the name to request
203  * @param id unique id of the connection for which the name is being released
204  * @returns a DBus result code on success, -errno on error
205  */
206 int release_kdbus_name(int fd, const char *name, __u64 id)
207 {
208         struct kdbus_cmd_name *cmd_name;
209
210         __u64 size = sizeof(*cmd_name) + strlen(name) + 1;
211
212         cmd_name = alloca(size);
213         cmd_name->id = id;
214         strcpy(cmd_name->name, name);
215         cmd_name->size = size;
216
217         if (ioctl(fd, KDBUS_CMD_NAME_RELEASE, cmd_name))
218         {
219                 if(errno == ESRCH)
220                         return DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
221                 else if (errno == EPERM)
222                         return DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
223                 _dbus_verbose ("error releasing name '%s' for id:%llu. Error: %m, %d\n", name, (unsigned long long)id, errno);
224                 return -errno;
225         }
226
227         _dbus_verbose("Name '%s' released\n", name);
228
229         return DBUS_RELEASE_NAME_REPLY_RELEASED;
230 }