interface_conf.c 39.3 KB
Newer Older
1 2 3
/*
 * interface_conf.c: interfaces XML handling
 *
4
 * Copyright (C) 2006-2010 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16
 *
 * 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
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
 *
 * Author: Daniel Veillard <veillard@redhat.com>
 *         Laine Stump <laine@redhat.com>
 */

#include <config.h>
#include "virterror_internal.h"
#include "datatypes.h"

#include "interface_conf.h"

#include "memory.h"
#include "xml.h"
#include "uuid.h"
#include "util.h"
#include "buf.h"

#define VIR_FROM_THIS VIR_FROM_INTERFACE

VIR_ENUM_IMPL(virInterface,
              VIR_INTERFACE_TYPE_LAST,
40
              "ethernet", "bridge", "bond", "vlan")
41

42
static virInterfaceDefPtr
43
virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType);
44
static int
45
virInterfaceDefDevFormat(virBufferPtr buf,
46 47
                         const virInterfaceDefPtr def, int level);

48 49 50 51 52
static
void virInterfaceIpDefFree(virInterfaceIpDefPtr def) {
    if (def == NULL)
        return;
    VIR_FREE(def->address);
53
    VIR_FREE(def);
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
}

static
void virInterfaceProtocolDefFree(virInterfaceProtocolDefPtr def) {
    int ii;

    if (def == NULL)
        return;
    for (ii = 0; ii < def->nips; ii++) {
        virInterfaceIpDefFree(def->ips[ii]);
    }
    VIR_FREE(def->ips);
    VIR_FREE(def->family);
    VIR_FREE(def->gateway);
    VIR_FREE(def);
}

71 72
void virInterfaceDefFree(virInterfaceDefPtr def)
{
73
    int i, pp;
74 75 76 77 78 79 80 81 82

    if (def == NULL)
        return;

    VIR_FREE(def->name);
    VIR_FREE(def->mac);

    switch (def->type) {
        case VIR_INTERFACE_TYPE_BRIDGE:
83
            VIR_FREE(def->data.bridge.delay);
84
            for (i = 0;i < def->data.bridge.nbItf;i++) {
85
                if (def->data.bridge.itf[i] == NULL)
86
                    break; /* to cope with half parsed data on errors */
87
                virInterfaceDefFree(def->data.bridge.itf[i]);
88 89 90 91 92 93
            }
            VIR_FREE(def->data.bridge.itf);
            break;
        case VIR_INTERFACE_TYPE_BOND:
            VIR_FREE(def->data.bond.target);
            for (i = 0;i < def->data.bond.nbItf;i++) {
94
                if (def->data.bond.itf[i] == NULL)
95
                    break; /* to cope with half parsed data on errors */
96
                virInterfaceDefFree(def->data.bond.itf[i]);
97 98 99 100 101 102 103 104 105
            }
            VIR_FREE(def->data.bond.itf);
            break;
        case VIR_INTERFACE_TYPE_VLAN:
            VIR_FREE(def->data.vlan.tag);
            VIR_FREE(def->data.vlan.devname);
            break;
    }

106 107 108 109 110
    /* free all protos */
    for (pp = 0; pp < def->nprotos; pp++) {
        virInterfaceProtocolDefFree(def->protos[pp]);
    }
    VIR_FREE(def->protos);
111 112 113 114
    VIR_FREE(def);
}

static int
115
virInterfaceDefParseName(virInterfaceDefPtr def,
116
                         xmlXPathContextPtr ctxt) {
117 118
    char *tmp;

119
    tmp = virXPathString("string(./@name)", ctxt);
120
    if (tmp == NULL) {
121 122
        virReportError(VIR_ERR_XML_ERROR,
                       "%s",  _("interface has no name"));
123
        return -1;
124 125
    }
    def->name = tmp;
126
    return 0;
127 128 129
}

static int
130
virInterfaceDefParseMtu(virInterfaceDefPtr def,
131 132 133
                        xmlXPathContextPtr ctxt) {
    unsigned long mtu;
    int ret;
134

135
    ret = virXPathULong("string(./mtu/@size)", ctxt, &mtu);
136
    if ((ret == -2) || ((ret == 0) && (mtu > 100000))) {
137 138
        virReportError(VIR_ERR_XML_ERROR,
                       "%s", _("interface mtu value is improper"));
139
        return -1;
140 141 142
    } else if (ret == 0) {
        def->mtu = (unsigned int) mtu;
    }
143
    return 0;
144 145 146
}

static int
147
virInterfaceDefParseStartMode(virInterfaceDefPtr def,
148 149 150
                              xmlXPathContextPtr ctxt) {
    char *tmp;

151
    tmp = virXPathString("string(./start/@mode)", ctxt);
152 153 154
    if (tmp == NULL)
        def->startmode = VIR_INTERFACE_START_UNSPECIFIED;
    else if (STREQ(tmp, "onboot"))
155 156 157 158 159 160
        def->startmode = VIR_INTERFACE_START_ONBOOT;
    else if (STREQ(tmp, "hotplug"))
        def->startmode = VIR_INTERFACE_START_HOTPLUG;
    else if (STREQ(tmp, "none"))
        def->startmode = VIR_INTERFACE_START_NONE;
    else {
161 162
        virReportError(VIR_ERR_XML_ERROR,
                       _("unknown interface startmode %s"), tmp);
163
        VIR_FREE(tmp);
164
        return -1;
165 166
    }
    VIR_FREE(tmp);
167
    return 0;
168 169 170
}

static int
171
virInterfaceDefParseBondMode(xmlXPathContextPtr ctxt) {
172 173 174
    char *tmp;
    int ret = 0;

175
    tmp = virXPathString("string(./@mode)", ctxt);
176
    if (tmp == NULL)
177
        return VIR_INTERFACE_BOND_NONE;
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    if (STREQ(tmp, "balance-rr"))
        ret = VIR_INTERFACE_BOND_BALRR;
    else if (STREQ(tmp, "active-backup"))
        ret = VIR_INTERFACE_BOND_ABACKUP;
    else if (STREQ(tmp, "balance-xor"))
        ret = VIR_INTERFACE_BOND_BALXOR;
    else if (STREQ(tmp, "broadcast"))
        ret = VIR_INTERFACE_BOND_BCAST;
    else if (STREQ(tmp, "802.3ad"))
        ret = VIR_INTERFACE_BOND_8023AD;
    else if (STREQ(tmp, "balance-tlb"))
        ret = VIR_INTERFACE_BOND_BALTLB;
    else if (STREQ(tmp, "balance-alb"))
        ret = VIR_INTERFACE_BOND_BALALB;
    else {
193 194
        virReportError(VIR_ERR_XML_ERROR,
                       _("unknown bonding mode %s"), tmp);
195 196 197
        ret = -1;
    }
    VIR_FREE(tmp);
198
    return ret;
199 200 201
}

static int
202
virInterfaceDefParseBondMiiCarrier(xmlXPathContextPtr ctxt) {
203 204 205
    char *tmp;
    int ret = 0;

206
    tmp = virXPathString("string(./miimon/@carrier)", ctxt);
207
    if (tmp == NULL)
208
        return VIR_INTERFACE_BOND_MII_NONE;
209 210 211 212 213
    if (STREQ(tmp, "ioctl"))
        ret = VIR_INTERFACE_BOND_MII_IOCTL;
    else if (STREQ(tmp, "netif"))
        ret = VIR_INTERFACE_BOND_MII_NETIF;
    else {
214 215
        virReportError(VIR_ERR_XML_ERROR,
                       _("unknown mii bonding carrier %s"), tmp);
216 217 218
        ret = -1;
    }
    VIR_FREE(tmp);
219
    return ret;
220 221 222
}

static int
223
virInterfaceDefParseBondArpValid(xmlXPathContextPtr ctxt) {
224 225 226
    char *tmp;
    int ret = 0;

227
    tmp = virXPathString("string(./arpmon/@validate)", ctxt);
228
    if (tmp == NULL)
229
        return VIR_INTERFACE_BOND_ARP_NONE;
230 231 232 233 234 235 236
    if (STREQ(tmp, "active"))
        ret = VIR_INTERFACE_BOND_ARP_ACTIVE;
    else if (STREQ(tmp, "backup"))
        ret = VIR_INTERFACE_BOND_ARP_BACKUP;
    else if (STREQ(tmp, "all"))
        ret = VIR_INTERFACE_BOND_ARP_ALL;
    else {
237 238
        virReportError(VIR_ERR_XML_ERROR,
                       _("unknown arp bonding validate %s"), tmp);
239 240 241
        ret = -1;
    }
    VIR_FREE(tmp);
242
    return ret;
243 244 245
}

static int
246
virInterfaceDefParseDhcp(virInterfaceProtocolDefPtr def,
247
                         xmlNodePtr dhcp, xmlXPathContextPtr ctxt) {
248
    xmlNodePtr save;
249 250 251
    char *tmp;
    int ret = 0;

252
    def->dhcp = 1;
253
    save = ctxt->node;
254 255
    ctxt->node = dhcp;
    /* Not much to do in the current version */
256
    tmp = virXPathString("string(./@peerdns)", ctxt);
257 258
    if (tmp) {
        if (STREQ(tmp, "yes"))
259
            def->peerdns = 1;
260
        else if (STREQ(tmp, "no"))
261
            def->peerdns = 0;
262
        else {
263 264
            virReportError(VIR_ERR_XML_ERROR,
                           _("unknown dhcp peerdns value %s"), tmp);
265 266 267 268
            ret = -1;
        }
        VIR_FREE(tmp);
    } else
269
        def->peerdns = -1;
270

271
    ctxt->node = save;
272
    return ret;
273 274 275
}

static int
276
virInterfaceDefParseIp(virInterfaceIpDefPtr def,
277
                       xmlXPathContextPtr ctxt) {
278 279 280 281
    int ret = 0;
    char *tmp;
    long l;

282
    tmp = virXPathString("string(./@address)", ctxt);
283
    def->address = tmp;
284
    if (tmp != NULL) {
285
        ret = virXPathLong("string(./@prefix)", ctxt, &l);
286
        if (ret == 0)
287
            def->prefix = (int) l;
288
        else if (ret == -2) {
289 290
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("Invalid ip address prefix value"));
291
            return -1;
292 293 294
        }
    }

295
    return 0;
296 297 298
}

static int
299
virInterfaceDefParseProtoIPv4(virInterfaceProtocolDefPtr def,
300
                              xmlXPathContextPtr ctxt) {
301 302 303 304 305
    xmlNodePtr dhcp;
    xmlNodePtr *ipNodes = NULL;
    int nIpNodes, ii, ret = -1;
    char *tmp;

306
    tmp = virXPathString("string(./route[1]/@gateway)", ctxt);
307
    def->gateway = tmp;
308

309
    dhcp = virXPathNode("./dhcp", ctxt);
310
    if (dhcp != NULL) {
311
        ret = virInterfaceDefParseDhcp(def, dhcp, ctxt);
312
        if (ret != 0)
313
           return ret;
314
    }
315

316
    nIpNodes = virXPathNodeSet("./ip", ctxt, &ipNodes);
317 318
    if (nIpNodes < 0)
        return -1;
319 320 321 322
    if (ipNodes == NULL)
        return 0;

    if (VIR_ALLOC_N(def->ips, nIpNodes) < 0) {
323
        virReportOOMError();
324 325 326 327 328 329 330
        goto error;
    }

    def->nips = 0;
    for (ii = 0; ii < nIpNodes; ii++) {

        virInterfaceIpDefPtr ip;
331

332
        if (VIR_ALLOC(ip) < 0) {
333
            virReportOOMError();
334 335 336 337
            goto error;
        }

        ctxt->node = ipNodes[ii];
338
        ret = virInterfaceDefParseIp(ip, ctxt);
339 340 341 342 343 344 345 346 347 348 349
        if (ret != 0) {
            virInterfaceIpDefFree(ip);
            goto error;
        }
        def->ips[def->nips++] = ip;
    }

    ret = 0;

error:
    VIR_FREE(ipNodes);
350
    return ret;
351 352 353
}

static int
354
virInterfaceDefParseProtoIPv6(virInterfaceProtocolDefPtr def,
355 356 357 358 359 360
                              xmlXPathContextPtr ctxt) {
    xmlNodePtr dhcp, autoconf;
    xmlNodePtr *ipNodes = NULL;
    int nIpNodes, ii, ret = -1;
    char *tmp;

361
    tmp = virXPathString("string(./route[1]/@gateway)", ctxt);
362 363
    def->gateway = tmp;

364
    autoconf = virXPathNode("./autoconf", ctxt);
365 366 367
    if (autoconf != NULL)
        def->autoconf = 1;

368
    dhcp = virXPathNode("./dhcp", ctxt);
369
    if (dhcp != NULL) {
370
        ret = virInterfaceDefParseDhcp(def, dhcp, ctxt);
371
        if (ret != 0)
372
           return ret;
373
    }
374

375
    nIpNodes = virXPathNodeSet("./ip", ctxt, &ipNodes);
376 377
    if (nIpNodes < 0)
        return -1;
378 379 380 381
    if (ipNodes == NULL)
        return 0;

    if (VIR_ALLOC_N(def->ips, nIpNodes) < 0) {
382
        virReportOOMError();
383 384 385 386 387 388 389 390 391
        goto error;
    }

    def->nips = 0;
    for (ii = 0; ii < nIpNodes; ii++) {

        virInterfaceIpDefPtr ip;

        if (VIR_ALLOC(ip) < 0) {
392
            virReportOOMError();
393 394 395 396
            goto error;
        }

        ctxt->node = ipNodes[ii];
397
        ret = virInterfaceDefParseIp(ip, ctxt);
398 399 400 401 402 403 404 405 406 407 408
        if (ret != 0) {
            virInterfaceIpDefFree(ip);
            goto error;
        }
        def->ips[def->nips++] = ip;
    }

    ret = 0;

error:
    VIR_FREE(ipNodes);
409
    return ret;
410 411 412
}

static int
413
virInterfaceDefParseIfAdressing(virInterfaceDefPtr def,
414
                                xmlXPathContextPtr ctxt) {
415 416 417
    xmlNodePtr save;
    xmlNodePtr *protoNodes = NULL;
    int nProtoNodes, pp, ret = -1;
418 419 420
    char *tmp;

    save = ctxt->node;
421

422
    nProtoNodes = virXPathNodeSet("./protocol", ctxt, &protoNodes);
423 424 425 426
    if (nProtoNodes < 0)
        goto error;

    if (nProtoNodes == 0) {
427 428
        /* no protocols is an acceptable outcome */
        return 0;
429
    }
430 431

    if (VIR_ALLOC_N(def->protos, nProtoNodes) < 0) {
432
        virReportOOMError();
433
        goto error;
434 435
    }

436 437 438 439 440 441
    def->nprotos = 0;
    for (pp = 0; pp < nProtoNodes; pp++) {

        virInterfaceProtocolDefPtr proto;

        if (VIR_ALLOC(proto) < 0) {
442
            virReportOOMError();
443 444 445 446
            goto error;
        }

        ctxt->node = protoNodes[pp];
447
        tmp = virXPathString("string(./@family)", ctxt);
448
        if (tmp == NULL) {
449 450
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("protocol misses the family attribute"));
451 452 453 454 455
            virInterfaceProtocolDefFree(proto);
            goto error;
        }
        proto->family = tmp;
        if (STREQ(tmp, "ipv4")) {
456
            ret = virInterfaceDefParseProtoIPv4(proto, ctxt);
457 458 459 460 461
            if (ret != 0) {
                virInterfaceProtocolDefFree(proto);
                goto error;
            }
        } else if (STREQ(tmp, "ipv6")) {
462
            ret = virInterfaceDefParseProtoIPv6(proto, ctxt);
463 464 465 466 467
            if (ret != 0) {
                virInterfaceProtocolDefFree(proto);
                goto error;
            }
        } else {
468 469
            virReportError(VIR_ERR_XML_ERROR,
                           _("unsupported protocol family '%s'"), tmp);
470 471 472 473 474 475 476 477 478 479
            virInterfaceProtocolDefFree(proto);
            goto error;
        }
        def->protos[def->nprotos++] = proto;
    }

    ret = 0;

error:
    VIR_FREE(protoNodes);
480
    ctxt->node = save;
481
    return ret;
482 483 484 485

}

static int
486
virInterfaceDefParseBridge(virInterfaceDefPtr def,
487 488 489
                           xmlXPathContextPtr ctxt) {
    xmlNodePtr *interfaces = NULL;
    xmlNodePtr bridge;
490
    virInterfaceDefPtr itf;
491 492 493 494
    int nbItf, i;
    int ret = 0;

    bridge = ctxt->node;
495
    nbItf = virXPathNodeSet("./interface", ctxt, &interfaces);
496
    if (nbItf < 0) {
497 498 499
        ret = -1;
        goto error;
    }
500 501
    if (nbItf > 0) {
        if (VIR_ALLOC_N(def->data.bridge.itf, nbItf) < 0) {
502
            virReportOOMError();
503 504 505
            ret = -1;
            goto error;
        }
506 507 508 509
        def->data.bridge.nbItf = nbItf;

        for (i = 0; i < nbItf;i++) {
            ctxt->node = interfaces[i];
510
            itf = virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_BRIDGE);
511 512 513 514 515 516 517
            if (itf == NULL) {
                ret = -1;
                def->data.bridge.nbItf = i;
                goto error;
            }
            def->data.bridge.itf[i] = itf;
        }
518 519 520 521 522
    }

error:
    VIR_FREE(interfaces);
    ctxt->node = bridge;
523
    return ret;
524 525 526
}

static int
527
virInterfaceDefParseBondItfs(virInterfaceDefPtr def,
528 529 530
                             xmlXPathContextPtr ctxt) {
    xmlNodePtr *interfaces = NULL;
    xmlNodePtr bond = ctxt->node;
531
    virInterfaceDefPtr itf;
532 533 534
    int nbItf, i;
    int ret = 0;

535
    nbItf = virXPathNodeSet("./interface", ctxt, &interfaces);
536 537 538 539 540 541
    if (nbItf < 0) {
        ret = -1;
        goto error;
    }

    if (nbItf == 0) {
542 543
        virReportError(VIR_ERR_XML_ERROR,
                       "%s", _("bond has no interfaces"));
544 545 546
        ret = -1;
        goto error;
    }
547

548
    if (VIR_ALLOC_N(def->data.bond.itf, nbItf) < 0) {
549
        virReportOOMError();
550 551 552 553 554 555 556
        ret = -1;
        goto error;
    }
    def->data.bond.nbItf = nbItf;

    for (i = 0; i < nbItf;i++) {
        ctxt->node = interfaces[i];
557
        itf = virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_BOND);
558 559 560 561 562 563 564 565 566 567 568
        if (itf == NULL) {
            ret = -1;
            def->data.bond.nbItf = i;
            goto error;
        }
        def->data.bond.itf[i] = itf;
    }

error:
    VIR_FREE(interfaces);
    ctxt->node = bond;
569
    return ret;
570 571 572
}

static int
573
virInterfaceDefParseBond(virInterfaceDefPtr def,
574
                         xmlXPathContextPtr ctxt) {
575
    int ret = -1;
576 577
    unsigned long tmp;

578
    def->data.bond.mode = virInterfaceDefParseBondMode(ctxt);
579 580 581
    if (def->data.bond.mode < 0)
        goto error;

582
    ret = virInterfaceDefParseBondItfs(def, ctxt);
583 584 585
    if (ret != 0)
       goto error;

586
    if (virXPathNode("./miimon[1]", ctxt) != NULL) {
587 588
        def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII;

589
        ret = virXPathULong("string(./miimon/@freq)", ctxt, &tmp);
590
        if ((ret == -2) || (ret == -1)) {
591 592
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface miimon freq missing or invalid"));
593 594 595 596
            goto error;
        }
        def->data.bond.frequency = (int) tmp;

597
        ret = virXPathULong("string(./miimon/@downdelay)", ctxt, &tmp);
598
        if (ret == -2) {
599 600
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface miimon downdelay invalid"));
601 602 603 604 605
            goto error;
        } else if (ret == 0) {
            def->data.bond.downdelay = (int) tmp;
        }

606
        ret = virXPathULong("string(./miimon/@updelay)", ctxt, &tmp);
607
        if (ret == -2) {
608 609
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface miimon updelay invalid"));
610 611 612 613 614
            goto error;
        } else if (ret == 0) {
            def->data.bond.updelay = (int) tmp;
        }

615
        def->data.bond.carrier = virInterfaceDefParseBondMiiCarrier(ctxt);
616 617
        if (def->data.bond.carrier < 0) {
            ret = -1;
618
            goto error;
619
        }
620

621
    } else if (virXPathNode("./arpmon[1]", ctxt) != NULL) {
622 623 624

        def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP;

625
        ret = virXPathULong("string(./arpmon/@interval)", ctxt, &tmp);
626
        if ((ret == -2) || (ret == -1)) {
627 628
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface arpmon interval missing or invalid"));
629 630 631 632 633
            goto error;
        }
        def->data.bond.interval = (int) tmp;

        def->data.bond.target =
634
            virXPathString("string(./arpmon/@target)", ctxt);
635
        if (def->data.bond.target == NULL) {
636 637
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface arpmon target missing"));
638
            ret = -1;
639 640 641
            goto error;
        }

642
        def->data.bond.validate = virInterfaceDefParseBondArpValid(ctxt);
643 644
        if (def->data.bond.validate < 0) {
            ret = -1;
645
            goto error;
646
        }
647 648
    }
error:
649
    return ret;
650 651 652
}

static int
653
virInterfaceDefParseVlan(virInterfaceDefPtr def,
654
                         xmlXPathContextPtr ctxt) {
655
    def->data.vlan.tag = virXPathString("string(./@tag)", ctxt);
656
    if (def->data.vlan.tag == NULL) {
657 658
        virReportError(VIR_ERR_XML_ERROR,
                       "%s", _("vlan interface misses the tag attribute"));
659
        return -1;
660 661 662
    }

    def->data.vlan.devname =
663
         virXPathString("string(./interface/@name)", ctxt);
664
    if (def->data.vlan.devname == NULL) {
665 666
        virReportError(VIR_ERR_XML_ERROR,
                       "%s", _("vlan interface misses name attribute"));
667
        return -1;
668
    }
669
    return 0;
670 671 672
}

static virInterfaceDefPtr
673
virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) {
674 675 676 677 678 679
    virInterfaceDefPtr def;
    int type;
    char *tmp;
    xmlNodePtr cur = ctxt->node;

    /* check @type */
680
    tmp = virXPathString("string(./@type)", ctxt);
681
    if (tmp == NULL) {
682 683
        virReportError(VIR_ERR_XML_ERROR,
                       "%s", _("interface misses the type attribute"));
684
        return NULL;
685 686 687
    }
    type = virInterfaceTypeFromString(tmp);
    if (type == -1) {
688 689
        virReportError(VIR_ERR_XML_ERROR,
                       _("unknown interface type %s"), tmp);
690
        VIR_FREE(tmp);
691
        return NULL;
692 693 694 695
    }
    VIR_FREE(tmp);

    if (VIR_ALLOC(def) < 0) {
696
        virReportOOMError();
697 698
        return NULL;
    }
699 700 701 702 703 704 705 706 707 708

    if (((parentIfType == VIR_INTERFACE_TYPE_BOND)
         && (type != VIR_INTERFACE_TYPE_ETHERNET))
        || ((parentIfType == VIR_INTERFACE_TYPE_BRIDGE)
            && (type != VIR_INTERFACE_TYPE_ETHERNET)
            && (type != VIR_INTERFACE_TYPE_BOND)
            && (type != VIR_INTERFACE_TYPE_VLAN))
        || (parentIfType == VIR_INTERFACE_TYPE_ETHERNET)
        || (parentIfType == VIR_INTERFACE_TYPE_VLAN))
        {
709 710 711
        virReportError(VIR_ERR_XML_ERROR,
                       _("interface has unsupported type '%s'"),
                       virInterfaceTypeToString(type));
712 713
        goto error;
    }
714 715 716
    def->type = type;
    switch (type) {
        case VIR_INTERFACE_TYPE_ETHERNET:
717
            if (virInterfaceDefParseName(def, ctxt) < 0)
718
                goto error;
719
            tmp = virXPathString("string(./mac/@address)", ctxt);
720 721
            if (tmp != NULL)
                def->mac = tmp;
722 723
            if (parentIfType == VIR_INTERFACE_TYPE_LAST) {
                /* only recognize these in toplevel bond interfaces */
724
                if (virInterfaceDefParseStartMode(def, ctxt) < 0)
725
                    goto error;
726
                if (virInterfaceDefParseMtu(def, ctxt) < 0)
727
                    goto error;
728
                if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
729 730
                    goto error;
            }
731 732 733 734
            break;
        case VIR_INTERFACE_TYPE_BRIDGE: {
            xmlNodePtr bridge;

735
            if (virInterfaceDefParseName(def, ctxt) < 0)
736
                goto error;
737
            if (virInterfaceDefParseStartMode(def, ctxt) < 0)
738
                goto error;
739
            if (virInterfaceDefParseMtu(def, ctxt) < 0)
740
                goto error;
741
            if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
742 743
                goto error;

744
            bridge = virXPathNode("./bridge[1]", ctxt);
745
            if (bridge == NULL) {
746 747
                virReportError(VIR_ERR_XML_ERROR,
                               "%s", _("bridge interface misses the bridge element"));
748 749 750 751 752 753 754 755 756 757
                goto error;
            }
            tmp = virXMLPropString(bridge, "stp");
            def->data.bridge.stp = -1;
            if (tmp != NULL) {
                if (STREQ(tmp, "on")) {
                    def->data.bridge.stp = 1;
                } else if (STREQ(tmp, "off")) {
                    def->data.bridge.stp = 0;
                } else {
758 759 760
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("bridge interface stp should be on or off got %s"),
                                   tmp);
761 762 763 764 765
                    VIR_FREE(tmp);
                    goto error;
                }
                VIR_FREE(tmp);
            }
766
            def->data.bridge.delay = virXMLPropString(bridge, "delay");
767
            ctxt->node = bridge;
768 769
            if (virInterfaceDefParseBridge(def, ctxt) < 0)
                goto error;
770 771 772 773 774
            break;
        }
        case VIR_INTERFACE_TYPE_BOND: {
            xmlNodePtr bond;

775
            if (virInterfaceDefParseName(def, ctxt) < 0)
776
                goto error;
777 778
            if (parentIfType == VIR_INTERFACE_TYPE_LAST) {
                /* only recognize these in toplevel bond interfaces */
779
                if (virInterfaceDefParseStartMode(def, ctxt) < 0)
780
                    goto error;
781
                if (virInterfaceDefParseMtu(def, ctxt) < 0)
782
                    goto error;
783
                if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
784 785 786
                    goto error;
            }

787
            bond = virXPathNode("./bond[1]", ctxt);
788
            if (bond == NULL) {
789 790
                virReportError(VIR_ERR_XML_ERROR,
                               "%s", _("bond interface misses the bond element"));
791 792 793
                goto error;
            }
            ctxt->node = bond;
794
            if (virInterfaceDefParseBond(def, ctxt)  < 0)
795 796 797 798 799 800
                goto error;
            break;
        }
        case VIR_INTERFACE_TYPE_VLAN: {
            xmlNodePtr vlan;

801
            tmp = virXPathString("string(./@name)", ctxt);
802 803
            if (tmp != NULL)
                def->name = tmp;
804
            if (virInterfaceDefParseStartMode(def, ctxt) < 0)
805
                goto error;
806
            if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
807
                goto error;
808
            vlan = virXPathNode("./vlan[1]", ctxt);
809
            if (vlan == NULL) {
810 811
                virReportError(VIR_ERR_XML_ERROR,
                               "%s", _("vlan interface misses the vlan element"));
812 813 814
                goto error;
            }
            ctxt->node = vlan;
815
            if (virInterfaceDefParseVlan(def, ctxt)  < 0)
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
                goto error;
            break;
        }

    }

    ctxt->node = cur;
    return def;

error:
    ctxt->node = cur;
    virInterfaceDefFree(def);
    return NULL;
}

831 832
virInterfaceDefPtr virInterfaceDefParseNode(xmlDocPtr xml,
                                            xmlNodePtr root)
833 834 835 836 837
{
    xmlXPathContextPtr ctxt = NULL;
    virInterfaceDefPtr def = NULL;

    if (!xmlStrEqual(root->name, BAD_CAST "interface")) {
838 839 840 841
        virReportError(VIR_ERR_XML_ERROR,
                       _("unexpected root element <%s>, "
                         "expecting <interface>"),
                       root->name);
842 843 844 845 846
        return NULL;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
847
        virReportOOMError();
848 849 850 851
        goto cleanup;
    }

    ctxt->node = root;
852
    def = virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_LAST);
853 854 855 856 857 858

cleanup:
    xmlXPathFreeContext(ctxt);
    return def;
}

J
Jiri Denemark 已提交
859 860 861
static virInterfaceDefPtr
virInterfaceDefParse(const char *xmlStr,
                     const char *filename)
862
{
J
Jiri Denemark 已提交
863
    xmlDocPtr xml;
864 865
    virInterfaceDefPtr def = NULL;

866
    if ((xml = virXMLParse(filename, xmlStr, _("(interface_definition)")))) {
J
Jiri Denemark 已提交
867 868
        def = virInterfaceDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
869 870 871 872 873
    }

    return def;
}

J
Jiri Denemark 已提交
874
virInterfaceDefPtr virInterfaceDefParseString(const char *xmlStr)
875
{
J
Jiri Denemark 已提交
876 877
    return virInterfaceDefParse(xmlStr, NULL);
}
878

J
Jiri Denemark 已提交
879 880 881
virInterfaceDefPtr virInterfaceDefParseFile(const char *filename)
{
    return virInterfaceDefParse(NULL, filename);
882 883 884
}

static int
885
virInterfaceBridgeDefFormat(virBufferPtr buf,
886
                            const virInterfaceDefPtr def, int level) {
887 888 889
    int i;
    int ret = 0;

890
    virBufferAsprintf(buf, "%*s  <bridge", level*2, "");
891
    if (def->data.bridge.stp == 1)
892
        virBufferAddLit(buf, " stp='on'");
893
    else if (def->data.bridge.stp == 0)
894 895
        virBufferAddLit(buf, " stp='off'");
    if (def->data.bridge.delay != NULL)
896
        virBufferAsprintf(buf, " delay='%s'", def->data.bridge.delay);
897
    virBufferAddLit(buf, ">\n");
898 899

    for (i = 0;i < def->data.bridge.nbItf;i++) {
900
        if (virInterfaceDefDevFormat(buf,
901
                                     def->data.bridge.itf[i], level+2) < 0)
902 903 904
            ret = -1;
    }

905
    virBufferAsprintf(buf, "%*s  </bridge>\n", level*2, "");
906
    return ret;
907 908 909
}

static int
910
virInterfaceBondDefFormat(virBufferPtr buf,
911
                          const virInterfaceDefPtr def, int level) {
912 913 914
    int i;
    int ret = 0;

915
    virBufferAsprintf(buf, "%*s  <bond", level*2, "");
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
    if (def->data.bond.mode == VIR_INTERFACE_BOND_BALRR)
        virBufferAddLit(buf, " mode='balance-rr'");
    else if (def->data.bond.mode == VIR_INTERFACE_BOND_ABACKUP)
        virBufferAddLit(buf, " mode='active-backup'");
    else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALXOR)
        virBufferAddLit(buf, " mode='balance-xor'");
    else if (def->data.bond.mode == VIR_INTERFACE_BOND_BCAST)
        virBufferAddLit(buf, " mode='broadcast'");
    else if (def->data.bond.mode == VIR_INTERFACE_BOND_8023AD)
        virBufferAddLit(buf, " mode='802.3ad'");
    else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALTLB)
        virBufferAddLit(buf, " mode='balance-tlb'");
    else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALALB)
        virBufferAddLit(buf, " mode='balance-alb'");
    virBufferAddLit(buf, ">\n");

    if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_MII) {
933
        virBufferAsprintf(buf, "%*s    <miimon freq='%d'",
934
                          level*2, "", def->data.bond.frequency);
935
        if (def->data.bond.downdelay > 0)
936
            virBufferAsprintf(buf, " downdelay='%d'", def->data.bond.downdelay);
937
        if (def->data.bond.updelay > 0)
938
            virBufferAsprintf(buf, " updelay='%d'", def->data.bond.updelay);
939 940 941 942 943 944 945
        if (def->data.bond.carrier == VIR_INTERFACE_BOND_MII_IOCTL)
            virBufferAddLit(buf, " carrier='ioctl'");
        else if (def->data.bond.carrier == VIR_INTERFACE_BOND_MII_NETIF)
            virBufferAddLit(buf, " carrier='netif'");
        virBufferAddLit(buf, "/>\n");
    } else if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_ARP) {
        if (def->data.bond.target == NULL) {
946 947
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("bond arp monitoring has no target"));
948
            return -1;
949
        }
950
        virBufferAsprintf(buf, "%*s    <arpmon interval='%d' target='%s'",
951
                          level*2, "",
952 953 954 955 956 957 958 959 960 961
                          def->data.bond.interval, def->data.bond.target);
        if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ACTIVE)
            virBufferAddLit(buf, " validate='active'");
        else if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_BACKUP)
            virBufferAddLit(buf, " validate='backup'");
        else if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ALL)
            virBufferAddLit(buf, " validate='all'");
        virBufferAddLit(buf, "/>\n");
    }
    for (i = 0;i < def->data.bond.nbItf;i++) {
962
        if (virInterfaceDefDevFormat(buf, def->data.bond.itf[i], level+2) < 0)
963 964 965
            ret = -1;
    }

966
    virBufferAsprintf(buf, "%*s  </bond>\n", level*2, "");
967
    return ret;
968 969 970
}

static int
971
virInterfaceVlanDefFormat(virBufferPtr buf,
972
                          const virInterfaceDefPtr def, int level) {
973
    if (def->data.vlan.tag == NULL) {
974 975
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("vlan misses the tag name"));
976
        return -1;
977 978
    }

979
    virBufferAsprintf(buf, "%*s  <vlan tag='%s'",
980
                      level*2, "", def->data.vlan.tag);
981 982
    if (def->data.vlan.devname != NULL) {
        virBufferAddLit(buf, ">\n");
983
        virBufferAsprintf(buf, "%*s    <interface name='%s'/>\n",
984
                          level*2, "", def->data.vlan.devname);
985
        virBufferAsprintf(buf, "%*s  </vlan>\n", level*2, "");
986 987
    } else
        virBufferAddLit(buf, "/>\n");
988
    return 0;
989 990 991
}

static int
992
virInterfaceProtocolDefFormat(virBufferPtr buf, const virInterfaceDefPtr def,
993
                              int level) {
994 995 996 997
    int pp, ii;

    for (pp = 0; pp < def->nprotos; pp++) {

998
        virBufferAsprintf(buf, "%*s  <protocol family='%s'>\n",
999
                          level*2, "", def->protos[pp]->family);
1000 1001

        if (def->protos[pp]->autoconf) {
1002
            virBufferAsprintf(buf, "%*s    <autoconf/>\n", level*2, "");
1003 1004 1005 1006
        }

        if (def->protos[pp]->dhcp) {
            if (def->protos[pp]->peerdns == 0)
1007
                virBufferAsprintf(buf, "%*s    <dhcp peerdns='no'/>\n",
1008
                                  level*2, "");
1009
            else if (def->protos[pp]->peerdns == 1)
1010
                virBufferAsprintf(buf, "%*s    <dhcp peerdns='yes'/>\n",
1011
                                  level*2, "");
1012
            else
1013
                virBufferAsprintf(buf, "%*s    <dhcp/>\n", level*2, "");
1014 1015 1016 1017 1018
        }

        for (ii = 0; ii < def->protos[pp]->nips; ii++) {
            if (def->protos[pp]->ips[ii]->address != NULL) {

1019
                virBufferAsprintf(buf, "%*s    <ip address='%s'", level*2, "",
1020 1021
                                  def->protos[pp]->ips[ii]->address);
                if (def->protos[pp]->ips[ii]->prefix != 0) {
1022
                    virBufferAsprintf(buf, " prefix='%d'",
1023 1024 1025 1026 1027 1028
                                      def->protos[pp]->ips[ii]->prefix);
                }
                virBufferAddLit(buf, "/>\n");
            }
        }
        if (def->protos[pp]->gateway != NULL) {
1029
            virBufferAsprintf(buf, "%*s    <route gateway='%s'/>\n",
1030
                              level*2, "", def->protos[pp]->gateway);
1031 1032
        }

1033
        virBufferAsprintf(buf, "%*s  </protocol>\n", level*2, "");
1034
    }
1035
    return 0;
1036 1037 1038
}

static int
1039
virInterfaceStartmodeDefFormat(virBufferPtr buf,
1040 1041
                               enum virInterfaceStartMode startmode,
                               int level) {
1042 1043
    const char *mode;
    switch (startmode) {
1044 1045
        case VIR_INTERFACE_START_UNSPECIFIED:
            return 0;
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
        case VIR_INTERFACE_START_NONE:
            mode = "none";
            break;
        case VIR_INTERFACE_START_ONBOOT:
            mode = "onboot";
            break;
        case VIR_INTERFACE_START_HOTPLUG:
            mode = "hotplug";
            break;
        default:
1056 1057
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("virInterfaceDefFormat unknown startmode"));
1058 1059
            return -1;
    }
1060
    virBufferAsprintf(buf, "%*s  <start mode='%s'/>\n", level*2, "", mode);
1061
    return 0;
1062 1063
}

1064
static int
1065
virInterfaceDefDevFormat(virBufferPtr buf,
1066
                         const virInterfaceDefPtr def, int level) {
1067
    const char *type = NULL;
1068

1069
    if (def == NULL) {
1070 1071
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("virInterfaceDefFormat NULL def"));
1072 1073 1074 1075
        goto cleanup;
    }

    if ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN)) {
1076 1077
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("virInterfaceDefFormat missing interface name"));
1078 1079 1080 1081
        goto cleanup;
    }

    if (!(type = virInterfaceTypeToString(def->type))) {
1082 1083
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected interface type %d"), def->type);
1084 1085 1086
        goto cleanup;
    }

1087
    virBufferAsprintf(buf, "%*s<interface type='%s' ", level*2, "", type);
1088
    if (def->name != NULL)
1089 1090
        virBufferEscapeString(buf, "name='%s'", def->name);
    virBufferAddLit(buf, ">\n");
1091 1092 1093

    switch (def->type) {
        case VIR_INTERFACE_TYPE_ETHERNET:
1094
            virInterfaceStartmodeDefFormat(buf, def->startmode, level);
1095
            if (def->mac != NULL)
1096
                virBufferAsprintf(buf, "%*s  <mac address='%s'/>\n",
1097
                                  level*2, "", def->mac);
1098
            if (def->mtu != 0)
1099
                virBufferAsprintf(buf, "%*s  <mtu size='%d'/>\n",
1100
                                  level*2, "", def->mtu);
1101
            virInterfaceProtocolDefFormat(buf, def, level);
1102 1103
            break;
        case VIR_INTERFACE_TYPE_BRIDGE:
1104
            virInterfaceStartmodeDefFormat(buf, def->startmode, level);
1105
            if (def->mtu != 0)
1106
                virBufferAsprintf(buf, "%*s  <mtu size='%d'/>\n",
1107
                                  level*2, "", def->mtu);
1108 1109
            virInterfaceProtocolDefFormat(buf, def, level);
            virInterfaceBridgeDefFormat(buf, def, level);
1110 1111
            break;
        case VIR_INTERFACE_TYPE_BOND:
1112
            virInterfaceStartmodeDefFormat(buf, def->startmode, level);
1113
            if (def->mtu != 0)
1114
                virBufferAsprintf(buf, "%*s  <mtu size='%d'/>\n",
1115
                                  level*2, "", def->mtu);
1116 1117
            virInterfaceProtocolDefFormat(buf, def, level);
            virInterfaceBondDefFormat(buf, def, level);
1118 1119
            break;
        case VIR_INTERFACE_TYPE_VLAN:
1120
            virInterfaceStartmodeDefFormat(buf, def->startmode, level);
1121
            if (def->mac != NULL)
1122
                virBufferAsprintf(buf, "%*s  <mac address='%s'/>\n",
1123
                                  level*2, "", def->mac);
1124
            if (def->mtu != 0)
1125
                virBufferAsprintf(buf, "%*s  <mtu size='%d'/>\n",
1126
                                  level*2, "", def->mtu);
1127 1128
            virInterfaceProtocolDefFormat(buf, def, level);
            virInterfaceVlanDefFormat(buf, def, level);
1129 1130 1131
            break;
    }

1132
    virBufferAsprintf(buf, "%*s</interface>\n", level*2, "");
1133

1134
    if (virBufferError(buf))
1135
        goto no_memory;
1136
    return 0;
1137
no_memory:
1138
    virReportOOMError();
1139
cleanup:
1140 1141 1142
    return -1;
}

1143
char *virInterfaceDefFormat(const virInterfaceDefPtr def)
1144 1145 1146
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

1147
    if (virInterfaceDefDevFormat(&buf, def, 0) < 0) {
1148 1149 1150 1151
        virBufferFreeAndReset(&buf);
        return NULL;
    }
    return virBufferContentAndReset(&buf);
1152 1153
}

1154 1155
/* virInterfaceObj manipulation */

1156 1157 1158 1159 1160 1161 1162 1163 1164
void virInterfaceObjLock(virInterfaceObjPtr obj)
{
    virMutexLock(&obj->lock);
}

void virInterfaceObjUnlock(virInterfaceObjPtr obj)
{
    virMutexUnlock(&obj->lock);
}
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 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 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228

void virInterfaceObjFree(virInterfaceObjPtr iface)
{
    if (!iface)
        return;

    virInterfaceDefFree(iface->def);
    virMutexDestroy(&iface->lock);
    VIR_FREE(iface);
}

/* virInterfaceObjList manipulation */

int virInterfaceFindByMACString(const virInterfaceObjListPtr interfaces,
                                const char *mac,
                                virInterfaceObjPtr *matches, int maxmatches)
{
    unsigned int i, matchct = 0;

    for (i = 0 ; i < interfaces->count ; i++) {

        virInterfaceObjLock(interfaces->objs[i]);
        if (STRCASEEQ(interfaces->objs[i]->def->mac, mac)) {
            matchct++;
            if (matchct <= maxmatches) {
                matches[matchct - 1] = interfaces->objs[i];
                /* keep the lock if we're returning object to caller */
                /* it is the caller's responsibility to unlock *all* matches */
                continue;
            }
        }
        virInterfaceObjUnlock(interfaces->objs[i]);

    }
    return matchct;
}

virInterfaceObjPtr virInterfaceFindByName(const virInterfaceObjListPtr
                                          interfaces,
                                          const char *name)
{
    unsigned int i;

    for (i = 0 ; i < interfaces->count ; i++) {
        virInterfaceObjLock(interfaces->objs[i]);
        if (STREQ(interfaces->objs[i]->def->name, name))
            return interfaces->objs[i];
        virInterfaceObjUnlock(interfaces->objs[i]);
    }

    return NULL;
}

void virInterfaceObjListFree(virInterfaceObjListPtr interfaces)
{
    unsigned int i;

    for (i = 0 ; i < interfaces->count ; i++)
        virInterfaceObjFree(interfaces->objs[i]);

    VIR_FREE(interfaces->objs);
    interfaces->count = 0;
}

1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
int virInterfaceObjListClone(virInterfaceObjListPtr src,
                             virInterfaceObjListPtr dest)
{
    int ret = -1;
    unsigned int i, cnt;

    if (!src || !dest)
        goto cleanup;

    virInterfaceObjListFree(dest); /* start with an empty list */
    cnt = src->count;
    for (i = 0; i < cnt; i++) {
        virInterfaceDefPtr def = src->objs[i]->def;
        virInterfaceDefPtr backup;
        virInterfaceObjPtr iface;
        char *xml = virInterfaceDefFormat(def);

        if (!xml)
            goto cleanup;

        if ((backup = virInterfaceDefParseString(xml)) == NULL) {
            VIR_FREE(xml);
            goto cleanup;
        }

        VIR_FREE(xml);
        if ((iface = virInterfaceAssignDef(dest, backup)) == NULL)
            goto cleanup;
        virInterfaceObjUnlock(iface); /* was locked by virInterfaceAssignDef */
    }

    ret = cnt;
cleanup:
    if ((ret < 0) && dest)
       virInterfaceObjListFree(dest);
    return ret;
}

1267
virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces,
1268 1269
                                         const virInterfaceDefPtr def)
{
1270
    virInterfaceObjPtr iface;
1271

1272
    if ((iface = virInterfaceFindByName(interfaces, def->name))) {
1273
        virInterfaceDefFree(iface->def);
1274
        iface->def = def;
1275

1276
        return iface;
1277 1278
    }

1279
    if (VIR_ALLOC(iface) < 0) {
1280
        virReportOOMError();
1281 1282
        return NULL;
    }
1283
    if (virMutexInit(&iface->lock) < 0) {
1284 1285
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
1286
        VIR_FREE(iface);
1287 1288
        return NULL;
    }
1289 1290
    virInterfaceObjLock(iface);
    iface->def = def;
1291 1292

    if (VIR_REALLOC_N(interfaces->objs, interfaces->count + 1) < 0) {
1293
        virReportOOMError();
1294
        VIR_FREE(iface);
1295 1296 1297
        return NULL;
    }

1298
    interfaces->objs[interfaces->count] = iface;
1299 1300
    interfaces->count++;

1301
    return iface;
1302 1303 1304 1305

}

void virInterfaceRemove(virInterfaceObjListPtr interfaces,
1306
                        const virInterfaceObjPtr iface)
1307 1308 1309
{
    unsigned int i;

1310
    virInterfaceObjUnlock(iface);
1311 1312
    for (i = 0 ; i < interfaces->count ; i++) {
        virInterfaceObjLock(interfaces->objs[i]);
1313
        if (interfaces->objs[i] == iface) {
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
            virInterfaceObjUnlock(interfaces->objs[i]);
            virInterfaceObjFree(interfaces->objs[i]);

            if (i < (interfaces->count - 1))
                memmove(interfaces->objs + i, interfaces->objs + i + 1,
                        sizeof(*(interfaces->objs)) * (interfaces->count - (i + 1)));

            if (VIR_REALLOC_N(interfaces->objs, interfaces->count - 1) < 0) {
                ; /* Failure to reduce memory allocation isn't fatal */
            }
            interfaces->count--;

            break;
        }
        virInterfaceObjUnlock(interfaces->objs[i]);
    }
}