~cyphermox/ubuntu/natty/connman/release-0.64

« back to all changes in this revision

Viewing changes to src/provider.c

  • Committer: Mathieu Trudel-Lapierre
  • Date: 2010-11-30 15:51:10 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: mathieu.trudel-lapierre@canonical.com-20101130155110-32g0usyc4jbl131x
New upstream release 0.64.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 
38
38
struct connman_provider {
39
39
        struct connman_element element;
 
40
        struct connman_service *vpn_service;
40
41
        char *identifier;
41
 
        char *path;
42
 
        enum connman_provider_state state;
43
 
        enum connman_provider_error error;
44
42
        char *name;
45
43
        char *type;
 
44
        char *host;
46
45
        char *dns;
47
46
        char *domain;
48
 
        DBusMessage *pending;
49
 
        guint timeout;
50
47
        struct connman_provider_driver *driver;
51
48
        void *driver_data;
52
49
};
53
50
 
54
 
static const char *state2string(enum connman_provider_state state)
55
 
{
56
 
        switch (state) {
57
 
        case CONNMAN_PROVIDER_STATE_UNKNOWN:
58
 
                break;
59
 
        case CONNMAN_PROVIDER_STATE_IDLE:
60
 
                return "idle";
61
 
        case CONNMAN_PROVIDER_STATE_CONNECT:
62
 
                return "connect";
63
 
        case CONNMAN_PROVIDER_STATE_READY:
64
 
                return "ready";
65
 
        case CONNMAN_PROVIDER_STATE_DISCONNECT:
66
 
                return "disconnect";
67
 
        case CONNMAN_PROVIDER_STATE_FAILURE:
68
 
                return "failure";
69
 
        }
70
 
        return NULL;
71
 
}
72
 
 
73
 
static const char *error2string(enum connman_provider_error error)
74
 
{
75
 
        switch (error) {
76
 
        case CONNMAN_PROVIDER_ERROR_UNKNOWN:
77
 
                break;
78
 
        case CONNMAN_PROVIDER_ERROR_CONNECT_FAILED:
79
 
                return "connect-failed";
80
 
        }
81
 
 
82
 
        return NULL;
83
 
}
84
 
 
85
 
static void append_path(gpointer key, gpointer value, gpointer user_data)
86
 
{
87
 
        struct connman_provider *provider = value;
88
 
        DBusMessageIter *iter = user_data;
89
 
 
90
 
        DBG("add provider path");
91
 
        if (provider->path == NULL)
92
 
                return;
93
 
 
94
 
        dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
95
 
                                        &provider->path);
96
 
}
97
 
 
98
 
void __connman_provider_list(DBusMessageIter *iter, void *user_data)
99
 
{
100
 
        g_hash_table_foreach(provider_hash, append_path, iter);
 
51
void __connman_provider_append_properties(struct connman_provider *provider,
 
52
                                                        DBusMessageIter *iter)
 
53
{
 
54
        if (provider->host != NULL)
 
55
                connman_dbus_dict_append_basic(iter, "Host",
 
56
                                        DBUS_TYPE_STRING, &provider->host);
 
57
 
 
58
        if (provider->domain != NULL)
 
59
                connman_dbus_dict_append_basic(iter, "Domain",
 
60
                                        DBUS_TYPE_STRING, &provider->domain);
 
61
 
 
62
        if (provider->type != NULL)
 
63
                connman_dbus_dict_append_basic(iter, "Type", DBUS_TYPE_STRING,
 
64
                                                 &provider->type);
101
65
}
102
66
 
103
67
static struct connman_provider *connman_provider_lookup(const char *identifier)
109
73
        return provider;
110
74
}
111
75
 
112
 
static void connman_provider_setup_vpn_ipv4(struct connman_provider *provider,
 
76
static int connman_provider_setup_vpn_ipv4(struct connman_provider *provider,
113
77
                                                struct connman_element *element)
114
78
{
115
79
        if (element == NULL || provider == NULL)
116
 
                return;
 
80
                return -EINVAL;
117
81
 
118
82
        DBG("set vpn type %d", element->type);
119
83
 
120
 
        if (provider == NULL)
121
 
                return;
122
 
 
123
84
        g_free(element->ipv4.address);
124
85
        element->ipv4.address = g_strdup(provider->element.ipv4.address);
125
86
 
 
87
        g_free(element->ipv4.peer);
 
88
        element->ipv4.peer = g_strdup(provider->element.ipv4.peer);
 
89
 
126
90
        g_free(element->ipv4.netmask);
127
91
        element->ipv4.netmask = g_strdup(provider->element.ipv4.netmask);
128
92
 
135
99
        g_free(element->ipv4.pac);
136
100
        element->ipv4.pac = g_strdup(provider->element.ipv4.pac);
137
101
 
138
 
        DBG("VPN exist");
 
102
        return connman_element_register(element, &provider->element);
139
103
}
140
104
 
141
105
struct connman_provider *connman_provider_ref(struct connman_provider *provider)
142
106
{
 
107
        DBG("provider %p", provider);
 
108
 
143
109
        if (connman_element_ref(&provider->element) == NULL)
144
110
                return NULL;
145
111
 
148
114
 
149
115
void connman_provider_unref(struct connman_provider *provider)
150
116
{
 
117
        DBG("provider %p", provider);
 
118
 
151
119
        connman_element_unref(&provider->element);
152
120
}
153
121
 
189
157
        return 0;
190
158
}
191
159
 
192
 
static void state_changed(struct connman_provider *provider)
193
 
{
194
 
        const char *str;
195
 
 
196
 
        str = state2string(provider->state);
197
 
        if (str == NULL)
198
 
                return;
199
 
 
200
 
        connman_dbus_property_changed_basic(provider->path,
201
 
                                CONNMAN_PROVIDER_INTERFACE, "State",
202
 
                                                DBUS_TYPE_STRING, &str); 
203
 
}
204
 
 
205
 
static void reply_pending(struct connman_provider *provider, int error)
206
 
{
207
 
        if (provider->timeout > 0) {
208
 
                g_source_remove(provider->timeout);
209
 
                provider->timeout = 0;
210
 
        }
211
 
 
212
 
        if (provider->pending != NULL) {
213
 
                if (error > 0) {
214
 
                        DBusMessage *reply;
215
 
 
216
 
                        reply = __connman_error_failed(provider->pending,
217
 
                                                                error);
218
 
                        if (reply != NULL)
219
 
                                g_dbus_send_message(connection, reply);
220
 
                } else
221
 
                        g_dbus_send_reply(connection, provider->pending,
222
 
                                                        DBUS_TYPE_INVALID);
223
 
 
224
 
                dbus_message_unref(provider->pending);
225
 
                provider->pending = NULL;
226
 
        }
227
 
}
228
 
 
229
 
static int connman_provider_disconnect(struct connman_provider *provider)
 
160
int __connman_provider_disconnect(struct connman_provider *provider)
230
161
{
231
162
        int err;
232
163
 
233
164
        DBG("provider %p", provider);
234
165
 
235
 
        reply_pending(provider, ECONNABORTED);
236
 
 
237
166
        if (provider->driver != NULL && provider->driver->disconnect != NULL)
238
167
                err = provider->driver->disconnect(provider);
239
168
        else
240
169
                return -EOPNOTSUPP;
241
170
 
242
 
        __connman_provider_indicate_state(provider,
243
 
                                        CONNMAN_PROVIDER_STATE_DISCONNECT);
 
171
        if (provider->vpn_service != NULL)
 
172
                __connman_service_indicate_state(provider->vpn_service,
 
173
                                        CONNMAN_SERVICE_STATE_DISCONNECT);
244
174
        if (err < 0) {
245
175
                if (err != -EINPROGRESS)
246
176
                        return err;
251
181
        return 0;
252
182
}
253
183
 
254
 
int __connman_provider_indicate_state(struct connman_provider *provider,
255
 
                                        enum connman_provider_state state)
256
 
{
257
 
        DBG("provider %p state %d", provider, state);
258
 
 
259
 
        if (provider == NULL)
260
 
                return -EINVAL;
261
 
 
262
 
        if (provider->state == state)
263
 
                return -EALREADY;
264
 
 
265
 
        if (provider->state == CONNMAN_PROVIDER_STATE_FAILURE &&
266
 
                                state == CONNMAN_PROVIDER_STATE_IDLE)
267
 
                return -EINVAL;
268
 
 
269
 
        if (provider->state == CONNMAN_PROVIDER_STATE_IDLE &&
270
 
                                state == CONNMAN_PROVIDER_STATE_DISCONNECT)
271
 
                return -EINVAL;
272
 
 
273
 
        if (state == CONNMAN_PROVIDER_STATE_IDLE &&
274
 
                        provider->state != CONNMAN_PROVIDER_STATE_DISCONNECT) {
275
 
                provider->state = CONNMAN_PROVIDER_STATE_DISCONNECT;
276
 
                state_changed(provider);
277
 
 
278
 
                connman_provider_disconnect(provider);
279
 
        }
280
 
 
281
 
        provider->state = state;
282
 
        state_changed(provider);
283
 
 
284
 
        if (state == CONNMAN_PROVIDER_STATE_READY)
285
 
                reply_pending(provider, 0);
286
 
 
287
 
        if (state == CONNMAN_PROVIDER_STATE_FAILURE)
288
 
                reply_pending(provider, EIO);
289
 
        else
290
 
                provider->error = CONNMAN_PROVIDER_ERROR_UNKNOWN;
291
 
 
292
 
        return 0;
293
 
}
294
 
 
295
 
int __connman_provider_indicate_error(struct connman_provider *provider,
296
 
                                      enum connman_provider_error error)
297
 
{
298
 
        DBG("provider %p error %d", provider, error);
299
 
 
300
 
        if (provider == NULL)
301
 
                return -EINVAL;
302
 
 
303
 
        provider->error = error;
304
 
 
305
 
        return __connman_provider_indicate_state(provider,
306
 
                                        CONNMAN_PROVIDER_STATE_FAILURE);
307
 
}
308
 
 
309
 
static gboolean connect_timeout(gpointer user_data)
310
 
{
311
 
        struct connman_provider *provider = user_data;
312
 
 
313
 
        DBG("provider %p", provider);
314
 
 
315
 
        provider->timeout = 0;
316
 
 
317
 
        if (provider->pending != NULL) {
318
 
                DBusMessage *reply;
319
 
 
320
 
                reply = __connman_error_operation_timeout(provider->pending);
321
 
                if (reply != NULL)
322
 
                        g_dbus_send_message(connection, reply);
323
 
 
324
 
                dbus_message_unref(provider->pending);
325
 
                provider->pending = NULL;
326
 
        }
327
 
 
328
 
        __connman_provider_indicate_error(provider,
329
 
                                CONNMAN_PROVIDER_ERROR_CONNECT_FAILED);
330
 
 
331
 
        return FALSE;
332
 
}
333
 
 
334
 
static connman_bool_t is_connecting(struct connman_provider *provider)
335
 
{
336
 
        switch (provider->state) {
337
 
        case CONNMAN_PROVIDER_STATE_UNKNOWN:
338
 
        case CONNMAN_PROVIDER_STATE_IDLE:
339
 
        case CONNMAN_PROVIDER_STATE_FAILURE:
340
 
        case CONNMAN_PROVIDER_STATE_DISCONNECT:
341
 
        case CONNMAN_PROVIDER_STATE_READY:
342
 
                break;
343
 
        case CONNMAN_PROVIDER_STATE_CONNECT:
344
 
                return TRUE;
345
 
        }
346
 
 
347
 
        return FALSE;
348
 
}
349
 
 
350
 
static int connman_provider_connect(struct connman_provider *provider)
 
184
int __connman_provider_connect(struct connman_provider *provider)
351
185
{
352
186
        int err;
353
187
 
354
188
        DBG("provider %p", provider);
355
189
 
356
 
        if (provider->state == CONNMAN_PROVIDER_STATE_READY)
357
 
                return -EISCONN;
358
 
 
359
 
        if (is_connecting(provider) == TRUE)
360
 
                return -EALREADY;
361
 
 
362
190
        g_free(provider->element.ipv4.address);
 
191
        g_free(provider->element.ipv4.peer);
363
192
        g_free(provider->element.ipv4.netmask);
364
193
        g_free(provider->element.ipv4.gateway);
365
194
        g_free(provider->element.ipv4.broadcast);
366
195
        g_free(provider->element.ipv4.pac);
367
196
 
368
197
        provider->element.ipv4.address = NULL;
 
198
        provider->element.ipv4.peer = NULL;
369
199
        provider->element.ipv4.netmask = NULL;
370
200
        provider->element.ipv4.gateway = NULL;
371
201
        provider->element.ipv4.broadcast = NULL;
380
210
                if (err != -EINPROGRESS)
381
211
                        return err;
382
212
 
383
 
                provider->timeout = g_timeout_add_seconds(60,
384
 
                                        connect_timeout, provider);
385
 
 
386
 
                __connman_provider_indicate_state(provider,
387
 
                                        CONNMAN_PROVIDER_STATE_CONNECT);
 
213
                __connman_service_indicate_state(provider->vpn_service,
 
214
                                        CONNMAN_SERVICE_STATE_ASSOCIATION);
388
215
                return -EINPROGRESS;
389
216
        }
390
217
 
394
221
int __connman_provider_remove(const char *path)
395
222
{
396
223
        struct connman_provider *provider;
 
224
        GHashTableIter iter;
 
225
        gpointer value, key;
397
226
 
398
227
        DBG("path %s", path);
399
228
 
400
 
        provider = g_hash_table_lookup(provider_hash, path);
401
 
        if (provider == NULL) {
402
 
                DBG("patch %s not found", path);
403
 
                return -ENXIO;
 
229
        g_hash_table_iter_init(&iter, provider_hash);
 
230
        while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
 
231
                const char *srv_path;
 
232
                provider = value;
 
233
 
 
234
                if (provider->vpn_service == NULL)
 
235
                        continue;
 
236
 
 
237
                srv_path = __connman_service_get_path(provider->vpn_service);
 
238
 
 
239
                if (g_strcmp0(srv_path, path) == 0) {
 
240
                        DBG("Removing VPN %s", provider->identifier);
 
241
                        g_hash_table_remove(provider_hash,
 
242
                                                provider->identifier);
 
243
                        return 0;
 
244
                }
404
245
        }
405
246
 
406
 
        g_hash_table_remove(provider_hash, path);
407
 
 
408
 
        return 0;
409
 
}
410
 
 
411
 
static DBusMessage *get_properties(DBusConnection *conn,
412
 
                                        DBusMessage *msg, void *user_data)
413
 
{
414
 
        struct connman_provider *provider = user_data;
415
 
        DBusMessage *reply;
416
 
        DBusMessageIter array, dict;
417
 
        dbus_bool_t required;
418
 
        const char *str;
419
 
 
420
 
        DBG("provider %p", provider);
421
 
 
422
 
        reply = dbus_message_new_method_return(msg);
423
 
        if (reply == NULL)
424
 
                return NULL;
425
 
 
426
 
        dbus_message_iter_init_append(reply, &array);
427
 
 
428
 
        connman_dbus_dict_open(&array, &dict);
429
 
 
430
 
        if (provider->name != NULL)
431
 
                connman_dbus_dict_append_basic(&dict, "Name",
432
 
                                        DBUS_TYPE_STRING, &provider->name);
433
 
 
434
 
        if (str != NULL)
435
 
                connman_dbus_dict_append_basic(&dict, "Type",
436
 
                                                 DBUS_TYPE_STRING,
437
 
                                                 &provider->type);
438
 
 
439
 
        str = state2string(provider->state);
440
 
        if (str != NULL)
441
 
                connman_dbus_dict_append_basic(&dict, "State",
442
 
                                                 DBUS_TYPE_STRING, &str);
443
 
 
444
 
        str = error2string(provider->error);
445
 
        if (str != NULL)
446
 
                connman_dbus_dict_append_basic(&dict, "Error",
447
 
                                                 DBUS_TYPE_STRING, &str);
448
 
 
449
 
        required = TRUE;
450
 
        connman_dbus_dict_append_basic(&dict, "PassphraseRequired",
451
 
                                         DBUS_TYPE_BOOLEAN, &required);
452
 
 
453
 
        connman_dbus_dict_close(&array, &dict);
454
 
 
455
 
        return reply;
456
 
}
457
 
 
458
 
static GDBusMethodTable provider_methods[] = {
459
 
        { "GetProperties", "", "a{sv}", get_properties },
460
 
        { },
461
 
};
462
 
 
463
 
static GDBusSignalTable provider_signals[] = {
464
 
        { "PropertyChanged", "sv" },
465
 
        { },
466
 
};
467
 
 
468
 
int connman_provider_set_connected(struct connman_provider *provider,
469
 
                                                connman_bool_t connected)
470
 
{
 
247
        return -ENXIO;
 
248
}
 
249
 
 
250
static int set_connected(struct connman_provider *provider,
 
251
                                        connman_bool_t connected)
 
252
{
 
253
        struct connman_service *service = provider->vpn_service;
 
254
 
 
255
        if (service == NULL)
 
256
                return -ENODEV;
 
257
 
471
258
        if (connected == TRUE) {
472
259
                enum connman_element_type type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
473
260
                struct connman_element *element;
 
261
                char *nameservers = NULL, *name = NULL;
 
262
                const char *value;
 
263
                char *second_ns;
 
264
                int err;
 
265
 
 
266
                __connman_service_indicate_state(provider->vpn_service,
 
267
                                        CONNMAN_SERVICE_STATE_CONFIGURATION);
474
268
 
475
269
                type = CONNMAN_ELEMENT_TYPE_IPV4;
476
270
 
477
271
                element = connman_element_create(NULL);
478
 
                if (element != NULL) {
479
 
                        element->type  = type;
480
 
                        element->index = provider->element.index;
481
 
 
482
 
                        connman_provider_setup_vpn_ipv4(provider, element);
483
 
 
484
 
                        if (connman_element_register(element,
485
 
                                        &provider->element) < 0)
486
 
                                connman_element_unref(element);
487
 
                        else {
488
 
                                char *nameservers = NULL;
489
 
                                const char *value;
490
 
                                char *name = NULL;
491
 
 
492
 
                                DBG("set dns");
493
 
                                nameservers = g_strdup(provider->dns);
494
 
                                value = nameservers;
495
 
                                name = connman_inet_ifname(
496
 
                                                provider->element.index);
497
 
                                while (value) {
498
 
                                        char *next = strchr(value, ' ');
499
 
                                        if (next)
500
 
                                                *(next++) = 0;
501
 
 
502
 
                                        connman_resolver_append(name,
503
 
                                                        provider->domain,
504
 
                                                        value);
505
 
                                        value = next;
506
 
                                }
507
 
                                DBG("free extra");
508
 
                                g_free(nameservers);
509
 
                                g_free(name);
510
 
                        }
511
 
 
512
 
                }
513
 
                __connman_provider_indicate_state(provider,
514
 
                                                  CONNMAN_PROVIDER_STATE_READY);
 
272
                if (element == NULL)
 
273
                        return -ENOMEM;
 
274
 
 
275
                element->type  = type;
 
276
                element->index = provider->element.index;
 
277
 
 
278
                err = connman_provider_setup_vpn_ipv4(provider, element);
 
279
                if (err < 0) {
 
280
                        connman_element_unref(element);
 
281
 
 
282
                        __connman_service_indicate_state(service,
 
283
                                                CONNMAN_SERVICE_STATE_FAILURE);
 
284
 
 
285
                        return err;
 
286
                }
 
287
 
 
288
                __connman_service_indicate_state(service,
 
289
                                                CONNMAN_SERVICE_STATE_READY);
 
290
 
 
291
                __connman_service_set_domainname(service, provider->domain);
 
292
 
 
293
                name = connman_inet_ifname(provider->element.index);
 
294
 
 
295
                nameservers = g_strdup(provider->dns);
 
296
                value = nameservers;
 
297
                second_ns = strchr(value, ' ');
 
298
                if (second_ns)
 
299
                        *(second_ns++) = 0;
 
300
                __connman_service_append_nameserver(service, value);
 
301
                value = second_ns;
 
302
 
 
303
                while (value) {
 
304
                        char *next = strchr(value, ' ');
 
305
                        if (next)
 
306
                                *(next++) = 0;
 
307
 
 
308
                        connman_resolver_append(name, provider->domain, value);
 
309
                        value = next;
 
310
                }
 
311
 
 
312
                g_free(nameservers);
 
313
                g_free(name);
 
314
 
515
315
        } else {
516
 
                reply_pending(provider, ECONNABORTED);
517
316
                connman_element_unregister_children(&provider->element);
518
 
                __connman_provider_indicate_state(provider,
519
 
                                        CONNMAN_PROVIDER_STATE_DISCONNECT);
 
317
                __connman_service_indicate_state(service,
 
318
                                                CONNMAN_SERVICE_STATE_IDLE);
520
319
        }
521
320
 
522
321
        return 0;
523
322
}
524
323
 
525
 
static void provider_free(gpointer user_data)
 
324
int connman_provider_set_state(struct connman_provider *provider,
 
325
                                        enum connman_provider_state state)
526
326
{
527
 
        struct connman_provider *provider = user_data;
528
 
        char *path = provider->path;
529
 
 
530
 
        DBG("provider %p", provider);
531
 
 
532
 
        reply_pending(provider, ENOENT);
533
 
        provider->path = NULL;
534
 
 
535
 
        if (path != NULL) {
536
 
                g_dbus_unregister_interface(connection, path,
537
 
                                                CONNMAN_PROVIDER_INTERFACE);
538
 
                g_free(path);
 
327
        if (provider == NULL || provider->vpn_service == NULL)
 
328
                return -EINVAL;
 
329
 
 
330
        switch (state) {
 
331
        case CONNMAN_PROVIDER_STATE_UNKNOWN:
 
332
                return -EINVAL;
 
333
        case CONNMAN_PROVIDER_STATE_IDLE:
 
334
                return set_connected(provider, FALSE);
 
335
        case CONNMAN_PROVIDER_STATE_CONNECT:
 
336
                return __connman_service_indicate_state(provider->vpn_service,
 
337
                                        CONNMAN_SERVICE_STATE_ASSOCIATION);
 
338
        case CONNMAN_PROVIDER_STATE_READY:
 
339
                return set_connected(provider, TRUE);
 
340
        case CONNMAN_PROVIDER_STATE_DISCONNECT:
 
341
                return __connman_service_indicate_state(provider->vpn_service,
 
342
                                        CONNMAN_SERVICE_STATE_DISCONNECT);
 
343
        case CONNMAN_PROVIDER_STATE_FAILURE:
 
344
                return __connman_service_indicate_state(provider->vpn_service,
 
345
                                        CONNMAN_SERVICE_STATE_FAILURE);
539
346
        }
540
347
 
541
 
        g_free(provider->name);
542
 
        g_free(provider->type);
543
 
        g_free(provider->domain);
544
 
        g_free(provider->identifier);
545
 
        g_free(provider->dns);
 
348
        return -EINVAL;
546
349
}
547
350
 
548
351
static void unregister_provider(gpointer data)
549
352
{
550
353
        struct connman_provider *provider = data;
 
354
        struct connman_service *service = provider->vpn_service;
551
355
 
552
356
        DBG("provider %p", provider);
553
357
 
554
 
        connman_provider_disconnect(provider);
 
358
        provider->vpn_service = NULL;
 
359
        __connman_service_put(service);
555
360
 
556
361
        connman_element_unregister(&provider->element);
557
362
        connman_provider_unref(provider);
561
366
{
562
367
        struct connman_provider *provider = element->private;
563
368
 
564
 
        provider_free(provider);
 
369
        DBG("provider %p", provider);
 
370
 
 
371
        g_free(provider->name);
 
372
        g_free(provider->type);
 
373
        g_free(provider->domain);
 
374
        g_free(provider->identifier);
 
375
        g_free(provider->dns);
565
376
}
566
377
 
567
 
static void __connman_provider_initialize(struct connman_provider *provider)
 
378
static void provider_initialize(struct connman_provider *provider)
568
379
{
569
380
        DBG("provider %p", provider);
570
381
 
571
 
        provider->state = CONNMAN_PROVIDER_STATE_UNKNOWN;
572
 
 
573
382
        __connman_element_initialize(&provider->element);
574
383
 
575
384
        provider->element.private = provider;
586
395
        provider->dns = NULL;
587
396
        provider->domain = NULL;
588
397
        provider->identifier = NULL;
589
 
        provider->path = NULL;
590
 
        provider->pending = NULL;
591
398
}
592
399
 
593
400
static struct connman_provider *connman_provider_new(void)
599
406
                return NULL;
600
407
 
601
408
        DBG("provider %p", provider);
602
 
        __connman_provider_initialize(provider);
 
409
        provider_initialize(provider);
603
410
 
604
411
        return provider;
605
412
}
606
413
 
607
 
static int provider_register(struct connman_provider *provider)
608
 
{
609
 
        const char *path = "/provider";
610
 
 
611
 
        DBG("provider %p", provider);
612
 
 
613
 
        if (provider->path != NULL)
614
 
                return -EALREADY;
615
 
 
616
 
        provider->path = g_strdup_printf("%s/%s", path, provider->identifier);
617
 
 
618
 
        DBG("path %s", provider->path);
619
 
 
620
 
        g_dbus_register_interface(connection, provider->path,
621
 
                                        CONNMAN_PROVIDER_INTERFACE,
622
 
                                        provider_methods, provider_signals,
623
 
                                        NULL, provider, NULL);
624
 
 
625
 
        return 0;
626
 
}
627
 
 
628
414
static struct connman_provider *connman_provider_get(const char *identifier)
629
415
{
630
416
        struct connman_provider *provider;
649
435
        return provider;
650
436
}
651
437
 
652
 
static struct connman_provider *connman_provider_create(const char *name)
 
438
static void provider_dbus_ident(char *ident)
653
439
{
654
 
        struct connman_provider *provider;
655
 
 
656
 
        provider = connman_provider_get(name);
657
 
 
658
 
        if (provider == NULL)
659
 
                return NULL;
660
 
 
661
 
        if (provider->path != NULL)
662
 
                return provider;
663
 
 
664
 
        provider_register(provider);
665
 
 
666
 
        return provider;
 
440
        int i, len = strlen(ident);
 
441
 
 
442
        for (i = 0; i < len; i++) {
 
443
                if (ident[i] >= '0' && ident[i] <= '9')
 
444
                        continue;
 
445
                if (ident[i] >= 'a' && ident[i] <= 'z')
 
446
                        continue;
 
447
                if (ident[i] >= 'A' && ident[i] <= 'Z')
 
448
                        continue;
 
449
                ident[i] = '_';
 
450
        }
667
451
}
668
452
 
669
453
int __connman_provider_create_and_connect(DBusMessage *msg)
670
454
{
671
455
        struct connman_provider *provider;
672
456
        DBusMessageIter iter, array;
673
 
        const char *type = NULL, *name = NULL;
 
457
        const char *type = NULL, *name = NULL, *service_path = NULL;
 
458
        const char *host = NULL, *domain = NULL;
674
459
        char *ident;
675
460
        gboolean created = FALSE;
676
461
        int err;
694
479
                                dbus_message_iter_get_basic(&value, &type);
695
480
                        else if (g_str_equal(key, "Name") == TRUE)
696
481
                                dbus_message_iter_get_basic(&value, &name);
 
482
                        else if (g_str_equal(key, "Host") == TRUE)
 
483
                                dbus_message_iter_get_basic(&value, &host);
 
484
                        else if (g_str_equal(key, "VPN.Domain") == TRUE)
 
485
                                dbus_message_iter_get_basic(&value, &domain);
697
486
                        break;
698
487
                }
699
488
 
700
 
                if (type != NULL && name != NULL)
701
 
                        break;
702
 
 
703
489
                dbus_message_iter_next(&array);
704
490
        }
705
491
 
 
492
        if (host == NULL || domain == NULL) {
 
493
                err = -EINVAL;
 
494
                goto failed;
 
495
        }
 
496
 
706
497
        DBG("Type %s name %s", type, name);
707
498
 
708
499
        if (type == NULL || name == NULL) {
710
501
                goto failed;
711
502
        }
712
503
 
713
 
        ident = g_strdup_printf("%s_%s", type, name);
 
504
        ident = g_strdup_printf("%s_%s", host, domain);
 
505
        provider_dbus_ident(ident);
 
506
 
 
507
        DBG("ident %s", ident);
714
508
 
715
509
        provider = connman_provider_lookup(ident);
716
510
 
717
511
        if (provider == NULL) {
718
512
                created = TRUE;
719
 
                provider = connman_provider_create(ident);
 
513
                provider = connman_provider_get(ident);
720
514
                if (provider) {
 
515
                        provider->host = g_strdup(host);
 
516
                        provider->domain = g_strdup(domain);
721
517
                        provider->name = g_strdup(name);
722
518
                        provider->type = g_strdup(type);
723
519
                }
761
557
        if (created == TRUE)
762
558
                provider_probe(provider);
763
559
 
764
 
        err = connman_provider_connect(provider);
 
560
        if (provider->vpn_service == NULL)
 
561
                provider->vpn_service =
 
562
                        __connman_service_create_from_provider(provider);
 
563
        if (provider->vpn_service == NULL) {
 
564
                err = -EOPNOTSUPP;
 
565
                goto failed;
 
566
        }
 
567
 
 
568
        err = __connman_service_connect(provider->vpn_service);
765
569
        if (err < 0 && err != -EINPROGRESS)
766
570
                goto failed;
767
571
 
 
572
        service_path = __connman_service_get_path(provider->vpn_service);
768
573
        g_dbus_send_reply(connection, msg,
769
 
                                DBUS_TYPE_OBJECT_PATH, &provider->path,
 
574
                                DBUS_TYPE_OBJECT_PATH, &service_path,
770
575
                                                        DBUS_TYPE_INVALID);
771
576
        return 0;
772
577
 
774
579
        if (provider != NULL && created == TRUE) {
775
580
                DBG("can not connect delete provider");
776
581
                connman_provider_unref(provider);
 
582
 
 
583
                if (provider->vpn_service != NULL) {
 
584
                        __connman_service_put(provider->vpn_service);
 
585
                        provider->vpn_service = NULL;
 
586
                }
777
587
        }
778
588
 
779
589
        return err;
780
590
}
781
591
 
 
592
const char * __connman_provider_get_ident(struct connman_provider *provider)
 
593
{
 
594
        if (provider == NULL)
 
595
                return NULL;
 
596
 
 
597
        return provider->identifier;
 
598
}
 
599
 
782
600
int connman_provider_set_string(struct connman_provider *provider,
783
601
                                        const char *key, const char *value)
784
602
{
796
614
        } else if (g_str_equal(key, "Address") == TRUE) {
797
615
                g_free(provider->element.ipv4.address);
798
616
                provider->element.ipv4.address = g_strdup(value);
 
617
        } else if (g_str_equal(key, "Peer") == TRUE) {
 
618
                g_free(provider->element.ipv4.peer);
 
619
                provider->element.ipv4.peer = g_strdup(value);
799
620
        } else if (g_str_equal(key, "Netmask") == TRUE) {
800
621
                g_free(provider->element.ipv4.netmask);
801
622
                provider->element.ipv4.netmask = g_strdup(value);
802
623
        } else if (g_str_equal(key, "PAC") == TRUE) {
803
624
                g_free(provider->element.ipv4.pac);
804
625
                provider->element.ipv4.pac = g_strdup(value);
 
626
                __connman_service_set_proxy_autoconfig(provider->vpn_service,
 
627
                                                                        value);
805
628
        } else if (g_str_equal(key, "DNS") == TRUE) {
806
629
                g_free(provider->dns);
807
630
                provider->dns = g_strdup(value);
838
661
 
839
662
void connman_provider_set_index(struct connman_provider *provider, int index)
840
663
{
 
664
        struct connman_service *service = provider->vpn_service;
 
665
        struct connman_ipconfig *ipconfig;
 
666
 
 
667
        DBG("");
 
668
 
 
669
        if (service == NULL)
 
670
                return;
 
671
 
 
672
        ipconfig = __connman_service_get_ipconfig(service);
 
673
 
 
674
        if (ipconfig == NULL) {
 
675
                __connman_service_create_ipconfig(service, index);
 
676
 
 
677
                ipconfig = __connman_service_get_ipconfig(service);
 
678
                if (ipconfig == NULL) {
 
679
                        DBG("Couldnt create ipconfig");
 
680
                        goto done;
 
681
                }
 
682
        }
 
683
 
 
684
        connman_ipconfig_set_method(ipconfig, CONNMAN_IPCONFIG_METHOD_FIXED);
 
685
        __connman_ipconfig_set_index(ipconfig, index);
 
686
 
 
687
 
 
688
done:
841
689
        provider->element.index = index;
842
690
}
843
691
 
846
694
        return provider->element.index;
847
695
}
848
696
 
 
697
const char *connman_provider_get_driver_name(struct connman_provider *provider)
 
698
{
 
699
        return provider->driver->name;
 
700
}
 
701
 
849
702
static gint compare_priority(gconstpointer a, gconstpointer b)
850
703
{
851
704
        return 0;
875
728
        driver_list = g_slist_remove(driver_list, driver);
876
729
}
877
730
 
 
731
static void provider_remove(gpointer key, gpointer value,
 
732
                                                gpointer user_data)
 
733
{
 
734
        struct connman_provider *provider = value;
 
735
 
 
736
        g_hash_table_remove(provider_hash, provider->identifier);
 
737
}
 
738
 
 
739
static void provider_offline_mode(connman_bool_t enabled)
 
740
{
 
741
        DBG("enabled %d", enabled);
 
742
 
 
743
        if (enabled == TRUE)
 
744
                g_hash_table_foreach(provider_hash, provider_remove, NULL);
 
745
 
 
746
}
 
747
 
 
748
static struct connman_notifier provider_notifier = {
 
749
        .name                   = "provider",
 
750
        .offline_mode           = provider_offline_mode,
 
751
};
 
752
 
878
753
int __connman_provider_init(void)
879
754
{
 
755
        int err;
 
756
 
880
757
        DBG("");
881
758
 
882
759
        connection = connman_dbus_get_connection();
883
760
 
884
761
        provider_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
885
762
                                                NULL, unregister_provider);
886
 
        return 0;
 
763
 
 
764
        err = connman_notifier_register(&provider_notifier);
 
765
        if (err < 0) {
 
766
                g_hash_table_destroy(provider_hash);
 
767
                dbus_connection_unref(connection);
 
768
        }
 
769
 
 
770
        return err;
887
771
}
888
772
 
889
773
void __connman_provider_cleanup(void)
890
774
{
891
775
        DBG("");
892
776
 
 
777
        connman_notifier_unregister(&provider_notifier);
 
778
 
893
779
        g_hash_table_foreach(provider_hash, clean_provider, NULL);
894
780
 
895
781
        g_hash_table_destroy(provider_hash);