bolt-manager.c 77.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Copyright © 2017 Red Hat, Inc
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       Christian J. Kellner <christian@kellner.me>
 */

#include "config.h"

23
#include "bolt-bouncer.h"
Christian Kellner's avatar
Christian Kellner committed
24
#include "bolt-config.h"
25
#include "bolt-device.h"
26
#include "bolt-domain.h"
27
#include "bolt-error.h"
28
#include "bolt-log.h"
29
#include "bolt-power.h"
30
#include "bolt-store.h"
Christian Kellner's avatar
Christian Kellner committed
31
#include "bolt-str.h"
32
#include "bolt-sysfs.h"
33
#include "bolt-time.h"
34
#include "bolt-udev.h"
35
#include "bolt-unix.h"
36
#include "bolt-watchdog.h"
37

Christian Kellner's avatar
Christian Kellner committed
38
39
#include "bolt-manager.h"

40
#include <libudev.h>
41
#include <string.h>
42

43
44
#define PROBING_SETTLE_TIME_MS 2000 /* in milli-seconds */

45
46
47
48
49
50
51
52
53
54
typedef struct udev_device udev_device;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (udev_device, udev_device_unref);


static void     bolt_manager_initable_iface_init (GInitableIface *iface);


static gboolean bolt_manager_initialize (GInitable    *initable,
                                         GCancellable *cancellable,
                                         GError      **error);
55

56
57
static gboolean bolt_manager_store_init (BoltManager *mgr,
                                         GError     **error);
58

59
60
static void     bolt_manager_store_upgrade (BoltManager *mgr,
                                            gboolean    *upgraded);
Christian Kellner's avatar
Christian Kellner committed
61

62
63
64
/* internal manager functions */
static void          manager_sd_notify_status (BoltManager *mgr);

65
/* domain related functions */
66
67
68
static gboolean      manager_load_domains (BoltManager *mgr,
                                           GError     **error);

69
70
71
static void          manager_bootacl_inital_sync (BoltManager *mgr,
                                                  BoltDomain  *domain);

72
73
74
static BoltDomain *  manager_domain_ensure (BoltManager        *mgr,
                                            struct udev_device *dev);

75
76
77
78
79
static BoltDomain *  manager_find_domain_by_syspath (BoltManager *mgr,
                                                     const char  *syspath);

static void          manager_register_domain (BoltManager *mgr,
                                              BoltDomain  *domain);
80

81
82
83
static void          manager_deregister_domain (BoltManager *mgr,
                                                BoltDomain  *domain);

84
85
static void          manager_cleanup_stale_domains (BoltManager *mgr);

86
/* device related functions */
87
88
89
static gboolean      manager_load_devices (BoltManager *mgr,
                                           GError     **error);

90
91
92
93
94
95
static void          manager_register_device (BoltManager *mgr,
                                              BoltDevice  *device);

static void          manager_deregister_device (BoltManager *mgr,
                                                BoltDevice  *device);

96
97
static BoltDevice *  manager_find_device_by_syspath (BoltManager *mgr,
                                                     const char  *sysfs);
98

99
static BoltDevice *  manager_find_device_by_uid (BoltManager *mgr,
100
101
                                                 const char  *uid,
                                                 GError     **error);
102

103
104
105
106
107
108
static BoltDevice *  bolt_manager_get_parent (BoltManager *mgr,
                                              BoltDevice  *dev);

static GPtrArray *   bolt_manager_get_children (BoltManager *mgr,
                                                BoltDevice  *target);

109
110
111
112
static void          bolt_manager_label_device (BoltManager *mgr,
                                                BoltDevice  *target);

/* udev events */
113
114
115
116
static void         handle_uevent_udev (BoltUdev           *udev,
                                        const char         *action,
                                        struct udev_device *device,
                                        gpointer            user_data);
117

118
119
120
121
static void          handle_udev_domain_event (BoltManager        *mgr,
                                               struct udev_device *device,
                                               const char         *action);

122
123
124
static void          handle_udev_domain_removed (BoltManager *mgr,
                                                 BoltDomain  *domain);

125
126
127
128
static void          handle_udev_device_event (BoltManager        *mgr,
                                               struct udev_device *device,
                                               const char         *action);

129
static void          handle_udev_device_added (BoltManager        *mgr,
130
                                               BoltDomain         *domain,
131
132
133
134
135
136
                                               struct udev_device *udev);

static void          handle_udev_device_changed (BoltManager        *mgr,
                                                 BoltDevice         *dev,
                                                 struct udev_device *udev);

137
static void          handle_udev_device_removed (BoltManager *mgr,
138
139
140
                                                 BoltDevice  *dev);

static void          handle_udev_device_attached (BoltManager        *mgr,
141
                                                  BoltDomain         *domain,
142
143
144
145
146
147
                                                  BoltDevice         *dev,
                                                  struct udev_device *udev);

static void          handle_udev_device_detached (BoltManager *mgr,
                                                  BoltDevice  *dev);

148
/* signal callbacks */
149
150
151
152
static void          handle_store_device_added (BoltStore   *store,
                                                const char  *uid,
                                                BoltManager *mgr);

153
154
155
static void          handle_store_device_removed (BoltStore   *store,
                                                  const char  *uid,
                                                  BoltManager *mgr);
156

157
158
159
160
static void          handle_domain_security_changed (BoltManager *mgr,
                                                     GParamSpec  *unused,
                                                     BoltDomain  *domain);

161
162
163
static void          handle_device_status_changed (BoltDevice  *dev,
                                                   BoltStatus   old,
                                                   BoltManager *mgr);
164

165
166
167
168
static void          handle_device_generation_changed (BoltDevice  *dev,
                                                       GParamSpec  *unused,
                                                       BoltManager *mgr);

169
170
171
172
static void          handle_power_state_changed (GObject    *gobject,
                                                 GParamSpec *pspec,
                                                 gpointer    user_data);

173
/* acquiring indicator  */
174
static void          manager_probing_device_added (BoltManager        *mgr,
175
                                                   struct udev_device *dev);
176
177

static void          manager_probing_device_removed (BoltManager        *mgr,
178
                                                     struct udev_device *dev);
179

180
181
182
static void          manager_probing_domain_added (BoltManager        *mgr,
                                                   struct udev_device *domain);

183
static void          manager_probing_activity (BoltManager *mgr,
184
                                               gboolean     weak);
185

186
/* force powering */
187
static BoltGuard *   manager_maybe_power_controller (BoltManager *mgr);
188

Christian Kellner's avatar
Christian Kellner committed
189
190
/* config */
static void          manager_load_user_config (BoltManager *mgr);
191

192
193
194
195
196
197
/* dbus property setter */
static gboolean handle_set_authmode (BoltExported *obj,
                                     const char   *name,
                                     const GValue *value,
                                     GError      **error);

198
/* dbus method calls */
199
200
201
202
203
static GVariant *  handle_list_domains (BoltExported          *object,
                                        GVariant              *params,
                                        GDBusMethodInvocation *invocation,
                                        GError               **error);

204
205
206
207
208
static GVariant *  handle_domain_by_id (BoltExported          *object,
                                        GVariant              *params,
                                        GDBusMethodInvocation *invocation,
                                        GError               **error);

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
static GVariant *  handle_list_devices (BoltExported          *object,
                                        GVariant              *params,
                                        GDBusMethodInvocation *invocation,
                                        GError               **error);

static GVariant *  handle_device_by_uid (BoltExported          *object,
                                         GVariant              *params,
                                         GDBusMethodInvocation *invocation,
                                         GError               **error);

static GVariant *  handle_enroll_device (BoltExported          *object,
                                         GVariant              *params,
                                         GDBusMethodInvocation *invocation,
                                         GError               **error);

static GVariant *  handle_forget_device (BoltExported          *object,
                                         GVariant              *params,
                                         GDBusMethodInvocation *invocation,
                                         GError               **error);
228

229
/*  */
230
231
struct _BoltManager
{
232
  BoltExported object;
233

234
  /* udev */
235
  BoltUdev *udev;
236

237
  /* state */
238
  BoltStore   *store;
239
  BoltDomain  *domains;
240
241
  GPtrArray   *devices;
  BoltPower   *power;
242
  BoltSecurity security;
243
  BoltAuthMode authmode;
244
  guint        generation;
245
246
247

  /* policy enforcer */
  BoltBouncer *bouncer;
248

249
  /* config */
Christian Kellner's avatar
Christian Kellner committed
250
  GKeyFile  *config;
251
252
  BoltPolicy policy;          /* default enrollment policy, unless specified */

253
254
255
256
257
258
  /* probing indicator  */
  guint      authorizing;     /* number of devices currently authorizing */
  GPtrArray *probing_roots;   /* pci device tree root */
  guint      probing_timeout; /* signal id & indicator */
  gint64     probing_tstamp;  /* time stamp of last activity */
  guint      probing_tsettle; /* how long to indicate after the last activity */
259
260
261

  /* watchdog */
  BoltWatchdog *dog;
262
263
264
265
266
267
};

enum {
  PROP_0,

  PROP_VERSION,
268
  PROP_PROBING,
269
  PROP_POLICY,
270
  PROP_SECURITY,
271
  PROP_AUTHMODE,
272
  PROP_POWERSTATE,
273
  PROP_GENERATION,
274

275
276
  PROP_LAST,
  PROP_EXPORTED = PROP_VERSION
277
278
};

279
280
static GParamSpec *props[PROP_LAST] = {NULL, };

281
282
G_DEFINE_TYPE_WITH_CODE (BoltManager,
                         bolt_manager,
283
                         BOLT_TYPE_EXPORTED,
284
285
286
287
288
289
290
291
292
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
                                                bolt_manager_initable_iface_init));


static void
bolt_manager_finalize (GObject *object)
{
  BoltManager *mgr = BOLT_MANAGER (object);

293
  g_clear_object (&mgr->udev);
294

295
296
297
298
299
300
  if (mgr->probing_timeout)
    {
      g_source_remove (mgr->probing_timeout);
      mgr->probing_timeout = 0;
    }

301
302
  g_clear_pointer (&mgr->probing_roots, g_ptr_array_unref);

303
  g_clear_object (&mgr->store);
304
  g_ptr_array_free (mgr->devices, TRUE);
305
  bolt_domain_clear (&mgr->domains);
306

307
  g_clear_object (&mgr->power);
308
  g_clear_object (&mgr->bouncer);
309

310
311
  g_clear_object (&mgr->dog);

312
313
314
315
316
317
318
319
320
321
  G_OBJECT_CLASS (bolt_manager_parent_class)->finalize (object);
}


static void
bolt_manager_get_property (GObject    *object,
                           guint       prop_id,
                           GValue     *value,
                           GParamSpec *pspec)
{
322
323
  BoltManager *mgr = BOLT_MANAGER (object);

324
325
326
  switch (prop_id)
    {
    case PROP_VERSION:
327
      g_value_set_uint (value, BOLT_DBUS_API_VERSION);
328
329
      break;

330
331
332
333
    case PROP_PROBING:
      g_value_set_boolean (value, mgr->probing_timeout > 0);
      break;

334
    case PROP_POLICY:
335
      g_value_set_enum (value, mgr->policy);
336
337
      break;

338
    case PROP_SECURITY:
339
      g_value_set_enum (value, mgr->security);
340
341
      break;

342
343
344
345
    case PROP_AUTHMODE:
      g_value_set_flags (value, mgr->authmode);
      break;

346
347
348
349
    case PROP_POWERSTATE:
      g_value_set_enum (value, bolt_power_get_state (mgr->power));
      break;

350
351
352
353
    case PROP_GENERATION:
      g_value_set_uint (value, mgr->generation);
      break;

354
355
356
357
358
359
360
361
362
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

static void
bolt_manager_init (BoltManager *mgr)
{
  mgr->devices = g_ptr_array_new_with_free_func (g_object_unref);
363

364
365
366
  mgr->probing_roots = g_ptr_array_new_with_free_func (g_free);
  mgr->probing_tsettle = PROBING_SETTLE_TIME_MS; /* milliseconds */

367
  mgr->security = BOLT_SECURITY_UNKNOWN;
368

369
370
  /* default configuration */
  mgr->policy = BOLT_POLICY_AUTO;
371
  mgr->authmode = BOLT_AUTH_ENABLED;
372
373
374
375
376
377
}

static void
bolt_manager_class_init (BoltManagerClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
378
  BoltExportedClass *exported_class = BOLT_EXPORTED_CLASS (klass);
379
380
381
382

  gobject_class->finalize = bolt_manager_finalize;
  gobject_class->get_property = bolt_manager_get_property;

383
384
385
386
387
388
389
390
391
392
393
  props[PROP_VERSION] =
    g_param_spec_uint ("version", "Version", "Version",
                       0, G_MAXUINT32, 0,
                       G_PARAM_READABLE |
                       G_PARAM_STATIC_STRINGS);

  props[PROP_PROBING] =
    g_param_spec_boolean ("probing", "Probing", "Probing",
                          FALSE,
                          G_PARAM_READABLE |
                          G_PARAM_STATIC_STRINGS);
394

395
  props[PROP_POLICY] =
396
397
398
    g_param_spec_enum ("default-policy", "DefaultPolicy", "DefaultPolicy",
                       BOLT_TYPE_POLICY,
                       BOLT_POLICY_AUTO,
399
400
401
                       G_PARAM_READABLE |
                       G_PARAM_STATIC_STRINGS);

402
  props[PROP_SECURITY] =
403
404
    g_param_spec_enum ("security-level", "SecurityLevel", NULL,
                       BOLT_TYPE_SECURITY,
405
                       BOLT_SECURITY_UNKNOWN,
406
407
408
                       G_PARAM_READABLE |
                       G_PARAM_STATIC_STRINGS);

409
410
411
412
413
414
415
  props[PROP_AUTHMODE] =
    g_param_spec_flags ("auth-mode", "AuthMode", NULL,
                        BOLT_TYPE_AUTH_MODE,
                        BOLT_AUTH_ENABLED,
                        G_PARAM_READABLE |
                        G_PARAM_STATIC_STRINGS);

416
417
418
419
420
421
422
  props[PROP_POWERSTATE] =
    g_param_spec_enum ("power-state", "PowerState", NULL,
                       BOLT_TYPE_POWER_STATE,
                       BOLT_FORCE_POWER_UNSET,
                       G_PARAM_READABLE |
                       G_PARAM_STATIC_STRINGS);

423
424
425
426
427
428
  props[PROP_GENERATION] =
    g_param_spec_uint ("generation", "Generation", NULL,
                       0, G_MAXUINT, 0,
                       G_PARAM_READABLE |
                       G_PARAM_STATIC_STRINGS);

429
430
431
432
433
  g_object_class_install_properties (gobject_class, PROP_LAST, props);


  bolt_exported_class_set_interface_info (exported_class,
                                          BOLT_DBUS_INTERFACE,
434
                                          BOLT_DBUS_GRESOURCE_PATH);
435
436
437
438
439
440

  bolt_exported_class_export_properties (exported_class,
                                         PROP_EXPORTED,
                                         PROP_LAST,
                                         props);

441
442
443
444
  bolt_exported_class_property_setter (exported_class,
                                       props[PROP_AUTHMODE],
                                       handle_set_authmode);

445
446
447
448
  bolt_exported_class_export_method (exported_class,
                                     "ListDomains",
                                     handle_list_domains);

449
450
451
452
  bolt_exported_class_export_method (exported_class,
                                     "DomainById",
                                     handle_domain_by_id);

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
  bolt_exported_class_export_method (exported_class,
                                     "ListDevices",
                                     handle_list_devices);

  bolt_exported_class_export_method (exported_class,
                                     "DeviceByUid",
                                     handle_device_by_uid);

  bolt_exported_class_export_method (exported_class,
                                     "EnrollDevice",
                                     handle_enroll_device);

  bolt_exported_class_export_method (exported_class,
                                     "ForgetDevice",
                                     handle_forget_device);
468
469
470
471
472
473
474
475
476
477
478
479
480
}

static void
bolt_manager_initable_iface_init (GInitableIface *iface)
{
  iface->init = bolt_manager_initialize;
}

static gboolean
bolt_manager_initialize (GInitable    *initable,
                         GCancellable *cancellable,
                         GError      **error)
{
481
  g_autoptr(BoltGuard) power = NULL;
482
  BoltManager *mgr;
483
484
  struct udev_enumerate *enumerate;
  struct udev_list_entry *l, *devices;
485
  gboolean upgraded = FALSE;
486
  gboolean ok;
487

488
489
  mgr = BOLT_MANAGER (initable);

490
491
492
493
  /* store setup */
  ok = bolt_manager_store_init (mgr, error);
  if (!ok)
    return FALSE;
494

Christian Kellner's avatar
Christian Kellner committed
495
496
497
  /* load dynamic user configuration */
  manager_load_user_config (mgr);

498
499
500
501
502
503
504
  /* polkit setup */
  mgr->bouncer = bolt_bouncer_new (cancellable, error);
  if (mgr->bouncer == NULL)
    return FALSE;

  bolt_bouncer_add_client (mgr->bouncer, mgr);

505
506
507
508
509
  /* watchdog setup */
  mgr->dog = bolt_watchdog_new (error);
  if (mgr->dog == NULL)
    return FALSE;

510
  /* udev setup*/
511
  bolt_info (LOG_TOPIC ("udev"), "initializing udev");
512
  mgr->udev = bolt_udev_new ("udev", NULL, error);
513

514
  if (mgr->udev == NULL)
515
516
    return FALSE;

517
518
519
520
  g_signal_connect_object (mgr->udev, "uevent",
                           (GCallback) handle_uevent_udev,
                           mgr, 0);

521
522
523
524
  ok = manager_load_domains (mgr, error);
  if (!ok)
    return FALSE;

525
526
527
  ok = manager_load_devices (mgr, error);
  if (!ok)
    return FALSE;
528

529
  /* setup the power controller */
530
  mgr->power = bolt_power_new (mgr->udev);
531
532
  bolt_bouncer_add_client (mgr->bouncer, mgr->power);

533
534
535
  g_signal_connect_object (mgr->power, "notify::state",
                           G_CALLBACK (handle_power_state_changed),
                           mgr, 0);
536
537

  /* if we don't see any tb device, we try to force power */
538
  power = manager_maybe_power_controller (mgr);
539

540
541
  if (power != NULL)
    bolt_info (LOG_TOPIC ("manager"), "acquired power guard '%s'",
542
               bolt_guard_get_id (power));
543

544
  /* TODO: error checking */
545
  enumerate =  bolt_udev_new_enumerate (mgr->udev, NULL);
546
547
548
  udev_enumerate_add_match_subsystem (enumerate, "thunderbolt");
  /* only devices (i.e. not the domain controller) */

549
  bolt_info (LOG_TOPIC ("udev"), "enumerating devices");
550
551
552
  udev_enumerate_scan_devices (enumerate);
  devices = udev_enumerate_get_list_entry (enumerate);

553
  udev_list_entry_foreach (l, devices)
554
    {
555
      g_autoptr(GError) err = NULL;
556
      g_autoptr(udev_device) udevice = NULL;
557
      const char *syspath;
558
      const char *devtype;
559

560
      syspath = udev_list_entry_get_name (l);
561
562
563
      udevice = bolt_udev_device_new_from_syspath (mgr->udev,
                                                   syspath,
                                                   &err);
564
565

      if (udevice == NULL)
566
567
568
569
        {
          bolt_warn_err (err, "enumerating devices");
          continue;
        }
570

571
572
573
      devtype = udev_device_get_devtype (udevice);

      if (bolt_streq (devtype, "thunderbolt_domain"))
574
        handle_udev_domain_event (mgr, udevice, "add");
575

576
577
      if (bolt_streq (devtype, "thunderbolt_device"))
        handle_udev_device_event (mgr, udevice, "add");
578
579
    }

580
  udev_enumerate_unref (enumerate);
581

Christian Kellner's avatar
Christian Kellner committed
582
  /* upgrade the store, if needed */
583
584
585
586
  bolt_manager_store_upgrade (mgr, &upgraded);

  if (upgraded)
    manager_cleanup_stale_domains (mgr);
Christian Kellner's avatar
Christian Kellner committed
587

588
589
  manager_sd_notify_status (mgr);

590
591
592
  return TRUE;
}

593
594
static gboolean
bolt_manager_store_init (BoltManager *mgr, GError **error)
595
596
597
{
  bolt_info (LOG_TOPIC ("manager"), "initializing store");

598
599
600
  mgr->store = bolt_store_new (bolt_get_store_path (), error);
  if (mgr->store == NULL)
    return FALSE;
601
602
603
604
605
606
607
608

  g_signal_connect_object (mgr->store, "device-added",
                           G_CALLBACK (handle_store_device_added),
                           mgr, 0);

  g_signal_connect_object (mgr->store, "device-removed",
                           G_CALLBACK (handle_store_device_removed),
                           mgr, 0);
609
610

  return TRUE;
611
612
}

Christian Kellner's avatar
Christian Kellner committed
613
static void
614
bolt_manager_store_upgrade (BoltManager *mgr, gboolean *upgraded)
Christian Kellner's avatar
Christian Kellner committed
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
{
  g_autoptr(GError) err = NULL;
  BoltStore *store = mgr->store;
  guint ver;
  gboolean ok;

  ver = bolt_store_get_version (store);

  if (ver == BOLT_STORE_VERSION)
    {
      bolt_debug (LOG_TOPIC ("store"), "store is up to date");
      return;
    }

  bolt_info (LOG_TOPIC ("store"), "attempting upgrade from '%d'",
             ver);

  ok = bolt_store_upgrade (store, NULL, &err);
  if (!ok)
    {
      bolt_warn_err (err, LOG_TOPIC ("store"), "upgrade failed");
      return;
    }

639
  ver = bolt_store_get_version (store);
Christian Kellner's avatar
Christian Kellner committed
640
641
  bolt_info (LOG_TOPIC ("store"), "upgraded to version '%d'",
             ver);
642
643

  *upgraded = TRUE;
Christian Kellner's avatar
Christian Kellner committed
644
645
}

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
/* internal functions */
static void
manager_sd_notify_status (BoltManager *mgr)
{
  g_autoptr(GError) err = NULL;
  g_autofree char *status = NULL;
  const char *pstate = NULL;
  BoltPowerState power;
  gboolean sent;
  gboolean authorizing;
  gboolean ok = FALSE;

  authorizing = bolt_flag_isset (mgr->authmode, BOLT_AUTH_ENABLED);
  power = bolt_power_get_state (mgr->power);
  pstate = bolt_enum_to_string (BOLT_TYPE_POWER_STATE, power, NULL);

  status = g_strdup_printf ("STATUS=authmode: %s,"
                            " force-power: %s",
                            (authorizing ? "enabled" : "DISABLED"),
                            (pstate ? : "unknown"));

  ok = bolt_sd_notify_literal (status, &sent, &err);

  if (!ok)
    bolt_warn_err (err, LOG_TOPIC ("status"),
                   "failed to send status");
  else
    bolt_debug (LOG_TOPIC ("status"), "%s [sent: %s]",
                status, bolt_yesno (sent));
}

677
678
679
680
681
static void
manager_maybe_set_security (BoltManager *mgr,
                            BoltSecurity security)
{
  /* update the security level, if it is not already
682
  * set, but also ignore if security is 'unknown' */
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702

  if (security == BOLT_SECURITY_UNKNOWN)
    return;

  if (mgr->security == BOLT_SECURITY_UNKNOWN)
    {
      bolt_info ("security level set to '%s'",
                 bolt_security_to_string (security));
      mgr->security = security;
      g_object_notify_by_pspec (G_OBJECT (mgr),
                                props[PROP_SECURITY]);
    }
  else if (mgr->security != security)
    {
      bolt_warn ("multiple security levels (%s vs %s)",
                 bolt_security_to_string (mgr->security),
                 bolt_security_to_string (security));
    }
}

703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
static void
manager_maybe_set_generation (BoltManager *mgr,
                              guint        gen)
{
  guint check;

  check = MAX (mgr->generation, gen);

  if (mgr->generation >= check)
    return;

  bolt_info ("global 'generation' set to '%d'", check);

  mgr->generation = check;
  g_object_notify_by_pspec (G_OBJECT (mgr),
                            props[PROP_GENERATION]);
}

721
/* domain related function */
722
723
724
725
726
727
728
729
730
static gboolean
manager_load_domains (BoltManager *mgr,
                      GError     **error)
{
  g_auto(GStrv) ids = NULL;

  ids = bolt_store_list_uids (mgr->store, "domains", error);
  if (ids == NULL)
    {
731
      g_prefix_error (error, "failed to list domains in store: ");
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
      return FALSE;
    }

  bolt_info (LOG_TOPIC ("store"), "loading domains");

  for (guint i = 0; i < g_strv_length (ids); i++)
    {
      g_autoptr(GError) err = NULL;
      BoltDomain *dom = NULL;
      const char *uid = ids[i];

      bolt_info (LOG_TOPIC ("store"), LOG_DOM_UID (uid),
                 "loading domain");

      dom = bolt_store_get_domain (mgr->store, uid, &err);
      if (dom == NULL)
        {
          bolt_warn_err (err, LOG_DOM_UID (uid), LOG_TOPIC ("store"),
                         "failed to load domain", uid);
          continue;
        }

      manager_register_domain (mgr, dom);
    }

  return TRUE;
}

760
761
762
763
764
765
766
767
768
769
770
static void
manager_bootacl_inital_sync (BoltManager *mgr,
                             BoltDomain  *domain)
{
  g_autoptr(GError) err = NULL;
  g_auto(GStrv) acl = NULL;
  gboolean ok;
  guint n, empty;

  if (!bolt_domain_supports_bootacl (domain))
    {
771
      bolt_info (LOG_TOPIC ("bootacl"), LOG_DOM (domain),
772
773
774
775
776
777
778
779
780
                 "bootacl not supported, no sync");
      return;
    }

  acl = bolt_domain_dup_bootacl (domain);
  g_assert (acl != NULL);

  n = bolt_domain_bootacl_slots (domain, &empty);

781
  bolt_info (LOG_TOPIC ("bootacl"), LOG_DOM (domain),
782
783
784
785
786
787
788
789
790
791
792
793
             "sync start [slots: %u free: %u]", n, empty);

  for (guint i = 0; i < mgr->devices->len; i++)
    {
      BoltDevice *dev = g_ptr_array_index (mgr->devices, i);
      const char *duid = bolt_device_get_uid (dev);
      gboolean polok, inacl, sync;

      polok = bolt_device_get_policy (dev) == BOLT_POLICY_AUTO;
      inacl = bolt_domain_bootacl_contains (domain, duid);
      sync = polok && !inacl;

794
      bolt_info (LOG_TOPIC ("bootacl"), LOG_DOM (domain),
795
                 LOG_DEV_UID (duid),
796
                 "sync '%.13s…' %s [policy: %3s, in acl: %3s]",
797
798
799
800
801
802
803
804
805
806
807
808
809
                 duid, bolt_yesno (sync), bolt_yesno (polok),
                 bolt_yesno (inacl));

      if (!sync)
        continue;

      bolt_domain_bootacl_allocate (domain, acl, duid);
    }

  ok = bolt_domain_bootacl_set (domain, acl, &err);

  if (!ok && err != NULL)
    {
810
      bolt_warn_err (err, LOG_DOM (domain), "failed to write bootacl");
811
812
813
814
      return;
    }

  bolt_domain_bootacl_slots (domain, &empty);
815
  bolt_info (LOG_TOPIC ("bootacl"), LOG_DOM (domain),
816
817
818
819
             "sync done [wrote: %s, now free: %u]",
             bolt_yesno (ok), empty);
}

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
static gboolean
domain_has_stable_uuid (BoltDomain         *domain,
                        struct udev_device *dev)
{
  g_autoptr(GError) err = NULL;
  gboolean stable;
  gboolean ok;
  guint32 pci_id;

  /* On integrated TBT, like ICL/TGL, the uuid of the
   * controller is randomly generated on *every* boot,
   * and thus the uuid is not stable. */

  /* default to FALSE, in case we have no entry */
  stable = FALSE;

  ok = bolt_sysfs_nhi_id_for_domain (dev, &pci_id, &err);
  if (!ok)
    {
      bolt_warn_err (err, LOG_TOPIC ("udev"), LOG_DOM (domain),
                     "failed to get NHI for domain");
      return FALSE;
    }

  ok = bolt_nhi_uuid_is_stable (pci_id, &stable, &err);
  if (!ok)
    bolt_warn_err (err, LOG_TOPIC ("udev"), LOG_DOM (domain),
                   "failed to determine if uid is stable");

  bolt_info (LOG_TOPIC ("udev"), LOG_DOM (domain),
             "uuid is stable: %s (for NHI: 0x%04x)",
             bolt_yesno (stable), pci_id);

  return stable;
}

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
static void
manager_store_domain (BoltManager *mgr,
                      BoltDomain  *domain)
{
  g_autoptr(GError) err = NULL;
  gboolean ok;

  bolt_info (LOG_TOPIC ("store"), LOG_DOM (domain),
             "storing newly connected domain");

  ok = bolt_store_put_domain (mgr->store, domain, &err);
  if (!ok)
    bolt_warn_err (err, LOG_TOPIC ("store"), LOG_DOM (domain),
                   "could not store domain");
}

872
873
874
875
static BoltDomain *
manager_domain_ensure (BoltManager        *mgr,
                       struct udev_device *dev)
{
876
  g_autoptr(GError) err = NULL;
877
  BoltSecurity level;
878
879
  BoltDomain *domain = NULL;
  GDBusConnection *bus;
880
  struct udev_device *host;
881
  struct udev_device *dom;
882
  const char *security;
883
  const char *syspath;
884
  const char *op;
885
  const char *uid;
886
  gboolean iommu;
887

888
889
890
891
  /* check if we already know a domain that is the parent
   * of the device (dev); if not then 'dev' is very likely
   * the host device.
   */
892
893
894
895
896
897
898
899
  syspath = udev_device_get_syspath (dev);
  domain = manager_find_domain_by_syspath (mgr, syspath);

  if (domain != NULL)
    return domain;

  /* dev is very likely the host, i.e. root switch device,
   * but we might as well make sure we can get the domain
900
901
902
903
   * from any; also we make sure that we have indeed the
   * host device via this lookup.
   */
  dom = bolt_sysfs_domain_for_device (dev, &host);
904
905
906
  if (dom == NULL)
    return NULL;

907
  uid = udev_device_get_sysattr_value (host, "unique_id");
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922

  /* check if we have a stored domain with a matching uid
   * of the host device, if so then we have just connected
   * the corresponding domain controller, represented by
   * the 'dom' udev_device.
   */
  domain = bolt_domain_find_id (mgr->domains, uid, NULL);

  if (domain != NULL)
    {
      bolt_domain_connected (domain, dom);
      return domain;
    }

  /* this is an unknown, unstored domain controller */
923
  domain = bolt_domain_new_for_udev (dom, uid, &err);
924
925
926
927
928
929
930
931

  if (domain == NULL)
    {
      bolt_warn_err (err, LOG_TOPIC ("udev"),
                     "failed to create domain: %s");
      return NULL;
    }

932
933
934
  level = bolt_domain_get_security (domain);
  iommu = bolt_domain_has_iommu (domain);
  security = bolt_security_for_display (level, iommu);
935
936

  bolt_msg (LOG_DOM (domain), "newly connected [%s] (%s)",
937
            security, syspath);
938

939
  manager_maybe_set_security (mgr, level);
940

941
942
943
944
945
  manager_register_domain (mgr, domain);

  /* registering the domain will add one reference */
  g_object_unref (domain);

946
947
948
  /* add all devices with POLICY_AUTO to the bootacl */
  manager_bootacl_inital_sync (mgr, domain);

949
950
951
952
  /* now store the domain (with an updated bootacl),
   * but only if its uuid is the same across reboots */
  if (domain_has_stable_uuid (domain, dom))
    manager_store_domain (mgr, domain);
953

954
  /* export it on the bus and emit the added signals */
955
956
957
958
959
960
961
962
963
964
965
966
  bus = bolt_exported_get_connection (BOLT_EXPORTED (mgr));
  if (bus == NULL)
    return domain;

  bolt_domain_export (domain, bus);

  op = bolt_exported_get_object_path (BOLT_EXPORTED (domain));
  bolt_exported_emit_signal (BOLT_EXPORTED (mgr),
                             "DomainAdded",
                             g_variant_new ("(o)", op),
                             NULL);

967
968
969
  return domain;
}

970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
static BoltDomain *
manager_find_domain_by_syspath (BoltManager *mgr,
                                const char  *syspath)
{
  BoltDomain *iter = mgr->domains;
  guint n_domains;

  n_domains = bolt_domain_count (mgr->domains);
  for (guint i = 0; i < n_domains; i++)
    {
      const char *prefix = bolt_domain_get_syspath (iter);

      /* we get a perfect match, if we search for the domain
       * itself, or if we are looking for the domain that
       * is the parent of the device in @syspath */
985
      if (prefix && g_str_has_prefix (syspath, prefix))
986
987
988
989
990
991
992
993
        return iter;

      iter = bolt_domain_next (iter);
    }

  return NULL;
}

994
995
996
997
998
999
1000
static gboolean
bootacl_alloc (BoltDomain  *domain,
               GStrv        acl,
               const char  *uid,
               gint        *slot,
               BoltManager *mgr)
{