Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: src/profile.c

Issue 6659006: flimflam: add support for multiple profiles (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/flimflam.git@master
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * 2 *
3 * Connection Manager 3 * Connection Manager
4 * 4 *
5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved. 5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 * 10 *
(...skipping 13 matching lines...) Expand all
24 #endif 24 #endif
25 25
26 #include <string.h> 26 #include <string.h>
27 27
28 #include <glib.h> 28 #include <glib.h>
29 #include <gdbus.h> 29 #include <gdbus.h>
30 30
31 #include "connman.h" 31 #include "connman.h"
32 32
33 #define PROFILE_DEFAULT_IDENT "default" 33 #define PROFILE_DEFAULT_IDENT "default"
34 #define PROFILE_MAX 3 /* 2 is probably sufficient */
34 35
35 #define _DBG_PROFILE(fmt, arg...) DBG(DBG_PROFILE, fmt, ## arg) 36 #define _DBG_PROFILE(fmt, arg...) DBG(DBG_PROFILE, fmt, ## arg)
36 37
37 struct connman_profile { 38 struct connman_profile {
38 » char *ident; 39 » struct connman_storage_ident ident;
39 char *path; 40 char *path;
40 char *name; 41 char *name;
41 connman_bool_t offlinemode; 42 connman_bool_t offlinemode;
42 }; 43 };
43 44
44 static GHashTable *profile_hash = NULL; 45 static GHashTable *profile_hash = NULL;
46
47 static struct connman_profile *profile_stack[PROFILE_MAX];
48 static int cur_profile = -1;
49
50 static struct connman_storage_ident default_ident = {
51 .ident = PROFILE_DEFAULT_IDENT
52 };
45 static struct connman_profile *default_profile = NULL; 53 static struct connman_profile *default_profile = NULL;
46 54
47 static DBusConnection *connection = NULL; 55 static DBusConnection *connection = NULL;
48 56
57 static int ident_equal(const struct connman_storage_ident *a,
58 const struct connman_storage_ident *b)
59 {
60 return (g_strcmp0(a->user, b->user) == 0 &&
61 g_strcmp0(a->ident, b->ident) == 0);
62 }
63
49 static void append_path(gpointer key, gpointer value, gpointer user_data) 64 static void append_path(gpointer key, gpointer value, gpointer user_data)
50 { 65 {
51 struct connman_profile *profile = value; 66 struct connman_profile *profile = value;
52 DBusMessageIter *iter = user_data; 67 DBusMessageIter *iter = user_data;
53 68
54 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, 69 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
55 &profile->path); 70 &profile->path);
56 } 71 }
57 72
58 void __connman_profile_list(DBusMessageIter *iter, void *arg) 73 void __connman_profile_list(DBusMessageIter *iter, void *arg)
59 { 74 {
60 _DBG_PROFILE("");
61
62 g_hash_table_foreach(profile_hash, append_path, iter); 75 g_hash_table_foreach(profile_hash, append_path, iter);
63 } 76 }
64 77
65 static void profiles_changed(void) 78 static void profiles_changed(void)
66 { 79 {
67 _DBG_PROFILE("");
68
69 connman_dbus_send_property_changed_array(CONNMAN_MANAGER_PATH, 80 connman_dbus_send_property_changed_array(CONNMAN_MANAGER_PATH,
70 CONNMAN_MANAGER_INTERFACE, "Profiles", 81 CONNMAN_MANAGER_INTERFACE, "Profiles",
71 DBUS_TYPE_OBJECT_PATH, __connman_profile_list, NULL); 82 DBUS_TYPE_OBJECT_PATH, __connman_profile_list, NULL);
72 } 83 }
73 84
74 static void name_changed(struct connman_profile *profile)
75 {
76 _DBG_PROFILE("profile %p", profile);
77
78 connman_dbus_send_property_changed_variant(profile->path,
79 CONNMAN_PROFILE_INTERFACE, "Name",
80 DBUS_TYPE_STRING, &profile->name);
81 }
82
83 static void offlinemode_changed(struct connman_profile *profile)
84 {
85 _DBG_PROFILE("profile %p", profile);
86
87 connman_dbus_send_property_changed_variant(profile->path,
88 CONNMAN_PROFILE_INTERFACE, "OfflineMode",
89 DBUS_TYPE_BOOLEAN, &profile->offlinemode);
90 }
91
92 connman_bool_t __connman_profile_get_offlinemode(void) 85 connman_bool_t __connman_profile_get_offlinemode(void)
93 { 86 {
94 » if (default_profile == NULL) 87 » return (default_profile == NULL) ? FALSE : default_profile->offlinemode;
95 » » return FALSE;
96
97 » _DBG_PROFILE("offlinemode %d", default_profile->offlinemode);
98
99 » return default_profile->offlinemode;
100 } 88 }
101 89
102 int __connman_profile_set_offlinemode(connman_bool_t offlinemode) 90 int __connman_profile_set_offlinemode(connman_bool_t offlinemode)
103 { 91 {
104 _DBG_PROFILE("offlinemode %d", offlinemode); 92 _DBG_PROFILE("offlinemode %d", offlinemode);
105 93
106 » if (default_profile == NULL) 94 » /* TODO(sleffler) disallow if no default profile? */
107 » » return -EINVAL; 95 » if (default_profile != NULL) {
96 » » /*
97 » » * OfflineMode is only saved to the default profile;
98 » » * this ensures it is preserved across user changes.
99 » » */
100 » » if (default_profile->offlinemode == offlinemode)
101 » » » return -EALREADY;
108 102
109 » if (default_profile->offlinemode == offlinemode) 103 » » default_profile->offlinemode = offlinemode;
110 » » return -EALREADY;
111 104
112 » default_profile->offlinemode = offlinemode; 105 » » connman_dbus_send_property_changed_variant(
113 » offlinemode_changed(default_profile); 106 » » default_profile->path,
107 » » CONNMAN_PROFILE_INTERFACE, "OfflineMode",
108 » » DBUS_TYPE_BOOLEAN, &offlinemode);
109 » }
110 » return __connman_device_set_offlinemode(offlinemode);
111 }
114 112
115 » __connman_device_set_offlinemode(offlinemode); 113 /*
114 * Return the active profile; it's on the top of the stack.
115 */
116 static inline struct connman_profile *active_profile(void)
117 {
118 » return cur_profile >= 0 ? profile_stack[cur_profile] : NULL;
119 }
116 120
121 /*
122 * Load/Save objects. When loading we walk the stack of profiles
123 * until we find a successful load. Saving always happens to the
124 * top-most/active profile.
125 */
126
127 static inline int load_continue(int err)
128 {
129 /* NB: ENXIO for no file, ESRCH for no group/key */
130 return (err == -ENXIO || err == -ESRCH);
131 }
132
133 int __connman_profile_load_service(struct connman_service *service)
134 {
135 int i, err;
136
137 _DBG_PROFILE("service %p", service);
138
139 err = 0;
140 for (i = cur_profile; i >= 0; i--) {
141 const struct connman_profile *profile = profile_stack[i];
142
143 err = __connman_storage_load_service(service, &profile->ident);
144 if (!load_continue(err))
145 break;
146 }
147 return err;
148 }
149
150 int __connman_profile_save_service(struct connman_service *service)
151 {
152 struct connman_profile *profile = active_profile();
153
154 _DBG_PROFILE("service %p profile %p", service, profile);
155
156 return (profile == NULL) ? 0 :
157 __connman_storage_save_service(service, &profile->ident);
158 }
159
160 int __connman_profile_load_device(struct connman_device *device)
161 {
162 int i, err;
163
164 _DBG_PROFILE("device %p", device);
165
166 err = 0;
167 for (i = cur_profile; i >= 0; i--) {
168 const struct connman_profile *profile = profile_stack[i];
169
170 err = __connman_storage_load_device(device, &profile->ident);
171 if (!load_continue(err))
172 break;
173 }
174 return err;
175 }
176
177 int __connman_profile_save_device(struct connman_device *device)
178 {
179 struct connman_profile *profile = active_profile();
180
181 _DBG_PROFILE("device %p profile %p", device, profile);
182
183 return (profile == NULL) ? 0:
184 __connman_storage_save_device(device, &profile->ident);
185 }
186
187 int __connman_profile_load_ipconfig(struct connman_ipconfig *ipconfig)
188 {
189 int i, err;
190
191 _DBG_PROFILE("ipconfig %p", ipconfig);
192
193 err = 0;
194 for (i = cur_profile; i >= 0; i--) {
195 const struct connman_profile *profile = profile_stack[i];
196
197 err = __connman_storage_load_ipconfig(ipconfig,
198 &profile->ident);
199 if (!load_continue(err))
200 break;
201 }
202 return err;
203 }
204
205 int __connman_profile_save_ipconfig(const struct connman_ipconfig *ipconfig)
206 {
207 struct connman_profile *profile = active_profile();
208
209 _DBG_PROFILE("ipconfig %p profile %p", ipconfig, profile);
210
211 return (profile == NULL) ? 0 :
212 __connman_storage_save_ipconfig(ipconfig, &profile->ident);
213 }
214
215 /*
216 * Save the default profile if registered.
217 */
218 int __connman_profile_save_default(void)
219 {
220 if (default_profile != NULL)
221 __connman_storage_save_profile(default_profile);
117 return 0; 222 return 0;
118 } 223 }
119 224
120 int __connman_profile_save_default(void) 225 /*
226 * Save the active profile (if any).
227 */
228 int __connman_profile_save_active(void)
121 { 229 {
122 » _DBG_PROFILE(""); 230 » struct connman_profile *profile = active_profile();
123 231 » return (profile == NULL) ? -EINVAL :
124 » if (default_profile != NULL) 232 » __connman_storage_save_profile(profile);
125 » » __connman_storage_save_profile(default_profile);
126
127 » return 0;
128 } 233 }
129 234
130 const char *__connman_profile_active_ident(void) 235 /*
236 * Return the identifier for the active profile or NULL
237 * if there is none.
238 */
239 const struct connman_storage_ident *__connman_profile_active_ident(void)
131 { 240 {
132 » _DBG_PROFILE(""); 241 » struct connman_profile *profile = active_profile();
133 242 » return profile != NULL ? &profile->ident : NULL;
134 » return PROFILE_DEFAULT_IDENT;
135 } 243 }
136 244
245 /*
246 * Return the object path for the active profile or NULL
247 * if there is none.
248 */
137 const char *__connman_profile_active_path(void) 249 const char *__connman_profile_active_path(void)
138 { 250 {
139 » _DBG_PROFILE(""); 251 » struct connman_profile *profile = active_profile();
140 252 » return profile != NULL ? profile->path : NULL;
141 » if (default_profile == NULL)
142 » » return NULL;
143
144 » return default_profile->path;
145 } 253 }
146 254
147 static guint changed_timeout = 0; 255 static guint changed_timeout = 0;
148 256
149 static void append_services(DBusMessageIter *iter, void *arg) 257 static void append_services(DBusMessageIter *iter, void *arg)
150 { 258 {
151 » const struct connman_profile *profile = arg; 259 » __connman_service_list(iter, arg);
152 » if (g_strcmp0(profile->ident, PROFILE_DEFAULT_IDENT) == 0)
153 » » __connman_service_list(iter, arg);
154 } 260 }
155 static gboolean services_changed(gpointer user_data) 261 static gboolean services_changed(gpointer user_data)
156 { 262 {
157 » struct connman_profile *profile = default_profile; 263 » struct connman_profile *profile = user_data;
158 264
159 changed_timeout = 0; 265 changed_timeout = 0;
160 266
161 if (profile != NULL) { 267 if (profile != NULL) {
162 connman_dbus_send_property_changed_array(profile->path, 268 connman_dbus_send_property_changed_array(profile->path,
163 CONNMAN_PROFILE_INTERFACE, "Services", 269 CONNMAN_PROFILE_INTERFACE, "Services",
164 DBUS_TYPE_OBJECT_PATH, append_services, profile); 270 DBUS_TYPE_OBJECT_PATH, append_services, profile);
165 271
166 » » if (g_strcmp0(profile->ident, PROFILE_DEFAULT_IDENT) == 0) 272 » » connman_dbus_send_property_changed_array(CONNMAN_MANAGER_PATH,
167 » » » connman_dbus_send_property_changed_array( 273 » » CONNMAN_MANAGER_INTERFACE, "Services",
168 » » » CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, 274 » » DBUS_TYPE_OBJECT_PATH, append_services, profile);
169 » » » "Services",
170 » » » DBUS_TYPE_OBJECT_PATH, append_services, profile);
171 } 275 }
172 return FALSE; 276 return FALSE;
173 } 277 }
174 278
279 /*
280 * Handle changes to the profile. Generate PropertChanged signals
Nathan Williams 2011/03/09 21:28:10 Typo.
Sam Leffler 2011/03/09 22:31:14 Done
281 * on Manager.Services and Profile.Services for the currently active
282 * profile. To minimize overhead requests may be coalesced using a
283 * 1 second delay on the signals.
284 */
175 void __connman_profile_changed(gboolean delayed) 285 void __connman_profile_changed(gboolean delayed)
176 { 286 {
177 » _DBG_PROFILE(""); 287 » _DBG_PROFILE("delayed %d changed_timeout %d", delayed, changed_timeout);
178 288
179 if (changed_timeout > 0) { 289 if (changed_timeout > 0) {
180 g_source_remove(changed_timeout); 290 g_source_remove(changed_timeout);
181 changed_timeout = 0; 291 changed_timeout = 0;
182 } 292 }
183 293
184 if (delayed == FALSE) { 294 if (delayed == FALSE) {
185 services_changed(NULL); 295 services_changed(NULL);
Nathan Williams 2011/03/09 21:28:10 Now that services_changed() takes a profile argume
Sam Leffler 2011/03/09 22:31:14 Yup, updated.
186 return; 296 return;
187 } 297 }
188 298
189 » changed_timeout = g_timeout_add_seconds(1, services_changed, NULL); 299 » changed_timeout = g_timeout_add_seconds(1, services_changed,
300 » active_profile());
190 } 301 }
191 302
192 int __connman_profile_add_device(struct connman_device *device) 303 int __connman_profile_add_device(struct connman_device *device)
193 { 304 {
194 struct connman_service *service; 305 struct connman_service *service;
195 306
196 _DBG_PROFILE("device %p", device); 307 _DBG_PROFILE("device %p", device);
197 308
198 service = __connman_service_create_from_device(device); 309 service = __connman_service_create_from_device(device);
199 if (service == NULL) 310 if (service == NULL)
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 378
268 static void __profile_entry_list(DBusMessageIter *iter, void *arg) 379 static void __profile_entry_list(DBusMessageIter *iter, void *arg)
269 { 380 {
270 struct connman_profile *profile = arg; 381 struct connman_profile *profile = arg;
271 GKeyFile *keyfile; 382 GKeyFile *keyfile;
272 gchar **groups; 383 gchar **groups;
273 int i; 384 int i;
274 385
275 _DBG_PROFILE("profile %p", profile); 386 _DBG_PROFILE("profile %p", profile);
276 387
277 » keyfile = __connman_storage_open(profile->ident); 388 » keyfile = __connman_storage_open(&profile->ident);
278 if (keyfile == NULL) 389 if (keyfile == NULL)
279 return; 390 return;
280 391
281 groups = g_key_file_get_groups(keyfile, NULL); 392 groups = g_key_file_get_groups(keyfile, NULL);
282 for (i = 0; groups[i] != NULL; i++) { 393 for (i = 0; groups[i] != NULL; i++) {
283 const char *gname = groups[i]; 394 const char *gname = groups[i];
284 switch (get_service_type(gname)) { 395 switch (get_service_type(gname)) {
285 case CONNMAN_SERVICE_TYPE_UNKNOWN: 396 case CONNMAN_SERVICE_TYPE_UNKNOWN:
286 case CONNMAN_SERVICE_TYPE_ETHERNET: 397 case CONNMAN_SERVICE_TYPE_ETHERNET:
287 break; 398 break;
288 case CONNMAN_SERVICE_TYPE_BLUETOOTH: 399 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
289 case CONNMAN_SERVICE_TYPE_WIMAX: 400 case CONNMAN_SERVICE_TYPE_WIMAX:
290 /* NB: don't care about these right now */ 401 /* NB: don't care about these right now */
291 break; 402 break;
292 case CONNMAN_SERVICE_TYPE_CELLULAR: 403 case CONNMAN_SERVICE_TYPE_CELLULAR:
293 case CONNMAN_SERVICE_TYPE_WIFI: 404 case CONNMAN_SERVICE_TYPE_WIFI:
294 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, 405 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
295 &gname); 406 &gname);
296 break; 407 break;
297 } 408 }
298 } 409 }
299 g_strfreev(groups); 410 g_strfreev(groups);
300 » __connman_storage_close(profile->ident, keyfile, FALSE); 411 » __connman_storage_close(&profile->ident, keyfile, FALSE);
301 } 412 }
302 413
303 static DBusMessage *get_properties(DBusConnection *conn, 414 static DBusMessage *get_properties(DBusConnection *conn,
304 DBusMessage *msg, void *data) 415 DBusMessage *msg, void *data)
305 { 416 {
306 struct connman_profile *profile = data; 417 struct connman_profile *profile = data;
307 DBusMessage *reply; 418 DBusMessage *reply;
308 DBusMessageIter array, dict; 419 DBusMessageIter array, dict;
309 420
310 _DBG_PROFILE("conn %p", conn); 421 _DBG_PROFILE("conn %p", conn);
311 422
312 reply = dbus_message_new_method_return(msg); 423 reply = dbus_message_new_method_return(msg);
313 if (reply == NULL) 424 if (reply == NULL)
314 return NULL; 425 return NULL;
315 426
316 dbus_message_iter_init_append(reply, &array); 427 dbus_message_iter_init_append(reply, &array);
317 428
318 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, 429 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
319 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 430 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
320 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING 431 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
321 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); 432 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
322 433
323 if (profile->name != NULL) 434 if (profile->name != NULL)
324 connman_dbus_dict_append_variant(&dict, "Name", 435 connman_dbus_dict_append_variant(&dict, "Name",
325 DBUS_TYPE_STRING, &profile->name); 436 DBUS_TYPE_STRING, &profile->name);
326 437
327 » connman_dbus_dict_append_variant(&dict, "OfflineMode", 438 » if (profile == default_profile)
328 » DBUS_TYPE_BOOLEAN, &profile->offlinemode); 439 » » connman_dbus_dict_append_variant(&dict, "OfflineMode",
440 » » DBUS_TYPE_BOOLEAN, &profile->offlinemode);
329 441
330 » connman_dbus_dict_append_variant_array(&dict, "Services", 442 » if (profile == active_profile())
331 » DBUS_TYPE_OBJECT_PATH, __connman_service_list, NULL); 443 » » connman_dbus_dict_append_variant_array(&dict, "Services",
444 » » DBUS_TYPE_OBJECT_PATH, __connman_service_list, NULL);
332 445
333 connman_dbus_dict_append_variant_array(&dict, "Entries", 446 connman_dbus_dict_append_variant_array(&dict, "Entries",
334 DBUS_TYPE_STRING, __profile_entry_list, profile); 447 DBUS_TYPE_STRING, __profile_entry_list, profile);
335 448
336 dbus_message_iter_close_container(&array, &dict); 449 dbus_message_iter_close_container(&array, &dict);
337 450
338 return reply; 451 return reply;
339 } 452 }
340 453
341 static DBusMessage *set_property(DBusConnection *conn, 454 static DBusMessage *set_property(DBusConnection *conn,
(...skipping 23 matching lines...) Expand all
365 const char *name; 478 const char *name;
366 479
367 if (type != DBUS_TYPE_STRING) 480 if (type != DBUS_TYPE_STRING)
368 return __connman_error_invalid_arguments(msg); 481 return __connman_error_invalid_arguments(msg);
369 482
370 dbus_message_iter_get_basic(&value, &name); 483 dbus_message_iter_get_basic(&value, &name);
371 484
372 g_free(profile->name); 485 g_free(profile->name);
373 profile->name = g_strdup(name); 486 profile->name = g_strdup(name);
374 487
375 » » if (profile->name != NULL) 488 » » if (profile->name != NULL) {
376 » » » name_changed(profile); 489 » » » connman_dbus_send_property_changed_variant(
377 490 » » » profile->path, CONNMAN_PROFILE_INTERFACE, "Name",
378 » » __connman_storage_save_profile(profile); 491 » » » DBUS_TYPE_STRING, &profile->name);
379 » } else if (g_str_equal(name, "OfflineMode") == TRUE) { 492 » » }
380 » » connman_bool_t offlinemode;
381
382 » » if (type != DBUS_TYPE_BOOLEAN)
383 » » » return __connman_error_invalid_arguments(msg);
384
385 » » dbus_message_iter_get_basic(&value, &offlinemode);
386
387 » » if (profile->offlinemode == offlinemode)
388 » » » return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
389
390 » » profile->offlinemode = offlinemode;
391 » » offlinemode_changed(profile);
392 493
393 __connman_storage_save_profile(profile); 494 __connman_storage_save_profile(profile);
394 } else 495 } else
395 return __connman_error_invalid_property(msg); 496 return __connman_error_invalid_property(msg);
396 497
397 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); 498 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
398 } 499 }
399 500
400 static DBusMessage *get_entry(DBusConnection *conn, 501 static DBusMessage *get_entry(DBusConnection *conn,
401 DBusMessage *msg, void *data) 502 DBusMessage *msg, void *data)
402 { 503 {
403 #define ADD_STR(name, val) do { \ 504 #define ADD_STR(name, val) do { \
404 connman_dbus_dict_append_variant(&dict, name, DBUS_TYPE_STRING, val); \ 505 connman_dbus_dict_append_variant(&dict, name, DBUS_TYPE_STRING, val); \
405 } while (0) 506 } while (0)
406 #define VAL_STR(name) do { \ 507 #define VAL_STR(name) do { \
407 val = g_key_file_get_string(keyfile, ident, name, NULL); \ 508 val = g_key_file_get_string(keyfile, ident, name, NULL); \
408 if (val != NULL) \ 509 if (val != NULL) \
409 ADD_STR(name, &val); \ 510 ADD_STR(name, &val); \
410 } while (0) 511 } while (0)
411 struct connman_profile *profile = data; 512 struct connman_profile *profile = data;
412 GKeyFile *keyfile; 513 GKeyFile *keyfile;
413 const char *ident, *val; 514 const char *ident, *val;
414 gchar **tokens; 515 gchar **tokens;
415 DBusMessageIter iter, array, dict; 516 DBusMessageIter iter, array, dict;
416 DBusMessage *reply; 517 DBusMessage *reply;
417 connman_bool_t autoconnect, hidden_ssid; 518 connman_bool_t autoconnect, hidden_ssid;
519 int len;
418 520
419 _DBG_PROFILE("profile %p", profile); 521 _DBG_PROFILE("profile %p", profile);
420 522
421 if (dbus_message_iter_init(msg, &iter) == FALSE) 523 if (dbus_message_iter_init(msg, &iter) == FALSE)
422 return __connman_error_invalid_arguments(msg); 524 return __connman_error_invalid_arguments(msg);
423 525
424 dbus_message_iter_get_basic(&iter, &ident); 526 dbus_message_iter_get_basic(&iter, &ident);
425 527
426 » keyfile = __connman_storage_open(profile->ident); 528 » keyfile = __connman_storage_open(&profile->ident);
427 if (keyfile == NULL) { 529 if (keyfile == NULL) {
428 » » _DBG_PROFILE("cannot open keyfile %s", profile->ident); 530 » » _DBG_PROFILE("cannot open keyfile %s:%s",
531 » » profile->ident.user, profile->ident.ident);
429 return __connman_error_not_found(msg); /* XXX */ 532 return __connman_error_not_found(msg); /* XXX */
430 } 533 }
431 534
432 if (g_key_file_has_group(keyfile, ident) == FALSE) { 535 if (g_key_file_has_group(keyfile, ident) == FALSE) {
433 _DBG_PROFILE("ident %s not found", ident); 536 _DBG_PROFILE("ident %s not found", ident);
434 » » __connman_storage_close(profile->ident, keyfile, FALSE); 537 » » __connman_storage_close(&profile->ident, keyfile, FALSE);
435 return __connman_error_not_found(msg); 538 return __connman_error_not_found(msg);
436 } 539 }
437 540
438 /* 541 /*
439 * Split group name into components; e.g. 542 * Split group name into components; e.g.
440 * <type>_<device>_<ssid>_<mode>_<security> for wifi 543 * <type>_<device>_<ssid>_<mode>_<security> for wifi
441 */ 544 */
442 tokens = g_strsplit(ident, "_", 0); 545 tokens = g_strsplit(ident, "_", 0);
443 » /* NB: tokens[0] is NULL if ident is "" */ 546 » len = g_strv_length(tokens);
444 » if (tokens == NULL || tokens[0] == NULL) { 547 » if (len < 2) {
445 » » _DBG_PROFILE("ident %s malformed", ident); 548 » » _DBG_PROFILE("ident %s malformed, len %d", ident, len);
446 » » __connman_storage_close(profile->ident, keyfile, FALSE); 549 » » g_strfreev(tokens);
550 » » __connman_storage_close(&profile->ident, keyfile, FALSE);
447 return __connman_error_invalid_arguments(msg); 551 return __connman_error_invalid_arguments(msg);
448 } 552 }
449 553
450 reply = dbus_message_new_method_return(msg); 554 reply = dbus_message_new_method_return(msg);
451 if (reply == NULL) { 555 if (reply == NULL) {
452 _DBG_PROFILE("cannot allocate reply"); 556 _DBG_PROFILE("cannot allocate reply");
453 g_strfreev(tokens); 557 g_strfreev(tokens);
454 » » __connman_storage_close(profile->ident, keyfile, FALSE); 558 » » __connman_storage_close(&profile->ident, keyfile, FALSE);
455 return NULL; 559 return NULL;
456 } 560 }
457 561
458 dbus_message_iter_init_append(reply, &array); 562 dbus_message_iter_init_append(reply, &array);
459 563
460 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, 564 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
461 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 565 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
462 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING 566 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
463 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); 567 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
464 568
465 val = tokens[0]; 569 val = tokens[0];
466 connman_dbus_dict_append_variant(&dict, "Type", DBUS_TYPE_STRING, &val); 570 connman_dbus_dict_append_variant(&dict, "Type", DBUS_TYPE_STRING, &val);
467 571
468 switch (__connman_service_string2type(val)) { 572 switch (__connman_service_string2type(val)) {
469 case CONNMAN_SERVICE_TYPE_WIFI: 573 case CONNMAN_SERVICE_TYPE_WIFI:
470 » » if (g_strv_length(tokens) != 5) { 574 » » if (len != 5 && len != 6) {
471 » » » /* TODO(sleffler) accept > 5? */ 575 » » » _DBG_PROFILE("bad token cnt %d for ident %s",
472 » » » _DBG_PROFILE("bad token cnt %d", g_strv_length(tokens)); 576 » » » len, ident);
473 break; 577 break;
474 } 578 }
475 val = tokens[3]; 579 val = tokens[3];
476 ADD_STR("Mode", &val); 580 ADD_STR("Mode", &val);
477 val = tokens[4]; 581 val = tokens[4];
582 /* NB: g_strsplit breaks 802_1x into 802+1x; restore */
583 if (g_strcmp0(val, "802") == 0)
584 val = "802_1x";
478 ADD_STR("Security", &val); 585 ADD_STR("Security", &val);
479 break; 586 break;
480 case CONNMAN_SERVICE_TYPE_CELLULAR: 587 case CONNMAN_SERVICE_TYPE_CELLULAR:
481 /* TODO(sleffler) extract cellular attributes */ 588 /* TODO(sleffler) extract cellular attributes */
482 break; 589 break;
483 default: 590 default:
484 break; 591 break;
485 } 592 }
486 593
487 /* NB: always set AutoConnect in reply */ 594 /* NB: always set AutoConnect in reply */
488 val = g_key_file_get_string(keyfile, ident, "AutoConnect", NULL); 595 val = g_key_file_get_string(keyfile, ident, "AutoConnect", NULL);
489 autoconnect = (g_strcmp0(val, "true") == 0 ? TRUE : FALSE); 596 autoconnect = (g_strcmp0(val, "true") == 0 ? TRUE : FALSE);
490 connman_dbus_dict_append_variant(&dict, "AutoConnect", 597 connman_dbus_dict_append_variant(&dict, "AutoConnect",
491 DBUS_TYPE_BOOLEAN, &autoconnect); 598 DBUS_TYPE_BOOLEAN, &autoconnect);
492 599
493 VAL_STR("Name"); 600 VAL_STR("Name");
494 VAL_STR("Passphrase"); 601 VAL_STR("Passphrase");
495 VAL_STR("Failure"); 602 VAL_STR("Failure");
496 VAL_STR("Modified"); 603 VAL_STR("Modified");
497 604
498 val = g_key_file_get_string(keyfile, ident, "WiFi.HiddenSSID", NULL); 605 val = g_key_file_get_string(keyfile, ident, "WiFi.HiddenSSID", NULL);
499 hidden_ssid = (g_strcmp0(val, "true") == 0 ? TRUE : FALSE); 606 hidden_ssid = (g_strcmp0(val, "true") == 0 ? TRUE : FALSE);
500 connman_dbus_dict_append_variant(&dict, "WiFi.HiddenSSID", 607 connman_dbus_dict_append_variant(&dict, "WiFi.HiddenSSID",
501 DBUS_TYPE_BOOLEAN, &hidden_ssid); 608 DBUS_TYPE_BOOLEAN, &hidden_ssid);
502 609
503 dbus_message_iter_close_container(&array, &dict); 610 dbus_message_iter_close_container(&array, &dict);
504 611
505 g_strfreev(tokens); 612 g_strfreev(tokens);
506 » __connman_storage_close(profile->ident, keyfile, FALSE); 613 » __connman_storage_close(&profile->ident, keyfile, FALSE);
507 614
508 return reply; 615 return reply;
509 #undef VAL_STR 616 #undef VAL_STR
510 #undef ADD_STR 617 #undef ADD_STR
511 } 618 }
512 619
513 static DBusMessage *delete_entry(DBusConnection *conn, 620 static DBusMessage *delete_entry(DBusConnection *conn,
514 DBusMessage *msg, void *data) 621 DBusMessage *msg, void *data)
515 { 622 {
516 struct connman_profile *profile = data; 623 struct connman_profile *profile = data;
517 DBusMessageIter iter; 624 DBusMessageIter iter;
518 const char *identifier; 625 const char *identifier;
519 struct connman_service *service; 626 struct connman_service *service;
520 GKeyFile *keyfile; 627 GKeyFile *keyfile;
521 gboolean status; 628 gboolean status;
522 629
523 » _DBG_PROFILE("profile %s", profile->ident); 630 » _DBG_PROFILE("profile %s:%s", profile->ident.user,
631 » profile->ident.ident);
524 632
525 if (dbus_message_iter_init(msg, &iter) == FALSE) 633 if (dbus_message_iter_init(msg, &iter) == FALSE)
526 return __connman_error_invalid_arguments(msg); 634 return __connman_error_invalid_arguments(msg);
527 635
528 dbus_message_iter_get_basic(&iter, &identifier); 636 dbus_message_iter_get_basic(&iter, &identifier);
529 637
530 if (__connman_security_check_privilege(msg, 638 if (__connman_security_check_privilege(msg,
531 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0) 639 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
532 return __connman_error_permission_denied(msg); 640 return __connman_error_permission_denied(msg);
533 641
534 service = __connman_service_lookup(identifier); 642 service = __connman_service_lookup(identifier);
535 if (service != NULL) { 643 if (service != NULL) {
536 /* NB: this does not remove the service */ 644 /* NB: this does not remove the service */
537 __connman_service_reset(service); 645 __connman_service_reset(service);
538 } 646 }
539 647
540 /* Remove directly from profile */ 648 /* Remove directly from profile */
541 » keyfile = __connman_storage_open(profile->ident); 649 » keyfile = __connman_storage_open(&profile->ident);
542 if (keyfile == NULL) { 650 if (keyfile == NULL) {
543 _DBG_PROFILE("cannot open key file"); 651 _DBG_PROFILE("cannot open key file");
544 return __connman_error_invalid_arguments(msg); 652 return __connman_error_invalid_arguments(msg);
545 } 653 }
546 654
547 status = g_key_file_remove_group(keyfile, identifier, NULL); 655 status = g_key_file_remove_group(keyfile, identifier, NULL);
548 » __connman_storage_close(profile->ident, keyfile, status); 656 » __connman_storage_close(&profile->ident, keyfile, status);
549 657
550 if (status == FALSE) { 658 if (status == FALSE) {
551 _DBG_PROFILE("cannot remove %s", identifier); 659 _DBG_PROFILE("cannot remove %s", identifier);
552 return __connman_error_not_found(msg); 660 return __connman_error_not_found(msg);
553 } 661 }
554 662
555 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); 663 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
556 } 664 }
557 665
558 static GDBusMethodTable profile_methods[] = { 666 static GDBusMethodTable profile_methods[] = {
559 { "GetProperties", "", "a{sv}", get_properties }, 667 { "GetProperties", "", "a{sv}", get_properties },
560 { "SetProperty", "sv", "", set_property }, 668 { "SetProperty", "sv", "", set_property },
561 { "GetEntry", "s", "a{sv}", get_entry }, 669 { "GetEntry", "s", "a{sv}", get_entry },
562 { "DeleteEntry", "s", "", delete_entry }, 670 { "DeleteEntry", "s", "", delete_entry },
563 { }, 671 { },
564 }; 672 };
565 673
566 static GDBusSignalTable profile_signals[] = { 674 static GDBusSignalTable profile_signals[] = {
567 { "PropertyChanged", "sv" }, 675 { "PropertyChanged", "sv" },
568 { }, 676 { },
569 }; 677 };
570 678
679 static void free_ident(struct connman_storage_ident *ident)
680 {
681 g_free(ident->user);
682 g_free(ident->ident);
683 }
684
571 static void free_profile(struct connman_profile *profile) 685 static void free_profile(struct connman_profile *profile)
572 { 686 {
687 free_ident(&profile->ident);
688 g_free(profile->path);
573 g_free(profile->name); 689 g_free(profile->name);
574 g_free(profile->path);
575 g_free(profile->ident);
576 g_free(profile); 690 g_free(profile);
577 } 691 }
578 692
579 static void unregister_profile(gpointer data) 693 static void unregister_profile(gpointer data)
580 { 694 {
581 struct connman_profile *profile = data; 695 struct connman_profile *profile = data;
582 696
583 _DBG_PROFILE("profile %p", profile); 697 _DBG_PROFILE("profile %p", profile);
584 698
585 » connman_info("Removing profile %s", profile->ident); 699 » connman_info("Remove profile %s:%s", profile->ident.user,
700 » profile->ident.ident);
586 701
587 g_dbus_unregister_interface(connection, profile->path, 702 g_dbus_unregister_interface(connection, profile->path,
588 CONNMAN_PROFILE_INTERFACE); 703 CONNMAN_PROFILE_INTERFACE);
589 704
590 » if (g_strcmp0(profile->ident, PROFILE_DEFAULT_IDENT) == 0) 705 » if (profile == default_profile)
591 default_profile = NULL; 706 default_profile = NULL;
592 707
593 free_profile(profile); 708 free_profile(profile);
594 } 709 }
595 710
596 static int create_profile(const char *ident, const char *name, 711 static char *getpath(const struct connman_storage_ident *ident)
597 » » » » » » » const char **path) 712 {
713 » if (ident->user != NULL) {
714 » » /* NB: check for two tokens done in validate_ident */
715 » » return g_strdup_printf("/profile/%s/%s",
716 » » ident->user, ident->ident);
717 » } else
718 » » return g_strdup_printf("/profile/%s", ident->ident);
719 }
720
721 /*
722 * Create an in-memory profile using the specified identifier
723 * and name. The object path and a reference to the profile
724 * data structure are returned on success.
725 */
726 static int create_profile(struct connman_storage_ident *ident,
727 const char *name, const char **path, struct connman_profile **pprofile)
598 { 728 {
599 struct connman_profile *profile; 729 struct connman_profile *profile;
600 730
601 » _DBG_PROFILE("ident %s name %s", ident, name); 731 » _DBG_PROFILE("ident %s:%s name %s", ident->user, ident->ident, name);
602 732
603 profile = g_try_new0(struct connman_profile, 1); 733 profile = g_try_new0(struct connman_profile, 1);
604 » if (profile == NULL) 734 » if (profile == NULL) {
735 » » free_ident(ident);
605 return -ENOMEM; 736 return -ENOMEM;
737 }
606 738
607 » profile->ident = g_strdup(ident); 739 » profile->ident = *ident;
608 » profile->path = g_strdup_printf("/profile/%s", ident); 740 » profile->path = getpath(ident);
609 741 » /* TODO(sleffler) check ident.user */
610 » if (profile->ident == NULL || profile->path == NULL) { 742 » if (profile->ident.ident == NULL || profile->path == NULL) {
611 free_profile(profile); 743 free_profile(profile);
612 return -ENOMEM; 744 return -ENOMEM;
613 } 745 }
614 746
615 if (g_hash_table_lookup(profile_hash, profile->path) != NULL) { 747 if (g_hash_table_lookup(profile_hash, profile->path) != NULL) {
616 free_profile(profile); 748 free_profile(profile);
617 return -EEXIST; 749 return -EEXIST;
618 } 750 }
619 751
620 profile->name = g_strdup(name); 752 profile->name = g_strdup(name);
621 753
622 __connman_storage_load_profile(profile); 754 __connman_storage_load_profile(profile);
623 755
624 g_hash_table_insert(profile_hash, g_strdup(profile->path), profile); 756 g_hash_table_insert(profile_hash, g_strdup(profile->path), profile);
625 757
626 » connman_info("Adding profile %s", ident); 758 » connman_info("Add profile %s:%s", ident->user, ident->ident);
627 759
628 » if (g_strcmp0(ident, PROFILE_DEFAULT_IDENT) == 0) 760 » if (ident_equal(ident, &default_ident))
629 default_profile = profile; 761 default_profile = profile;
630 762
631 g_dbus_register_interface(connection, profile->path, 763 g_dbus_register_interface(connection, profile->path,
632 CONNMAN_PROFILE_INTERFACE, 764 CONNMAN_PROFILE_INTERFACE,
633 profile_methods, profile_signals, 765 profile_methods, profile_signals,
634 NULL, profile, NULL); 766 NULL, profile, NULL);
635 767
636 if (path != NULL) 768 if (path != NULL)
637 *path = profile->path; 769 *path = profile->path;
638 770
639 _DBG_PROFILE("profile %p path %s", profile, profile->path); 771 _DBG_PROFILE("profile %p path %s", profile, profile->path);
640 772
773 *pprofile = profile;
641 return 0; 774 return 0;
642 } 775 }
643 776
644 static gboolean validate_ident(const char *ident) 777 /*
778 * Check a profile identifier token. This must be non-null and
779 * made up of alpha-numeric chars suitable for use in a D-bus
780 * object path.
781 */
782 static gboolean validate_token(const char *ident)
645 { 783 {
646 unsigned int i; 784 unsigned int i;
647 unsigned int len = strlen(ident); 785 unsigned int len = strlen(ident);
648 786
649 if (len < 1) 787 if (len < 1)
650 return FALSE; 788 return FALSE;
651 789
652 for (i = 0; i < len; i++) { 790 for (i = 0; i < len; i++) {
653 if (ident[i] >= '0' && ident[i] <= '9') 791 if (ident[i] >= '0' && ident[i] <= '9')
654 continue; 792 continue;
655 if (ident[i] >= 'a' && ident[i] <= 'z') 793 if (ident[i] >= 'a' && ident[i] <= 'z')
656 continue; 794 continue;
657 if (ident[i] >= 'A' && ident[i] <= 'Z') 795 if (ident[i] >= 'A' && ident[i] <= 'Z')
658 continue; 796 continue;
659 return FALSE; 797 return FALSE;
660 } 798 }
661 799
662 return TRUE; 800 return TRUE;
663 } 801 }
664 802
803 /*
804 * Validate the profile identifier. It must be suitable
805 * for use in a D-Bus object path and, optionally, be of
806 * the form ~user/ident to signify a per-user profile.
807 */
808 static gboolean parse_ident(const char *str,
809 struct connman_storage_ident *ident)
810 {
811 gboolean is_valid;
812
813 if (str[0] == '~') {
814 /* syntax is ~user/name for profile in cryptohome */
815 gchar **tokens = g_strsplit_set(str, "~/", 4);
816 if (g_strv_length(tokens) == 3) {
817 is_valid = (validate_token(tokens[1]) == TRUE &&
818 validate_token(tokens[2]) == TRUE);
819 if (is_valid) {
820 ident->user = g_strdup(tokens[1]);
821 ident->ident = g_strdup(tokens[2]);
822 }
823 } else
824 is_valid = FALSE;
825 g_strfreev(tokens);
826 } else {
827 is_valid = validate_token(str);
828 if (is_valid) {
829 ident->user = NULL;
830 ident->ident = g_strdup(str);
831 }
832 }
833 return is_valid;
834 }
835
836 /*
837 * Lookup a profile on the stack by object path.
838 */
839 static struct connman_profile *lookup_stack_by_path(const char *path)
840 {
841 int i;
842
843 for (i = cur_profile; i >= 0; i--)
844 if (g_strcmp0(profile_stack[i]->path, path) == 0)
845 return profile_stack[i];
846 return NULL;
847 }
848
849 /*
850 * Push a profile on the stack and make it the ``active profile''.
851 * The profile may be currently registered in memory or previously
852 * created by CreateProfile. The profile may not already be on
853 * the stack.
854 */
855 int __connman_profile_push(const char *ident, const char *name,
856 const char **path)
857 {
858 struct connman_profile *profile;
859 struct connman_storage_ident sid;
860 char *tmp_path;
861 int err;
862
863 _DBG_PROFILE("ident %s name %s", ident, name);
864
865 if (parse_ident(ident, &sid) == FALSE) {
866 connman_error("%s: invalid profile name %s", __func__, ident);
867 return -EINVAL;
868 }
869
870 if (cur_profile+1 >= PROFILE_MAX) {
871 connman_error("%s: too many profiles (max %d)", __func__,
872 PROFILE_MAX);
873 free_ident(&sid);
874 return -EMFILE;
875 }
876
877 /*
878 * Check for in-memory profile by way of a CreateProfile request.
879 */
880 tmp_path = getpath(&sid);
881 if (tmp_path == NULL) {
882 connman_error("%s: no memory for %s", __func__, ident);
883 free_ident(&sid);
884 return -ENOMEM;
885 }
886
887 profile = g_hash_table_lookup(profile_hash, tmp_path);
888 g_free(tmp_path);
889 if (profile == NULL) {
890 /*
891 * Not in memory; accept an existing file.
892 */
893 if (__connman_storage_exists(&sid) == FALSE) {
894 connman_error("%s: profile %s does not exist",
895 __func__, ident);
896 free_ident(&sid);
897 return -ENOENT;
898 }
899
900 err = create_profile(&sid, name, path, &profile);
901 if (err < 0) {
902 connman_error("%s: cannot open, error %d",
903 __func__, err);
904 /* NB: create_profile reclaims sid */
905 return err;
906 }
907 } else {
908 free_ident(&sid); /* NB: not needed below */
909 /*
910 * Check this profile is not already on the stack.
911 */
912 if (lookup_stack_by_path(profile->path) != NULL) {
913 connman_error("%s: already pushed", __func__);
914 return -EEXIST;
915 }
916 *path = profile->path;
917 }
918
919 profile_stack[++cur_profile] = profile;
920
921 profiles_changed();
922
923 return 0;
924 }
925
926 /*
927 * Pop the profile from the top of the stack and remove it from
928 * the in-memory table. Any associated services are invalidated
929 * (credentials revoked and connections closed). After a pop we
930 * generate a PropertyChanged signal for Manager.Profiles.
931 *
932 * An optional identifier may be specified. If specified it is
933 * checked against the active profile and if not the same then
934 * the request is rejected. This is useful to ensure the right
935 * profile is pop'd (as might happen on logout if an associated
936 * push failed for some reason).
937 */
938 int __connman_profile_pop(const char *ident)
939 {
940 struct connman_profile *profile;
941
942 _DBG_PROFILE("ident %s", ident);
943
944 if (cur_profile < 0) {
945 connman_error("%s: profile stack empty", __func__);
946 return -EINVAL;
947 }
948
949 profile = profile_stack[cur_profile];
950
951 if (ident != NULL) {
952 struct connman_storage_ident sid;
953
954 if (parse_ident(ident, &sid) == FALSE) {
955 connman_error("%s: invalid profile name %s",
956 __func__, ident);
957 return -EINVAL;
958 }
959 if (ident_equal(&profile->ident, &sid) == FALSE) {
960 connman_error("%s: %s is not the active profile",
961 __func__, ident);
962 free_ident(&sid);
963 return -ENXIO;
964 }
965 free_ident(&sid);
966 }
967
968 __connman_service_invalidate_profile(&profile->ident);
969
970 g_hash_table_remove(profile_hash, profile->path);
971 cur_profile--;
972
973 profiles_changed();
974
975 return 0;
976 }
977
978 /*
979 * Create a profile file and register it in memory. The
980 * file is created with minimal contents.
981 * TODO(sleffler) disallow overwriting an existing file?
982 */
665 int __connman_profile_create(const char *name, const char **path) 983 int __connman_profile_create(const char *name, const char **path)
666 { 984 {
667 struct connman_profile *profile; 985 struct connman_profile *profile;
986 struct connman_storage_ident sid;
668 int err; 987 int err;
669 988
670 _DBG_PROFILE("name %s", name); 989 _DBG_PROFILE("name %s", name);
671 990
672 » if (validate_ident(name) == FALSE) 991 » if (parse_ident(name, &sid) == FALSE) {
673 » » return -EINVAL; 992 » » connman_error("%s: invalid profile name %s)", __func__, name);
674 993 » » return -EINVAL;
675 » err = create_profile(name, NULL, path); 994 » }
676 » if (err < 0) 995
996 » err = create_profile(&sid, NULL, path, &profile);
997 » if (err < 0) {
998 » » connman_error("%s: cannot open, error %d", __func__, err);
999 » » /* NB: create_profile reclaims sid */
677 return err; 1000 return err;
678 1001 » }
679 » profile = g_hash_table_lookup(profile_hash, *path);
680 » if (profile == NULL)
681 » » return -EIO;
682 1002
683 __connman_storage_save_profile(profile); 1003 __connman_storage_save_profile(profile);
684 1004
685 profiles_changed(); 1005 profiles_changed();
686 1006
687 return 0; 1007 return 0;
688 } 1008 }
689 1009
1010 /*
1011 * Delete a profile and remove from memory. The default
1012 * profile may not be removed/deleted. Likewise, one
1013 * cannot remove a profile pushed on the stack.
1014 */
690 int __connman_profile_remove(const char *path) 1015 int __connman_profile_remove(const char *path)
691 { 1016 {
692 struct connman_profile *profile; 1017 struct connman_profile *profile;
693 1018
694 _DBG_PROFILE("path %s", path); 1019 _DBG_PROFILE("path %s", path);
695 1020
696 if (default_profile != NULL && 1021 if (default_profile != NULL &&
697 » » » » g_strcmp0(path, default_profile->path) == 0) 1022 » g_strcmp0(path, default_profile->path) == 0) {
698 » » return -EINVAL; 1023 » » connman_error("%s: cannot delete default profile", __func__);
1024 » » return -EINVAL;
1025 » }
699 1026
700 profile = g_hash_table_lookup(profile_hash, path); 1027 profile = g_hash_table_lookup(profile_hash, path);
701 » if (profile == NULL) 1028 » if (profile == NULL) {
1029 » » connman_error("%s: %s is not a registered profile",
1030 » » __func__, path);
702 return -ENXIO; 1031 return -ENXIO;
703 1032 » }
704 » __connman_storage_delete(profile->ident); 1033
705 1034 » if (lookup_stack_by_path(profile->path) != NULL) {
706 » g_hash_table_remove(profile_hash, path); 1035 » » connman_error("%s: disallowed, on stack", __func__);
707 1036 » » return -EEXIST;
708 » profiles_changed(); 1037 » }
709 1038
710 » return 0; 1039 » __connman_storage_delete(&profile->ident);
711 } 1040
712 1041 » g_hash_table_remove(profile_hash, profile->path);
1042
1043 » profiles_changed();
1044
1045 » return 0;
1046 }
1047
1048 /*
1049 * Initialize the profile stack by pushing the default
1050 * (global) profile. Unlike connman we do not read in
1051 * all available .profile's in the global dir.
1052 */
713 static int profile_init(void) 1053 static int profile_init(void)
714 { 1054 {
715 » GDir *dir; 1055 » struct connman_profile *profile;
716 » const gchar *file; 1056 » int err;
717 1057
718 » _DBG_PROFILE(""); 1058 » err = create_profile(&default_ident, "Default", NULL, &profile);
719 1059 » if (err == 0)
720 » dir = g_dir_open(STORAGEDIR, 0, NULL); 1060 » » profile_stack[++cur_profile] = profile;
721 » if (dir != NULL) { 1061 » return err;
722 » » while ((file = g_dir_read_name(dir)) != NULL) {
723 » » » GString *str;
724 » » » gchar *ident;
725
726 » » » if (g_str_has_suffix(file, ".profile") == FALSE)
727 » » » » continue;
728
729 » » » ident = g_strrstr(file, ".profile");
730 » » » if (ident == NULL)
731 » » » » continue;
732
733 » » » str = g_string_new_len(file, ident - file);
734 » » » if (str == NULL)
735 » » » » continue;
736
737 » » » ident = g_string_free(str, FALSE);
738
739 » » » if (validate_ident(ident) == TRUE)
740 » » » » create_profile(ident, NULL, NULL);
741
742 » » » g_free(ident);
743 » » }
744
745 » » g_dir_close(dir);
746 » }
747
748 » if (g_hash_table_size(profile_hash) == 0)
749 » » create_profile(PROFILE_DEFAULT_IDENT, "Default", NULL);
750
751 » profiles_changed();
752
753 » return 0;
754 } 1062 }
755 1063
756 static int profile_load(struct connman_profile *profile) 1064 static int profile_load(struct connman_profile *profile)
757 { 1065 {
758 GKeyFile *keyfile; 1066 GKeyFile *keyfile;
759 GError *error = NULL; 1067 GError *error = NULL;
760 connman_bool_t offlinemode; 1068 connman_bool_t offlinemode;
761 char *name; 1069 char *name;
762 1070
763 _DBG_PROFILE("profile %p", profile); 1071 _DBG_PROFILE("profile %p", profile);
764 1072
765 » keyfile = __connman_storage_open(profile->ident); 1073 » keyfile = __connman_storage_open(&profile->ident);
766 if (keyfile == NULL) 1074 if (keyfile == NULL)
767 return -EIO; 1075 return -EIO;
768 1076
769 name = g_key_file_get_string(keyfile, "global", "Name", NULL); 1077 name = g_key_file_get_string(keyfile, "global", "Name", NULL);
770 if (name != NULL) { 1078 if (name != NULL) {
771 g_free(profile->name); 1079 g_free(profile->name);
772 profile->name = name; 1080 profile->name = name;
773 } 1081 }
774 1082
775 offlinemode = g_key_file_get_boolean(keyfile, "global", 1083 offlinemode = g_key_file_get_boolean(keyfile, "global",
776 "OfflineMode", &error); 1084 "OfflineMode", &error);
777 if (error == NULL) 1085 if (error == NULL)
778 profile->offlinemode = offlinemode; 1086 profile->offlinemode = offlinemode;
779 g_clear_error(&error); 1087 g_clear_error(&error);
780 1088
781 » __connman_storage_close(profile->ident, keyfile, FALSE); 1089 » __connman_storage_close(&profile->ident, keyfile, FALSE);
782 1090
783 return 0; 1091 return 0;
784 } 1092 }
785 1093
786 static int profile_save(struct connman_profile *profile) 1094 static int profile_save(struct connman_profile *profile)
787 { 1095 {
788 GKeyFile *keyfile; 1096 GKeyFile *keyfile;
789 1097
790 _DBG_PROFILE("profile %p", profile); 1098 _DBG_PROFILE("profile %p", profile);
791 1099
792 » keyfile = __connman_storage_open(profile->ident); 1100 » keyfile = __connman_storage_open(&profile->ident);
793 if (keyfile == NULL) 1101 if (keyfile == NULL)
794 return -EIO; 1102 return -EIO;
795 1103
796 if (profile->name != NULL) 1104 if (profile->name != NULL)
797 g_key_file_set_string(keyfile, "global", 1105 g_key_file_set_string(keyfile, "global",
798 "Name", profile->name); 1106 "Name", profile->name);
799 1107
800 g_key_file_set_boolean(keyfile, "global", 1108 g_key_file_set_boolean(keyfile, "global",
801 "OfflineMode", profile->offlinemode); 1109 "OfflineMode", profile->offlinemode);
802 1110
803 » __connman_storage_close(profile->ident, keyfile, TRUE); 1111 » __connman_storage_close(&profile->ident, keyfile, TRUE);
804 1112
805 return 0; 1113 return 0;
806 } 1114 }
807 1115
808 static struct connman_storage profile_storage = { 1116 static struct connman_storage profile_storage = {
809 .name = "profile", 1117 .name = "profile",
810 .priority = CONNMAN_STORAGE_PRIORITY_LOW, 1118 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
811 .profile_init = profile_init, 1119 .profile_init = profile_init,
812 .profile_load = profile_load, 1120 .profile_load = profile_load,
813 .profile_save = profile_save, 1121 .profile_save = profile_save,
(...skipping 19 matching lines...) Expand all
833 void __connman_profile_cleanup(void) 1141 void __connman_profile_cleanup(void)
834 { 1142 {
835 _DBG_PROFILE(""); 1143 _DBG_PROFILE("");
836 1144
837 if (connection == NULL) 1145 if (connection == NULL)
838 return; 1146 return;
839 1147
840 g_hash_table_destroy(profile_hash); 1148 g_hash_table_destroy(profile_hash);
841 profile_hash = NULL; 1149 profile_hash = NULL;
842 1150
1151 cur_profile = -1;
1152 default_profile = NULL;
1153
843 connman_storage_unregister(&profile_storage); 1154 connman_storage_unregister(&profile_storage);
844 1155
845 dbus_connection_unref(connection); 1156 dbus_connection_unref(connection);
846 } 1157 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698