interface_backend_udev.c 39.2 KB
Newer Older
1 2 3
/*
 * interface_backend_udev.c: udev backend for virInterface
 *
4
 * Copyright (C) 2014 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 * Copyright (C) 2012 Doug Goldstein <cardoe@cardoe.com>
 *
 * This library 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/>.
 */
#include <config.h>

23
#include <dirent.h>
24 25
#include <libudev.h>

26
#include "virerror.h"
27
#include "virfile.h"
28
#include "c-ctype.h"
29
#include "datatypes.h"
30
#include "domain_conf.h"
31 32
#include "interface_driver.h"
#include "interface_conf.h"
33
#include "viralloc.h"
34
#include "virstring.h"
35
#include "virpidfile.h"
36
#include "viraccessapicheck.h"
J
John Ferlan 已提交
37
#include "virinterfaceobj.h"
38
#include "virnetdev.h"
39

40 41
#include "configmake.h"

42 43 44 45
#define VIR_FROM_THIS VIR_FROM_INTERFACE

struct udev_iface_driver {
    struct udev *udev;
46 47 48 49
    /* pid file FD, ensures two copies of the driver can't use the same root */
    int lockFD;

    char *stateDir;
50
    bool privileged;
51 52 53 54 55 56
};

typedef enum {
    VIR_UDEV_IFACE_ACTIVE,
    VIR_UDEV_IFACE_INACTIVE,
    VIR_UDEV_IFACE_ALL
57
} virUdevStatus;
58

59 60
static struct udev_iface_driver *driver;

61
static virInterfaceDef *udevGetIfaceDef(struct udev *udev, const char *name);
62

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
static const char *
virUdevStatusString(virUdevStatus status)
{
    switch (status) {
        case VIR_UDEV_IFACE_ACTIVE:
            return "active";
        case VIR_UDEV_IFACE_INACTIVE:
            return "inactive";
        case VIR_UDEV_IFACE_ALL:
            return "all";
    }

    return "";
}

78 79 80
/*
 * Get a minimal virInterfaceDef containing enough metadata
 * for access control checks to be performed. Currently
N
Nehal J Wani 已提交
81
 * this implies existence of name and mac address attributes
82 83 84 85 86 87 88
 */
static virInterfaceDef * ATTRIBUTE_NONNULL(1)
udevGetMinimalDefForDevice(struct udev_device *dev)
{
    virInterfaceDef *def;

    /* Allocate our interface definition structure */
89
    if (VIR_ALLOC(def) < 0)
90 91 92 93 94 95 96 97 98 99
        return NULL;

    if (VIR_STRDUP(def->name, udev_device_get_sysname(dev)) < 0)
        goto cleanup;

    if (VIR_STRDUP(def->mac, udev_device_get_sysattr_value(dev, "address")) < 0)
        goto cleanup;

    return def;

100
 cleanup:
101 102 103 104 105
    virInterfaceDefFree(def);
    return NULL;
}


106
static struct udev_enumerate * ATTRIBUTE_NONNULL(1)
107
udevGetDevices(struct udev *udev, virUdevStatus status)
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
{
    struct udev_enumerate *enumerate;

    /* Create a new enumeration to create a list */
    enumerate = udev_enumerate_new(udev);

    if (!enumerate)
        return NULL;

    /* Enumerate all network subsystem devices */
    udev_enumerate_add_match_subsystem(enumerate, "net");

    /* Ignore devices that are part of a bridge */
    udev_enumerate_add_nomatch_sysattr(enumerate, "brport/state", NULL);

    /* State of the device */
    switch (status) {
        case VIR_UDEV_IFACE_ACTIVE:
            udev_enumerate_add_match_sysattr(enumerate, "operstate", "up");
            break;

        case VIR_UDEV_IFACE_INACTIVE:
            udev_enumerate_add_match_sysattr(enumerate, "operstate", "down");
            break;

        case VIR_UDEV_IFACE_ALL:
            break;
    }

    /* We don't want to see the TUN devices that QEMU creates for other guests
     * running on this machine. By saying nomatch NULL, we just are getting
     * devices without the tun_flags sysattr.
     */
    udev_enumerate_add_nomatch_sysattr(enumerate, "tun_flags", NULL);

    return enumerate;
}

static int
147 148
udevNumOfInterfacesByStatus(virConnectPtr conn, virUdevStatus status,
                            virInterfaceObjListFilter filter)
149
{
150
    struct udev *udev = udev_ref(driver->udev);
151 152 153 154 155
    struct udev_enumerate *enumerate = NULL;
    struct udev_list_entry *devices;
    struct udev_list_entry *dev_entry;
    int count = 0;

156
    enumerate = udevGetDevices(udev, status);
157 158 159 160 161 162

    if (!enumerate) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to get number of %s interfaces on host"),
                       virUdevStatusString(status));
        count = -1;
163
        goto cleanup;
164 165 166 167 168 169 170 171 172 173
    }

    /* Do the scan to load up the enumeration */
    udev_enumerate_scan_devices(enumerate);

    /* Get a list we can walk */
    devices = udev_enumerate_get_list_entry(enumerate);

    /* For each item so we can count */
    udev_list_entry_foreach(dev_entry, devices) {
174 175 176 177 178 179 180 181 182 183 184 185
        struct udev_device *dev;
        const char *path;
        virInterfaceDefPtr def;

        path = udev_list_entry_get_name(dev_entry);
        dev = udev_device_new_from_syspath(udev, path);

        def = udevGetMinimalDefForDevice(dev);
        if (filter(conn, def))
            count++;
        udev_device_unref(dev);
        virInterfaceDefFree(def);
186 187
    }

188
 cleanup:
189 190 191 192 193 194 195 196
    if (enumerate)
        udev_enumerate_unref(enumerate);
    udev_unref(udev);

    return count;
}

static int
197 198 199
udevListInterfacesByStatus(virConnectPtr conn,
                           char **const names,
                           int names_len,
200 201
                           virUdevStatus status,
                           virInterfaceObjListFilter filter)
202
{
203
    struct udev *udev = udev_ref(driver->udev);
204 205 206 207 208
    struct udev_enumerate *enumerate = NULL;
    struct udev_list_entry *devices;
    struct udev_list_entry *dev_entry;
    int count = 0;

209
    enumerate = udevGetDevices(udev, status);
210 211 212 213 214

    if (!enumerate) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to get list of %s interfaces on host"),
                       virUdevStatusString(status));
215
        goto error;
216 217 218 219 220 221 222 223 224 225 226 227
    }

    /* Do the scan to load up the enumeration */
    udev_enumerate_scan_devices(enumerate);

    /* Get a list we can walk */
    devices = udev_enumerate_get_list_entry(enumerate);

    /* For each item so we can count */
    udev_list_entry_foreach(dev_entry, devices) {
        struct udev_device *dev;
        const char *path;
228
        virInterfaceDefPtr def;
229 230 231 232 233 234 235

        /* Ensure we won't exceed the size of our array */
        if (count > names_len)
            break;

        path = udev_list_entry_get_name(dev_entry);
        dev = udev_device_new_from_syspath(udev, path);
236 237 238 239 240 241 242 243 244

        def = udevGetMinimalDefForDevice(dev);
        if (filter(conn, def)) {
            if (VIR_STRDUP(names[count], udev_device_get_sysname(dev)) < 0) {
                udev_device_unref(dev);
                virInterfaceDefFree(def);
                goto error;
            }
            count++;
245
        }
246
        udev_device_unref(dev);
247
        virInterfaceDefFree(def);
248 249 250 251 252 253 254
    }

    udev_enumerate_unref(enumerate);
    udev_unref(udev);

    return count;

255
 error:
256 257 258 259 260 261 262 263 264 265 266
    if (enumerate)
        udev_enumerate_unref(enumerate);
    udev_unref(udev);

    for (names_len = 0; names_len < count; names_len++)
        VIR_FREE(names[names_len]);

    return -1;
}

static int
267
udevConnectNumOfInterfaces(virConnectPtr conn)
268
{
269 270 271
    if (virConnectNumOfInterfacesEnsureACL(conn) < 0)
        return -1;

272 273
    return udevNumOfInterfacesByStatus(conn, VIR_UDEV_IFACE_ACTIVE,
                                       virConnectNumOfInterfacesCheckACL);
274 275 276
}

static int
277 278 279
udevConnectListInterfaces(virConnectPtr conn,
                          char **const names,
                          int names_len)
280
{
281 282 283
    if (virConnectListInterfacesEnsureACL(conn) < 0)
        return -1;

284
    return udevListInterfacesByStatus(conn, names, names_len,
285 286
                                      VIR_UDEV_IFACE_ACTIVE,
                                      virConnectListInterfacesCheckACL);
287 288 289
}

static int
290
udevConnectNumOfDefinedInterfaces(virConnectPtr conn)
291
{
292 293 294
    if (virConnectNumOfDefinedInterfacesEnsureACL(conn) < 0)
        return -1;

295 296
    return udevNumOfInterfacesByStatus(conn, VIR_UDEV_IFACE_INACTIVE,
                                       virConnectNumOfDefinedInterfacesCheckACL);
297 298 299
}

static int
300 301 302
udevConnectListDefinedInterfaces(virConnectPtr conn,
                                 char **const names,
                                 int names_len)
303
{
304 305 306
    if (virConnectListDefinedInterfacesEnsureACL(conn) < 0)
        return -1;

307
    return udevListInterfacesByStatus(conn, names, names_len,
308 309
                                      VIR_UDEV_IFACE_INACTIVE,
                                      virConnectListDefinedInterfacesCheckACL);
310 311
}

312
#define MATCH(FLAG) (flags & (FLAG))
313
static int
314 315 316
udevConnectListAllInterfaces(virConnectPtr conn,
                             virInterfacePtr **ifaces,
                             unsigned int flags)
317 318 319 320 321
{
    struct udev *udev;
    struct udev_enumerate *enumerate = NULL;
    struct udev_list_entry *devices;
    struct udev_list_entry *dev_entry;
322
    virInterfacePtr *ifaces_list = NULL;
323 324 325 326 327 328
    virInterfacePtr iface_obj;
    int tmp_count;
    int count = 0;
    int status = 0;
    int ret;

329
    virCheckFlags(VIR_CONNECT_LIST_INTERFACES_FILTERS_ACTIVE, -1);
330

331 332 333
    if (virConnectListAllInterfacesEnsureACL(conn) < 0)
        return -1;

334
    /* Grab a udev reference */
335
    udev = udev_ref(driver->udev);
336 337

    /* List all interfaces in case we support more filter flags in the future */
338
    enumerate = udevGetDevices(udev, VIR_UDEV_IFACE_ALL);
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365

    if (!enumerate) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to get list of %s interfaces on host"),
                       virUdevStatusString(status));
        ret = -1;
        goto cleanup;
    }

    /* Do the scan to load up the enumeration */
    udev_enumerate_scan_devices(enumerate);

    /* Get a list we can walk */
    devices = udev_enumerate_get_list_entry(enumerate);

    /* For each item so we can count */
    udev_list_entry_foreach(dev_entry, devices) {
        count++;
    }

    /* If we've got nothing, exit out */
    if (count == 0) {
        ret = 0;
        goto cleanup;
    }

    /* If we're asked for the ifaces then alloc up memory */
366 367 368
    if (ifaces && VIR_ALLOC_N(ifaces_list, count + 1) < 0) {
        ret = -1;
        goto cleanup;
369 370 371 372 373 374 375 376 377 378 379 380 381 382
    }

    /* Get a list we can walk */
    devices = udev_enumerate_get_list_entry(enumerate);

    /* reset our iterator */
    count = 0;

    /* Walk through each device */
    udev_list_entry_foreach(dev_entry, devices) {
        struct udev_device *dev;
        const char *path;
        const char *name;
        const char *macaddr;
383
        virInterfaceDefPtr def;
384 385 386 387 388 389 390

        path = udev_list_entry_get_name(dev_entry);
        dev = udev_device_new_from_syspath(udev, path);
        name = udev_device_get_sysname(dev);
        macaddr = udev_device_get_sysattr_value(dev, "address");
        status = STREQ(udev_device_get_sysattr_value(dev, "operstate"), "up");

391 392 393 394 395 396 397 398
        def = udevGetMinimalDefForDevice(dev);
        if (!virConnectListAllInterfacesCheckACL(conn, def)) {
            udev_device_unref(dev);
            virInterfaceDefFree(def);
            continue;
        }
        virInterfaceDefFree(def);

399
        /* Filter the results */
400 401 402 403 404 405
        if (MATCH(VIR_CONNECT_LIST_INTERFACES_FILTERS_ACTIVE) &&
            !((MATCH(VIR_CONNECT_LIST_INTERFACES_ACTIVE) && status) ||
              (MATCH(VIR_CONNECT_LIST_INTERFACES_INACTIVE) && !status))) {
            udev_device_unref(dev);
            continue;
        }
406 407

        /* If we matched a filter, then add it */
408 409 410
        if (ifaces) {
            iface_obj = virGetInterface(conn, name, macaddr);
            ifaces_list[count++] = iface_obj;
411
        }
412
        udev_device_unref(dev);
413 414 415 416 417 418 419 420 421 422
    }

    /* Drop our refcounts */
    udev_enumerate_unref(enumerate);
    udev_unref(udev);

    /* Trim the array to its final size */
    if (ifaces) {
        ignore_value(VIR_REALLOC_N(ifaces_list, count + 1));
        *ifaces = ifaces_list;
423
        ifaces_list = NULL;
424 425 426 427
    }

    return count;

428
 cleanup:
429 430 431 432 433 434
    if (enumerate)
        udev_enumerate_unref(enumerate);
    udev_unref(udev);

    if (ifaces) {
        for (tmp_count = 0; tmp_count < count; tmp_count++)
435
            virObjectUnref(ifaces_list[tmp_count]);
436 437 438 439 440 441 442 443 444
    }

    VIR_FREE(ifaces_list);

    return ret;

}

static virInterfacePtr
445
udevInterfaceLookupByName(virConnectPtr conn, const char *name)
446
{
447
    struct udev *udev = udev_ref(driver->udev);
448 449
    struct udev_device *dev;
    virInterfacePtr ret = NULL;
450
    virInterfaceDefPtr def = NULL;
451 452 453 454 455 456 457

    /* get a device reference based on the device name */
    dev = udev_device_new_from_subsystem_sysname(udev, "net", name);
    if (!dev) {
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("couldn't find interface named '%s'"),
                       name);
458
        goto cleanup;
459 460
    }

461 462 463 464 465 466 467
    if (!(def = udevGetMinimalDefForDevice(dev)))
        goto cleanup;

    if (virInterfaceLookupByNameEnsureACL(conn, def) < 0)
       goto cleanup;

    ret = virGetInterface(conn, def->name, def->mac);
468 469
    udev_device_unref(dev);

470
 cleanup:
471
    udev_unref(udev);
472
    virInterfaceDefFree(def);
473 474 475 476 477

    return ret;
}

static virInterfacePtr
478
udevInterfaceLookupByMACString(virConnectPtr conn, const char *macstr)
479
{
480
    struct udev *udev = udev_ref(driver->udev);
481 482 483
    struct udev_enumerate *enumerate = NULL;
    struct udev_list_entry *dev_entry;
    struct udev_device *dev;
484
    virInterfaceDefPtr def = NULL;
485 486
    virInterfacePtr ret = NULL;

487
    enumerate = udevGetDevices(udev, VIR_UDEV_IFACE_ALL);
488 489 490 491 492

    if (!enumerate) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to lookup interface with MAC address '%s'"),
                       macstr);
493
        goto cleanup;
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
    }

    /* Match on MAC */
    udev_enumerate_add_match_sysattr(enumerate, "address", macstr);

    /* Do the scan to load up the enumeration */
    udev_enumerate_scan_devices(enumerate);

    /* Get a list we can walk */
    dev_entry = udev_enumerate_get_list_entry(enumerate);

    /* Check that we got something back */
    if (!dev_entry) {
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("couldn't find interface with MAC address '%s'"),
                       macstr);
510
        goto cleanup;
511 512 513 514 515 516 517
    }

    /* Check that we didn't get multiple items back */
    if (udev_list_entry_get_next(dev_entry)) {
        virReportError(VIR_ERR_MULTIPLE_INTERFACES,
                       _("the MAC address '%s' matches multiple interfaces"),
                       macstr);
518
        goto cleanup;
519 520 521
    }

    dev = udev_device_new_from_syspath(udev, udev_list_entry_get_name(dev_entry));
522 523 524 525 526 527 528 529

    if (!(def = udevGetMinimalDefForDevice(dev)))
        goto cleanup;

    if (virInterfaceLookupByMACStringEnsureACL(conn, def) < 0)
       goto cleanup;

    ret = virGetInterface(conn, def->name, def->mac);
530 531
    udev_device_unref(dev);

532
 cleanup:
533 534 535
    if (enumerate)
        udev_enumerate_unref(enumerate);
    udev_unref(udev);
536
    virInterfaceDefFree(def);
537 538 539 540

    return ret;
}

541 542 543 544 545 546 547 548
/**
 * Helper function for finding bond slaves using scandir()
 *
 * @param entry - directory entry passed by scandir()
 *
 * @return 1 if we want to add it to scandir's list, 0 if not.
 */
static int
549
udevBondScanDirFilter(const struct dirent *entry)
550 551 552 553 554 555 556 557 558 559 560 561
{
    /* This is ugly so if anyone has a better suggestion, please improve
     * this. Unfortunately the kernel stores everything in the top level
     * interface sysfs entry and references the slaves as slave_eth0 for
     * example.
     */
    if (STRPREFIX(entry->d_name, "slave_"))
        return 1;

    return 0;
}

562
/**
563
 * Helper function for finding bridge members using scandir()
564 565 566 567 568 569
 *
 * @param entry - directory entry passed by scandir()
 *
 * @return 1 if we want to add it to scandir's list, 0 if not.
 */
static int
570
udevBridgeScanDirFilter(const struct dirent *entry)
571 572 573 574
{
    if (STREQ(entry->d_name, ".") || STREQ(entry->d_name, ".."))
        return 0;

575 576 577 578 579
    /* Omit the domain interfaces from the list of bridge attached
     * devices. All we can do is check for the device name matching
     * vnet%d. Improvements to this check are welcome.
     */
    if (strlen(entry->d_name) >= 5) {
580
        if (STRPREFIX(entry->d_name, VIR_NET_GENERATED_TAP_PREFIX) &&
581 582 583 584
            c_isdigit(entry->d_name[4]))
            return 0;
    }

585 586 587 588
    return 1;
}


589 590 591
static int
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK
592 593 594 595
udevGetIfaceDefBond(struct udev *udev,
                    struct udev_device *dev,
                    const char *name,
                    virInterfaceDef *ifacedef)
596 597 598
{
    struct dirent **slave_list = NULL;
    int slave_count = 0;
599
    size_t i;
600 601 602 603 604 605 606 607 608 609 610 611 612
    const char *tmp_str;
    int tmp_int;

    /* Initial defaults */
    ifacedef->data.bond.target = NULL;
    ifacedef->data.bond.nbItf = 0;
    ifacedef->data.bond.itf = NULL;

    /* Set the bond specifics */
    tmp_str = udev_device_get_sysattr_value(dev, "bonding/downdelay");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bonding/downdelay' for '%s'"), name);
613
        goto error;
614 615 616 617 618
    }
    if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse 'bonding/downdelay' '%s' for '%s'"),
                tmp_str, name);
619
        goto error;
620 621 622 623 624 625 626
    }
    ifacedef->data.bond.downdelay = tmp_int;

    tmp_str = udev_device_get_sysattr_value(dev, "bonding/updelay");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bonding/updelay' for '%s'"), name);
627
        goto error;
628 629 630 631 632
    }
    if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse 'bonding/updelay' '%s' for '%s'"),
                tmp_str, name);
633
        goto error;
634 635 636 637 638 639 640
    }
    ifacedef->data.bond.updelay = tmp_int;

    tmp_str = udev_device_get_sysattr_value(dev, "bonding/miimon");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bonding/miimon' for '%s'"), name);
641
        goto error;
642 643 644 645 646
    }
    if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse 'bonding/miimon' '%s' for '%s'"),
                tmp_str, name);
647
        goto error;
648 649 650 651 652 653 654
    }
    ifacedef->data.bond.frequency = tmp_int;

    tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_interval");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bonding/arp_interval' for '%s'"), name);
655
        goto error;
656 657 658 659 660
    }
    if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse 'bonding/arp_interval' '%s' for '%s'"),
                tmp_str, name);
661
        goto error;
662 663 664 665 666 667 668 669 670 671 672 673
    }
    ifacedef->data.bond.interval = tmp_int;

    /* bonding/mode is in the format: "balance-rr 0" so we find the
     * space and increment the pointer to get the number and convert
     * it to an interger. libvirt uses 1 through 7 while the raw
     * number is 0 through 6 so increment it by 1.
     */
    tmp_str = udev_device_get_sysattr_value(dev, "bonding/mode");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bonding/mode' for '%s'"), name);
674
        goto error;
675 676 677 678 679
    }
    tmp_str = strchr(tmp_str, ' ');
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Invalid format for 'bonding/mode' for '%s'"), name);
680
        goto error;
681 682 683 684 685
    }
    if (strlen(tmp_str) < 2) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Unable to find correct value in 'bonding/mode' for '%s'"),
                name);
686
        goto error;
687 688 689 690 691
    }
    if (virStrToLong_i(tmp_str + 1, NULL, 10, &tmp_int) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse 'bonding/mode' '%s' for '%s'"),
                tmp_str, name);
692
        goto error;
693 694 695 696 697 698 699 700 701 702 703
    }
    ifacedef->data.bond.mode = tmp_int + 1;

    /* bonding/arp_validate is in the format: "none 0" so we find the
     * space and increment the pointer to get the number and convert
     * it to an interger.
     */
    tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_validate");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bonding/arp_validate' for '%s'"), name);
704
        goto error;
705 706 707 708 709
    }
    tmp_str = strchr(tmp_str, ' ');
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Invalid format for 'bonding/arp_validate' for '%s'"), name);
710
        goto error;
711 712 713 714 715
    }
    if (strlen(tmp_str) < 2) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Unable to find correct value in 'bonding/arp_validate' "
                "for '%s'"), name);
716
        goto error;
717 718 719 720 721
    }
    if (virStrToLong_i(tmp_str + 1, NULL, 10, &tmp_int) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse 'bonding/arp_validate' '%s' for '%s'"),
                tmp_str, name);
722
        goto error;
723 724 725 726 727 728 729 730
    }
    ifacedef->data.bond.validate = tmp_int;

    /* bonding/use_carrier is 0 or 1 and libvirt stores it as 1 or 2. */
    tmp_str = udev_device_get_sysattr_value(dev, "bonding/use_carrier");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bonding/use_carrier' for '%s'"), name);
731
        goto error;
732 733 734 735 736
    }
    if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse 'bonding/use_carrier' '%s' for '%s'"),
                tmp_str, name);
737
        goto error;
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
    }
    ifacedef->data.bond.carrier = tmp_int + 1;

    /* MII or ARP Monitoring is based on arp_interval and miimon.
     * if arp_interval > 0 then ARP monitoring is in play, if
     * miimon > 0 then MII monitoring is in play.
     */
    if (ifacedef->data.bond.interval > 0)
        ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP;
    else if (ifacedef->data.bond.frequency > 0)
        ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII;
    else
        ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_NONE;

    tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_ip_target");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bonding/arp_ip_target' for '%s'"), name);
756
        goto error;
757
    }
758
    if (VIR_STRDUP(ifacedef->data.bond.target, tmp_str) < 0)
759
        goto error;
760 761 762 763

    /* Slaves of the bond */
    /* Get each slave in the bond */
    slave_count = scandir(udev_device_get_syspath(dev), &slave_list,
764
            udevBondScanDirFilter, alphasort);
765 766 767 768

    if (slave_count < 0) {
        virReportSystemError(errno,
                _("Could not get slaves of bond '%s'"), name);
769
        goto error;
770 771 772
    }

    /* Allocate our list of slave devices */
773
    if (VIR_ALLOC_N(ifacedef->data.bond.itf, slave_count) < 0)
774
        goto error;
775 776 777 778 779 780 781
    ifacedef->data.bond.nbItf = slave_count;

    for (i = 0; i < slave_count; i++) {
        /* Names are slave_interface. e.g. slave_eth0
         * so we use the part after the _
         */
        tmp_str = strchr(slave_list[i]->d_name, '_');
782 783 784 785
        if (!tmp_str || strlen(tmp_str) < 2) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Invalid enslaved interface name '%s' seen for "
                             "bond '%s'"), slave_list[i]->d_name, name);
786
            goto error;
787 788
        }
        /* go past the _ */
789 790 791
        tmp_str++;

        ifacedef->data.bond.itf[i] =
792
            udevGetIfaceDef(udev, tmp_str);
793 794 795 796
        if (!ifacedef->data.bond.itf[i]) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not get interface information for '%s', which is "
                  "a enslaved in bond '%s'"), slave_list[i]->d_name, name);
797
            goto error;
798 799 800 801 802 803 804 805
        }
        VIR_FREE(slave_list[i]);
    }

    VIR_FREE(slave_list);

    return 0;

806
 error:
807
    for (i = 0; slave_count != -1 && i < slave_count; i++)
808 809 810 811 812 813
        VIR_FREE(slave_list[i]);
    VIR_FREE(slave_list);

    return -1;
}

814 815 816
static int
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK
817 818 819 820
udevGetIfaceDefBridge(struct udev *udev,
                      struct udev_device *dev,
                      const char *name,
                      virInterfaceDef *ifacedef)
821 822 823 824
{
    struct dirent **member_list = NULL;
    int member_count = 0;
    char *member_path;
825
    const char *tmp_str;
826
    int stp;
827
    size_t i;
828 829 830 831

    /* Set our type to Bridge  */
    ifacedef->type = VIR_INTERFACE_TYPE_BRIDGE;

832 833 834 835 836 837 838 839
    /* Retrieve the forward delay */
    tmp_str = udev_device_get_sysattr_value(dev, "bridge/forward_delay");
    if (!tmp_str) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not retrieve 'bridge/forward_delay' for '%s'"), name);
        goto error;
    }

840
    if (VIR_STRDUP(ifacedef->data.bridge.delay, tmp_str) < 0)
841
        goto error;
842

843 844 845
    /* Retrieve Spanning Tree State. Valid values = -1, 0, 1 */
    tmp_str = udev_device_get_sysattr_value(dev, "bridge/stp_state");
    if (!tmp_str) {
846
        virReportError(VIR_ERR_INTERNAL_ERROR,
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
            _("Could not retrieve 'bridge/stp_state' for '%s'"), name);
        goto error;
    }

    if (virStrToLong_i(tmp_str, NULL, 10, &stp) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse 'bridge/stp_state' '%s' for '%s'"),
                tmp_str, name);
        goto error;
    }

    switch (stp) {
    case -1:
    case 0:
    case 1:
        ifacedef->data.bridge.stp = stp;
        break;
    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
            _("Invalid STP state value %d received for '%s'. Must be "
              "-1, 0, or 1."), stp, name);
        goto error;
869 870 871 872
    }

    /* Members of the bridge */
    if (virAsprintf(&member_path, "%s/%s",
873
                udev_device_get_syspath(dev), "brif") < 0)
874
        goto error;
875 876 877

    /* Get each member of the bridge */
    member_count = scandir(member_path, &member_list,
878
            udevBridgeScanDirFilter, alphasort);
879 880 881 882 883 884 885 886

    /* Don't need the path anymore */
    VIR_FREE(member_path);

    if (member_count < 0) {
        virReportSystemError(errno,
                _("Could not get members of bridge '%s'"),
                name);
887
        goto error;
888 889 890
    }

    /* Allocate our list of member devices */
891
    if (VIR_ALLOC_N(ifacedef->data.bridge.itf, member_count) < 0)
892
        goto error;
893 894
    ifacedef->data.bridge.nbItf = member_count;

N
Nitesh Konkar 已提交
895
    /* Get the interface definitions for each member of the bridge */
896 897
    for (i = 0; i < member_count; i++) {
        ifacedef->data.bridge.itf[i] =
898
            udevGetIfaceDef(udev, member_list[i]->d_name);
899 900 901 902 903 904
        if (!ifacedef->data.bridge.itf[i]) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not get interface information for '%s', which is "
                  "a member of bridge '%s'"), member_list[i]->d_name, name);
            goto error;
        }
905 906 907 908 909 910 911
        VIR_FREE(member_list[i]);
    }

    VIR_FREE(member_list);

    return 0;

912
 error:
913
    for (i = 0; member_count != -1 && i < member_count; i++)
914 915 916 917 918
        VIR_FREE(member_list[i]);
    VIR_FREE(member_list);

    return -1;
}
919

920 921 922
static int
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK
923 924 925 926
udevGetIfaceDefVlan(struct udev *udev ATTRIBUTE_UNUSED,
                    struct udev_device *dev ATTRIBUTE_UNUSED,
                    const char *name,
                    virInterfaceDef *ifacedef)
927
{
928 929 930 931 932 933 934 935 936 937 938 939 940
    char *procpath = NULL;
    char *buf = NULL;
    char *vid_pos, *dev_pos;
    size_t vid_len, dev_len;
    const char *vid_prefix = "VID: ";
    const char *dev_prefix = "\nDevice: ";
    int ret = -1;

    if (virAsprintf(&procpath, "/proc/net/vlan/%s", name) < 0)
        goto cleanup;

    if (virFileReadAll(procpath, BUFSIZ, &buf) < 0)
        goto cleanup;
941

942
    if ((vid_pos = strstr(buf, vid_prefix)) == NULL) {
943
        virReportError(VIR_ERR_INTERNAL_ERROR,
944 945
                       _("failed to find the VID for the VLAN device '%s'"),
                       name);
946
        goto cleanup;
947
    }
948
    vid_pos += strlen(vid_prefix);
949

950 951 952 953 954 955 956
    if ((vid_len = strspn(vid_pos, "0123456789")) == 0 ||
        !c_isspace(vid_pos[vid_len])) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to find the VID for the VLAN device '%s'"),
                       name);
        goto cleanup;
    }
957

958 959 960 961 962 963 964
    if ((dev_pos = strstr(vid_pos + vid_len, dev_prefix)) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to find the real device for the VLAN device '%s'"),
                       name);
        goto cleanup;
    }
    dev_pos += strlen(dev_prefix);
965

966 967 968 969 970 971
    if ((dev_len = strcspn(dev_pos, "\n")) == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to find the real device for the VLAN device '%s'"),
                       name);
        goto cleanup;
    }
972

973 974
    if (VIR_STRNDUP(ifacedef->data.vlan.tag, vid_pos, vid_len) < 0)
        goto cleanup;
975
    if (VIR_STRNDUP(ifacedef->data.vlan.dev_name, dev_pos, dev_len) < 0) {
976 977 978 979 980 981 982 983 984 985
        VIR_FREE(ifacedef->data.vlan.tag);
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(procpath);
    VIR_FREE(buf);
    return ret;
986 987
}

988
static virInterfaceDef * ATTRIBUTE_NONNULL(1)
989
udevGetIfaceDef(struct udev *udev, const char *name)
990 991 992 993 994 995
{
    struct udev_device *dev = NULL;
    virInterfaceDef *ifacedef;
    unsigned int mtu;
    const char *mtu_str;
    char *vlan_parent_dev = NULL;
996
    const char *devtype;
997 998

    /* Allocate our interface definition structure */
999
    if (VIR_ALLOC(ifacedef) < 0)
1000 1001 1002 1003
        return NULL;

    /* Clear our structure and set safe defaults */
    ifacedef->startmode = VIR_INTERFACE_START_UNSPECIFIED;
1004
    if (VIR_STRDUP(ifacedef->name, name) < 0)
1005
        goto error;
1006 1007 1008 1009 1010 1011

    /* Lookup the device we've been asked about */
    dev = udev_device_new_from_subsystem_sysname(udev, "net", name);
    if (!dev) {
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("couldn't find interface named '%s'"), name);
1012
        goto error;
1013 1014 1015
    }

    /* MAC address */
1016 1017
    if (VIR_STRDUP(ifacedef->mac,
                   udev_device_get_sysattr_value(dev, "address")) < 0)
1018
        goto error;
1019

1020 1021 1022 1023
    /* Link state and speed */
    if (virNetDevGetLinkInfo(ifacedef->name, &ifacedef->lnk) < 0)
        goto error;

1024 1025 1026 1027 1028
    /* MTU */
    mtu_str = udev_device_get_sysattr_value(dev, "mtu");
    if (virStrToLong_ui(mtu_str, NULL, 10, &mtu) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                _("Could not parse MTU value '%s'"), mtu_str);
1029
        goto error;
1030 1031 1032 1033 1034 1035 1036 1037
    }
    ifacedef->mtu = mtu;

    /* Number of IP protocols this interface has assigned */
    /* XXX: Do we want a netlink query or a call out to ip or leave it? */
    ifacedef->nprotos = 0;
    ifacedef->protos = NULL;

1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
    /* Check the type of device we are working with based on the devtype */
    devtype = udev_device_get_devtype(dev);

    /* Set our type to ethernet as the default case */
    ifacedef->type = VIR_INTERFACE_TYPE_ETHERNET;

    if (STREQ_NULLABLE(devtype, "vlan")) {
        /* This only works on modern kernels (3.7 and newer)
         * e949b09b71d975a82f13ac88ce4ad338fed213da
         */
        ifacedef->type = VIR_INTERFACE_TYPE_VLAN;
    } else if (STREQ_NULLABLE(devtype, "bridge")) {
        ifacedef->type = VIR_INTERFACE_TYPE_BRIDGE;
1051 1052 1053
    } else if (STREQ_NULLABLE(devtype, "bond")) {
        /* This only works on modern kernels (3.9 and newer) */
        ifacedef->type = VIR_INTERFACE_TYPE_BOND;
1054 1055 1056 1057 1058 1059 1060 1061
    }

    /* Fallback checks if the devtype check didn't work. */
    if (ifacedef->type == VIR_INTERFACE_TYPE_ETHERNET) {
        /* First check if its a VLAN based on the name containing a dot,
         * to prevent false positives
         */
        vlan_parent_dev = strrchr(name, '.');
1062
        if (vlan_parent_dev)
1063
            ifacedef->type = VIR_INTERFACE_TYPE_VLAN;
1064 1065

        /* Fallback check to see if this is a bond device */
1066
        if (udev_device_get_sysattr_value(dev, "bonding/mode"))
1067
            ifacedef->type = VIR_INTERFACE_TYPE_BOND;
1068 1069 1070 1071
    }

    switch (ifacedef->type) {
    case VIR_INTERFACE_TYPE_VLAN:
1072
        if (udevGetIfaceDefVlan(udev, dev, name, ifacedef) < 0)
1073
            goto error;
1074 1075
        break;
    case VIR_INTERFACE_TYPE_BRIDGE:
1076
        if (udevGetIfaceDefBridge(udev, dev, name, ifacedef) < 0)
1077
            goto error;
1078
        break;
1079
    case VIR_INTERFACE_TYPE_BOND:
1080
        if (udevGetIfaceDefBond(udev, dev, name, ifacedef) < 0)
1081
            goto error;
1082
        break;
1083 1084
    case VIR_INTERFACE_TYPE_ETHERNET:
        break;
1085 1086 1087 1088 1089 1090
    }

    udev_device_unref(dev);

    return ifacedef;

1091
 error:
1092 1093
    udev_device_unref(dev);

1094
    virInterfaceDefFree(ifacedef);
1095 1096 1097 1098 1099

    return NULL;
}

static char *
1100 1101
udevInterfaceGetXMLDesc(virInterfacePtr ifinfo,
                        unsigned int flags)
1102
{
1103
    struct udev *udev = udev_ref(driver->udev);
1104 1105 1106 1107 1108 1109 1110 1111
    virInterfaceDef *ifacedef;
    char *xmlstr = NULL;

    virCheckFlags(VIR_INTERFACE_XML_INACTIVE, NULL);

    /* Recursively build up the interface XML based on the requested
     * interface name
     */
1112
    ifacedef = udevGetIfaceDef(udev, ifinfo->name);
1113 1114

    if (!ifacedef)
1115
        goto cleanup;
1116

1117 1118 1119
    if (virInterfaceGetXMLDescEnsureACL(ifinfo->conn, ifacedef) < 0)
        goto cleanup;

1120 1121
    xmlstr = virInterfaceDefFormat(ifacedef);

1122
    virInterfaceDefFree(ifacedef);
1123

1124
 cleanup:
1125 1126 1127 1128 1129 1130
    /* decrement our udev ptr */
    udev_unref(udev);

    return xmlstr;
}

1131
static int
1132
udevInterfaceIsActive(virInterfacePtr ifinfo)
1133
{
1134
    struct udev *udev = udev_ref(driver->udev);
1135
    struct udev_device *dev;
1136 1137
    virInterfaceDefPtr def = NULL;
    int status = -1;
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147

    dev = udev_device_new_from_subsystem_sysname(udev, "net",
                                                 ifinfo->name);
    if (!dev) {
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("couldn't find interface named '%s'"),
                       ifinfo->name);
        goto cleanup;
    }

1148 1149 1150 1151 1152 1153
    if (!(def = udevGetMinimalDefForDevice(dev)))
        goto cleanup;

    if (virInterfaceIsActiveEnsureACL(ifinfo->conn, def) < 0)
       goto cleanup;

1154 1155 1156 1157 1158
    /* Check if it's active or not */
    status = STREQ(udev_device_get_sysattr_value(dev, "operstate"), "up");

    udev_device_unref(dev);

1159
 cleanup:
1160
    udev_unref(udev);
1161
    virInterfaceDefFree(def);
1162 1163 1164 1165

    return status;
}

1166

1167 1168 1169
static int
udevStateCleanup(void);

1170
static int
1171
udevStateInitialize(bool privileged,
1172 1173 1174 1175 1176 1177 1178 1179
                    virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                    void *opaque ATTRIBUTE_UNUSED)
{
    int ret = -1;

    if (VIR_ALLOC(driver) < 0)
        goto cleanup;

1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
    driver->lockFD = -1;

    if (privileged) {
        if (virAsprintf(&driver->stateDir,
                        "%s/run/libvirt/nodedev", LOCALSTATEDIR) < 0)
            goto cleanup;
    } else {
        VIR_AUTOFREE(char *) rundir = NULL;

        if (!(rundir = virGetUserRuntimeDirectory()))
            goto cleanup;
        if (virAsprintf(&driver->stateDir, "%s/nodedev/run", rundir) < 0)
            goto cleanup;
    }

    if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
        virReportSystemError(errno, _("cannot create state directory '%s'"),
                             driver->stateDir);
        goto cleanup;
    }

    if ((driver->lockFD =
         virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
        goto cleanup;

1205 1206 1207 1208 1209 1210
    driver->udev = udev_new();
    if (!driver->udev) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to create udev context"));
        goto cleanup;
    }
1211
    driver->privileged = privileged;
1212 1213 1214 1215

    ret = 0;

 cleanup:
1216 1217
    if (ret < 0)
        udevStateCleanup();
1218 1219 1220 1221 1222 1223 1224 1225 1226
    return ret;
}

static int
udevStateCleanup(void)
{
    if (!driver)
        return -1;

1227 1228 1229 1230 1231
    if (driver->udev)
        udev_unref(driver->udev);

    if (driver->lockFD != -1)
        virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
1232

1233
    VIR_FREE(driver->stateDir);
1234 1235 1236 1237 1238
    VIR_FREE(driver);
    return 0;
}


1239 1240 1241 1242 1243 1244 1245 1246
static virDrvOpenStatus
udevConnectOpen(virConnectPtr conn,
                virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                virConfPtr conf ATTRIBUTE_UNUSED,
                unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
    if (driver == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("interface state driver is not active"));
        return VIR_DRV_OPEN_ERROR;
    }

    if (driver->privileged) {
        if (STRNEQ(conn->uri->path, "/system")) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected interface URI path '%s', try interface:///system"),
                           conn->uri->path);
1258 1259
            return VIR_DRV_OPEN_ERROR;
        }
1260 1261 1262 1263 1264 1265
    } else {
        if (STRNEQ(conn->uri->path, "/session")) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected interface URI path '%s', try interface:///session"),
                           conn->uri->path);
            return VIR_DRV_OPEN_ERROR;
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
        }
    }

    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

    return VIR_DRV_OPEN_SUCCESS;
}

static int udevConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return 0;
}


static int udevConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* Trivially secure, since always inside the daemon */
    return 1;
}


static int udevConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* Not encrypted, but remote driver takes care of that */
    return 0;
}


static int udevConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return 1;
}


1301
static virInterfaceDriver udevIfaceDriver = {
1302
    .name = "udev",
1303 1304 1305 1306 1307 1308 1309 1310 1311
    .connectNumOfInterfaces = udevConnectNumOfInterfaces, /* 1.0.0 */
    .connectListInterfaces = udevConnectListInterfaces, /* 1.0.0 */
    .connectNumOfDefinedInterfaces = udevConnectNumOfDefinedInterfaces, /* 1.0.0 */
    .connectListDefinedInterfaces = udevConnectListDefinedInterfaces, /* 1.0.0 */
    .connectListAllInterfaces = udevConnectListAllInterfaces, /* 1.0.0 */
    .interfaceLookupByName = udevInterfaceLookupByName, /* 1.0.0 */
    .interfaceLookupByMACString = udevInterfaceLookupByMACString, /* 1.0.0 */
    .interfaceIsActive = udevInterfaceIsActive, /* 1.0.0 */
    .interfaceGetXMLDesc = udevInterfaceGetXMLDesc, /* 1.0.0 */
1312 1313
};

1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325

static virHypervisorDriver udevHypervisorDriver = {
    .name = "interface",
    .connectOpen = udevConnectOpen, /* 4.1.0 */
    .connectClose = udevConnectClose, /* 4.1.0 */
    .connectIsEncrypted = udevConnectIsEncrypted, /* 4.1.0 */
    .connectIsSecure = udevConnectIsSecure, /* 4.1.0 */
    .connectIsAlive = udevConnectIsAlive, /* 4.1.0 */
};


static virConnectDriver udevConnectDriver = {
1326
    .localOnly = true,
1327
    .uriSchemes = (const char *[]){ "interface", NULL },
1328 1329 1330 1331 1332
    .hypervisorDriver = &udevHypervisorDriver,
    .interfaceDriver = &udevIfaceDriver,
};


1333 1334 1335 1336 1337 1338
static virStateDriver interfaceStateDriver = {
    .name = "udev",
    .stateInitialize = udevStateInitialize,
    .stateCleanup = udevStateCleanup,
};

1339
int
1340 1341
udevIfaceRegister(void)
{
1342 1343
    if (virRegisterConnectDriver(&udevConnectDriver, false) < 0)
        return -1;
1344
    if (virSetSharedInterfaceDriver(&udevIfaceDriver) < 0) {
1345 1346 1347 1348
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to register udev interface driver"));
        return -1;
    }
1349 1350
    if (virRegisterStateDriver(&interfaceStateDriver) < 0)
        return -1;
1351 1352
    return 0;
}