~connman-maintainers/connman/head

« back to all changes in this revision

Viewing changes to plugins/iwd.c

  • Committer: Marcel Holtmann
  • Author(s): Emmanuel VAUTRIN
  • Date: 2023-08-16 07:07:35 UTC
  • Revision ID: git-v1:f372333004a5bc8945feafb43e09d8f64996f1c6
iwd: Fix invalid-key error on user reconnection

Connecting to a WiFi network under disconnection leads to an
invalid-key error, when the disconnection callback tries to reset the
connected status and the network is still connecting or associating.
In this case, connman_network_set_connected() sets a
CONNMAN_NETWORK_ERROR_CONNECT_FAIL error, which shall be ignored.

Show diffs side-by-side

added added

removed removed

Lines of Context:
90
90
        char *mode;
91
91
 
92
92
        struct connman_device *device;
 
93
 
 
94
        char *network;
 
95
        char *pending_network;
 
96
        bool disconnecting;
93
97
};
94
98
 
95
99
/*
243
247
        connman_network_set_connected(iwdn->network, true);
244
248
}
245
249
 
246
 
static void update_network_disconnected(struct iwd_network *iwdn)
247
 
{
248
 
        DBG("interface name %s", iwdn->name);
249
 
        connman_network_set_connected(iwdn->network, false);
250
 
}
251
 
 
252
250
static void cm_network_connect_cb(DBusMessage *message, void *user_data)
253
251
{
254
252
        const char *path = user_data;
279
277
        update_network_connected(iwdn);
280
278
}
281
279
 
 
280
static void abort_pending_network(struct iwd_device *iwdd,
 
281
                                        enum connman_network_error error)
 
282
{
 
283
        struct iwd_network *iwdn;
 
284
 
 
285
        if (!iwdd->pending_network)
 
286
                return;
 
287
 
 
288
        iwdn = g_hash_table_lookup(networks, iwdd->pending_network);
 
289
        if (iwdn)
 
290
                connman_network_set_error(iwdn->network, error);
 
291
 
 
292
        g_free(iwdd->pending_network);
 
293
        iwdd->pending_network = NULL;
 
294
}
 
295
 
282
296
static int cm_network_connect(struct connman_network *network)
283
297
{
284
298
        struct iwd_network *iwdn = connman_network_get_data(network);
 
299
        struct iwd_device *iwdd;
 
300
        int err;
285
301
 
286
 
        if (!iwdn)
 
302
        if (!iwdn || !iwdn->iwdd)
287
303
                return -EINVAL;
288
304
 
 
305
        iwdd = iwdn->iwdd;
 
306
        if (iwdd->disconnecting) {
 
307
                if (g_strcmp0(iwdn->path, iwdd->pending_network)) {
 
308
                        abort_pending_network(iwdd,
 
309
                                        CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
 
310
                        iwdd->pending_network = g_strdup(iwdn->path);
 
311
                }
 
312
                return -EINPROGRESS;
 
313
        }
 
314
 
289
315
        if (!g_dbus_proxy_method_call(iwdn->proxy, "Connect",
290
316
                        NULL, cm_network_connect_cb,
291
 
                        g_strdup(iwdn->path), g_free))
292
 
                return -EIO;
 
317
                        g_strdup(iwdn->path), g_free)) {
 
318
                err = -EIO;
 
319
                goto out;
 
320
        }
293
321
 
294
322
        connman_network_set_associating(iwdn->network, true);
295
323
 
296
 
        return -EINPROGRESS;
 
324
        g_free(iwdd->network);
 
325
        iwdd->network = g_strdup(iwdn->path);
 
326
 
 
327
        err = -EINPROGRESS;
 
328
 
 
329
out:
 
330
        abort_pending_network(iwdd, CONNMAN_NETWORK_ERROR_UNKNOWN);
 
331
        return err;
297
332
}
298
333
 
299
334
static void cm_network_forget_cb(DBusMessage *message, void *user_data)
336
371
        return 0;
337
372
}
338
373
 
 
374
static void update_network_disconnected(struct iwd_network *iwdn)
 
375
{
 
376
        struct iwd_network *iwdn_pending = NULL;
 
377
        struct iwd_device *iwdd;
 
378
 
 
379
        if (!iwdn || !iwdn->iwdd)
 
380
                return;
 
381
 
 
382
        iwdd = iwdn->iwdd;
 
383
 
 
384
        DBG("interface name %s", iwdn->name);
 
385
 
 
386
        if (iwdd->pending_network) {
 
387
                iwdn_pending =
 
388
                        g_hash_table_lookup(networks, iwdd->pending_network);
 
389
        }
 
390
 
 
391
        if (!iwdn_pending || g_strcmp0(iwdn->path, iwdd->pending_network))
 
392
                connman_network_set_connected(iwdn->network, false);
 
393
 
 
394
        iwdd->disconnecting = false;
 
395
 
 
396
        if (g_strcmp0(iwdn->path, iwdd->network)) {
 
397
                if (!g_strcmp0(iwdn->path, iwdd->pending_network)) {
 
398
                        abort_pending_network(iwdd,
 
399
                                        CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
 
400
                }
 
401
                DBG("current wifi network has changed since disconnection");
 
402
                return;
 
403
        }
 
404
 
 
405
        g_free(iwdd->network);
 
406
        iwdd->network = NULL;
 
407
 
 
408
        if (iwdn_pending) {
 
409
                cm_network_connect(iwdn_pending->network);
 
410
        }
 
411
}
 
412
 
339
413
static void cm_network_disconnect_cb(DBusMessage *message, void *user_data)
340
414
{
341
415
        const char *path = user_data;
345
419
        if (!iwdn)
346
420
                return;
347
421
 
 
422
        if (iwdn->iwdd)
 
423
                iwdn->iwdd->disconnecting = false;
 
424
 
348
425
        if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) {
349
426
                const char *dbus_error = dbus_message_get_error_name(message);
350
427
 
369
446
{
370
447
        struct iwd_network *iwdn = connman_network_get_data(network);
371
448
        struct iwd_station *iwds;
 
449
        struct iwd_device *iwdd;
372
450
 
373
 
        if (!iwdn && !iwdn->iwdd)
 
451
        if (!iwdn || !iwdn->iwdd)
374
452
                return -EINVAL;
375
453
 
376
 
        iwds = g_hash_table_lookup(stations, iwdn->iwdd->path);
 
454
        iwdd = iwdn->iwdd;
 
455
        if (iwdd->disconnecting)
 
456
                return -EALREADY;
 
457
 
 
458
        iwds = g_hash_table_lookup(stations, iwdd->path);
377
459
        if (!iwds)
378
460
                return -EIO;
379
461
 
383
465
                        NULL, cm_network_disconnect_cb, g_strdup(iwdn->path), g_free))
384
466
                return -EIO;
385
467
 
 
468
        iwdd->disconnecting = true;
 
469
 
386
470
        return 0;
387
471
}
388
472
 
582
666
        }
583
667
 
584
668
        connman_device_set_powered(iwdd->device, cbd->powered);
 
669
 
 
670
        if (!cbd->powered) {
 
671
                abort_pending_network(iwdd,
 
672
                                        CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
 
673
                iwdd->disconnecting = false;
 
674
        }
585
675
out:
586
676
        g_free(cbd->path);
587
677
        g_free(cbd);
1424
1514
        g_free(iwdd->adapter);
1425
1515
        g_free(iwdd->name);
1426
1516
        g_free(iwdd->address);
 
1517
 
 
1518
        g_free(iwdd->network);
 
1519
        g_free(iwdd->pending_network);
 
1520
 
1427
1521
        g_free(iwdd);
1428
1522
}
1429
1523