interface_conf.c 39.1 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
 *
 * Author: Daniel Veillard <veillard@redhat.com>
 *         Laine Stump <laine@redhat.com>
 */

#include <config.h>
25
#include "virerror.h"
26 27 28 29
#include "datatypes.h"

#include "interface_conf.h"

30
#include "viralloc.h"
31
#include "virxml.h"
32
#include "viruuid.h"
33
#include "virutil.h"
34
#include "virbuffer.h"
35 36 37 38 39

#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) {
J
Jim Fehlig 已提交
575
    int res;
576

577
    def->data.bond.mode = virInterfaceDefParseBondMode(ctxt);
578
    if (def->data.bond.mode < 0)
J
Jim Fehlig 已提交
579
        return -1;
580

J
Jim Fehlig 已提交
581 582
    if (virInterfaceDefParseBondItfs(def, ctxt) != 0)
        return -1;
583

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

J
Jim Fehlig 已提交
587 588 589
        res = virXPathInt("string(./miimon/@freq)", ctxt,
                          &def->data.bond.frequency);
        if ((res == -2) || (res == -1)) {
590 591
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface miimon freq missing or invalid"));
J
Jim Fehlig 已提交
592
            return -1;
593 594
        }

J
Jim Fehlig 已提交
595 596 597
        res = virXPathInt("string(./miimon/@downdelay)", ctxt,
                          &def->data.bond.downdelay);
        if (res == -2) {
598 599
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface miimon downdelay invalid"));
J
Jim Fehlig 已提交
600
            return -1;
601 602
        }

J
Jim Fehlig 已提交
603 604 605
        res = virXPathInt("string(./miimon/@updelay)", ctxt,
                          &def->data.bond.updelay);
        if (res == -2) {
606 607
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface miimon updelay invalid"));
J
Jim Fehlig 已提交
608
            return -1;
609 610
        }

611
        def->data.bond.carrier = virInterfaceDefParseBondMiiCarrier(ctxt);
J
Jim Fehlig 已提交
612 613
        if (def->data.bond.carrier < 0)
            return -1;
614

615
    } else if (virXPathNode("./arpmon[1]", ctxt) != NULL) {
616 617 618

        def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP;

J
Jim Fehlig 已提交
619 620 621
        res = virXPathInt("string(./arpmon/@interval)", ctxt,
                          &def->data.bond.interval);
        if ((res == -2) || (res == -1)) {
622 623
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface arpmon interval missing or invalid"));
J
Jim Fehlig 已提交
624
            return -1;
625 626 627
        }

        def->data.bond.target =
628
            virXPathString("string(./arpmon/@target)", ctxt);
629
        if (def->data.bond.target == NULL) {
630 631
            virReportError(VIR_ERR_XML_ERROR,
                           "%s", _("bond interface arpmon target missing"));
J
Jim Fehlig 已提交
632
            return -1;
633 634
        }

635
        def->data.bond.validate = virInterfaceDefParseBondArpValid(ctxt);
J
Jim Fehlig 已提交
636 637
        if (def->data.bond.validate < 0)
            return -1;
638
    }
J
Jim Fehlig 已提交
639 640

    return 0;
641 642 643
}

static int
644
virInterfaceDefParseVlan(virInterfaceDefPtr def,
645
                         xmlXPathContextPtr ctxt) {
646
    def->data.vlan.tag = virXPathString("string(./@tag)", ctxt);
647
    if (def->data.vlan.tag == NULL) {
648 649
        virReportError(VIR_ERR_XML_ERROR,
                       "%s", _("vlan interface misses the tag attribute"));
650
        return -1;
651 652 653
    }

    def->data.vlan.devname =
654
         virXPathString("string(./interface/@name)", ctxt);
655
    if (def->data.vlan.devname == NULL) {
656 657
        virReportError(VIR_ERR_XML_ERROR,
                       "%s", _("vlan interface misses name attribute"));
658
        return -1;
659
    }
660
    return 0;
661 662 663
}

static virInterfaceDefPtr
664
virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) {
665 666 667 668 669 670
    virInterfaceDefPtr def;
    int type;
    char *tmp;
    xmlNodePtr cur = ctxt->node;

    /* check @type */
671
    tmp = virXPathString("string(./@type)", ctxt);
672
    if (tmp == NULL) {
673 674
        virReportError(VIR_ERR_XML_ERROR,
                       "%s", _("interface misses the type attribute"));
675
        return NULL;
676 677 678
    }
    type = virInterfaceTypeFromString(tmp);
    if (type == -1) {
679 680
        virReportError(VIR_ERR_XML_ERROR,
                       _("unknown interface type %s"), tmp);
681
        VIR_FREE(tmp);
682
        return NULL;
683 684 685 686
    }
    VIR_FREE(tmp);

    if (VIR_ALLOC(def) < 0) {
687
        virReportOOMError();
688 689
        return NULL;
    }
690 691 692 693 694 695 696 697 698 699

    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))
        {
700 701 702
        virReportError(VIR_ERR_XML_ERROR,
                       _("interface has unsupported type '%s'"),
                       virInterfaceTypeToString(type));
703 704
        goto error;
    }
705 706 707
    def->type = type;
    switch (type) {
        case VIR_INTERFACE_TYPE_ETHERNET:
708
            if (virInterfaceDefParseName(def, ctxt) < 0)
709
                goto error;
710
            tmp = virXPathString("string(./mac/@address)", ctxt);
711 712
            if (tmp != NULL)
                def->mac = tmp;
713 714
            if (parentIfType == VIR_INTERFACE_TYPE_LAST) {
                /* only recognize these in toplevel bond interfaces */
715
                if (virInterfaceDefParseStartMode(def, ctxt) < 0)
716
                    goto error;
717
                if (virInterfaceDefParseMtu(def, ctxt) < 0)
718
                    goto error;
719
                if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
720 721
                    goto error;
            }
722 723 724 725
            break;
        case VIR_INTERFACE_TYPE_BRIDGE: {
            xmlNodePtr bridge;

726
            if (virInterfaceDefParseName(def, ctxt) < 0)
727
                goto error;
728
            if (virInterfaceDefParseStartMode(def, ctxt) < 0)
729
                goto error;
730
            if (virInterfaceDefParseMtu(def, ctxt) < 0)
731
                goto error;
732
            if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
733 734
                goto error;

735
            bridge = virXPathNode("./bridge[1]", ctxt);
736
            if (bridge == NULL) {
737 738
                virReportError(VIR_ERR_XML_ERROR,
                               "%s", _("bridge interface misses the bridge element"));
739 740 741 742 743 744 745 746 747 748
                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 {
749 750 751
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("bridge interface stp should be on or off got %s"),
                                   tmp);
752 753 754 755 756
                    VIR_FREE(tmp);
                    goto error;
                }
                VIR_FREE(tmp);
            }
757
            def->data.bridge.delay = virXMLPropString(bridge, "delay");
758
            ctxt->node = bridge;
759 760
            if (virInterfaceDefParseBridge(def, ctxt) < 0)
                goto error;
761 762 763 764 765
            break;
        }
        case VIR_INTERFACE_TYPE_BOND: {
            xmlNodePtr bond;

766
            if (virInterfaceDefParseName(def, ctxt) < 0)
767
                goto error;
768 769
            if (parentIfType == VIR_INTERFACE_TYPE_LAST) {
                /* only recognize these in toplevel bond interfaces */
770
                if (virInterfaceDefParseStartMode(def, ctxt) < 0)
771
                    goto error;
772
                if (virInterfaceDefParseMtu(def, ctxt) < 0)
773
                    goto error;
774
                if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
775 776 777
                    goto error;
            }

778
            bond = virXPathNode("./bond[1]", ctxt);
779
            if (bond == NULL) {
780 781
                virReportError(VIR_ERR_XML_ERROR,
                               "%s", _("bond interface misses the bond element"));
782 783 784
                goto error;
            }
            ctxt->node = bond;
785
            if (virInterfaceDefParseBond(def, ctxt)  < 0)
786 787 788 789 790 791
                goto error;
            break;
        }
        case VIR_INTERFACE_TYPE_VLAN: {
            xmlNodePtr vlan;

792
            tmp = virXPathString("string(./@name)", ctxt);
793 794
            if (tmp != NULL)
                def->name = tmp;
795
            if (virInterfaceDefParseStartMode(def, ctxt) < 0)
796
                goto error;
797
            if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
798
                goto error;
799
            vlan = virXPathNode("./vlan[1]", ctxt);
800
            if (vlan == NULL) {
801 802
                virReportError(VIR_ERR_XML_ERROR,
                               "%s", _("vlan interface misses the vlan element"));
803 804 805
                goto error;
            }
            ctxt->node = vlan;
806
            if (virInterfaceDefParseVlan(def, ctxt)  < 0)
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
                goto error;
            break;
        }

    }

    ctxt->node = cur;
    return def;

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

822 823
virInterfaceDefPtr virInterfaceDefParseNode(xmlDocPtr xml,
                                            xmlNodePtr root)
824 825 826 827 828
{
    xmlXPathContextPtr ctxt = NULL;
    virInterfaceDefPtr def = NULL;

    if (!xmlStrEqual(root->name, BAD_CAST "interface")) {
829 830 831 832
        virReportError(VIR_ERR_XML_ERROR,
                       _("unexpected root element <%s>, "
                         "expecting <interface>"),
                       root->name);
833 834 835 836 837
        return NULL;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
838
        virReportOOMError();
839 840 841 842
        goto cleanup;
    }

    ctxt->node = root;
843
    def = virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_LAST);
844 845 846 847 848 849

cleanup:
    xmlXPathFreeContext(ctxt);
    return def;
}

J
Jiri Denemark 已提交
850 851 852
static virInterfaceDefPtr
virInterfaceDefParse(const char *xmlStr,
                     const char *filename)
853
{
J
Jiri Denemark 已提交
854
    xmlDocPtr xml;
855 856
    virInterfaceDefPtr def = NULL;

857
    if ((xml = virXMLParse(filename, xmlStr, _("(interface_definition)")))) {
J
Jiri Denemark 已提交
858 859
        def = virInterfaceDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
860 861 862 863 864
    }

    return def;
}

J
Jiri Denemark 已提交
865
virInterfaceDefPtr virInterfaceDefParseString(const char *xmlStr)
866
{
J
Jiri Denemark 已提交
867 868
    return virInterfaceDefParse(xmlStr, NULL);
}
869

J
Jiri Denemark 已提交
870 871 872
virInterfaceDefPtr virInterfaceDefParseFile(const char *filename)
{
    return virInterfaceDefParse(NULL, filename);
873 874 875
}

static int
876
virInterfaceBridgeDefFormat(virBufferPtr buf,
877
                            const virInterfaceDefPtr def, int level) {
878 879 880
    int i;
    int ret = 0;

881
    virBufferAsprintf(buf, "%*s  <bridge", level*2, "");
882
    if (def->data.bridge.stp == 1)
883
        virBufferAddLit(buf, " stp='on'");
884
    else if (def->data.bridge.stp == 0)
885 886
        virBufferAddLit(buf, " stp='off'");
    if (def->data.bridge.delay != NULL)
887
        virBufferAsprintf(buf, " delay='%s'", def->data.bridge.delay);
888
    virBufferAddLit(buf, ">\n");
889 890

    for (i = 0;i < def->data.bridge.nbItf;i++) {
891
        if (virInterfaceDefDevFormat(buf,
892
                                     def->data.bridge.itf[i], level+2) < 0)
893 894 895
            ret = -1;
    }

896
    virBufferAsprintf(buf, "%*s  </bridge>\n", level*2, "");
897
    return ret;
898 899 900
}

static int
901
virInterfaceBondDefFormat(virBufferPtr buf,
902
                          const virInterfaceDefPtr def, int level) {
903 904 905
    int i;
    int ret = 0;

906
    virBufferAsprintf(buf, "%*s  <bond", level*2, "");
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
    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) {
924
        virBufferAsprintf(buf, "%*s    <miimon freq='%d'",
925
                          level*2, "", def->data.bond.frequency);
926
        if (def->data.bond.downdelay > 0)
927
            virBufferAsprintf(buf, " downdelay='%d'", def->data.bond.downdelay);
928
        if (def->data.bond.updelay > 0)
929
            virBufferAsprintf(buf, " updelay='%d'", def->data.bond.updelay);
930 931 932 933 934 935 936
        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) {
937 938
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("bond arp monitoring has no target"));
939
            return -1;
940
        }
941
        virBufferAsprintf(buf, "%*s    <arpmon interval='%d' target='%s'",
942
                          level*2, "",
943 944 945 946 947 948 949 950 951 952
                          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++) {
953
        if (virInterfaceDefDevFormat(buf, def->data.bond.itf[i], level+2) < 0)
954 955 956
            ret = -1;
    }

957
    virBufferAsprintf(buf, "%*s  </bond>\n", level*2, "");
958
    return ret;
959 960 961
}

static int
962
virInterfaceVlanDefFormat(virBufferPtr buf,
963
                          const virInterfaceDefPtr def, int level) {
964
    if (def->data.vlan.tag == NULL) {
965 966
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("vlan misses the tag name"));
967
        return -1;
968 969
    }

970
    virBufferAsprintf(buf, "%*s  <vlan tag='%s'",
971
                      level*2, "", def->data.vlan.tag);
972 973
    if (def->data.vlan.devname != NULL) {
        virBufferAddLit(buf, ">\n");
974
        virBufferAsprintf(buf, "%*s    <interface name='%s'/>\n",
975
                          level*2, "", def->data.vlan.devname);
976
        virBufferAsprintf(buf, "%*s  </vlan>\n", level*2, "");
977 978
    } else
        virBufferAddLit(buf, "/>\n");
979
    return 0;
980 981 982
}

static int
983
virInterfaceProtocolDefFormat(virBufferPtr buf, const virInterfaceDefPtr def,
984
                              int level) {
985 986 987 988
    int pp, ii;

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

989
        virBufferAsprintf(buf, "%*s  <protocol family='%s'>\n",
990
                          level*2, "", def->protos[pp]->family);
991 992

        if (def->protos[pp]->autoconf) {
993
            virBufferAsprintf(buf, "%*s    <autoconf/>\n", level*2, "");
994 995 996 997
        }

        if (def->protos[pp]->dhcp) {
            if (def->protos[pp]->peerdns == 0)
998
                virBufferAsprintf(buf, "%*s    <dhcp peerdns='no'/>\n",
999
                                  level*2, "");
1000
            else if (def->protos[pp]->peerdns == 1)
1001
                virBufferAsprintf(buf, "%*s    <dhcp peerdns='yes'/>\n",
1002
                                  level*2, "");
1003
            else
1004
                virBufferAsprintf(buf, "%*s    <dhcp/>\n", level*2, "");
1005 1006 1007 1008 1009
        }

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

1010
                virBufferAsprintf(buf, "%*s    <ip address='%s'", level*2, "",
1011 1012
                                  def->protos[pp]->ips[ii]->address);
                if (def->protos[pp]->ips[ii]->prefix != 0) {
1013
                    virBufferAsprintf(buf, " prefix='%d'",
1014 1015 1016 1017 1018 1019
                                      def->protos[pp]->ips[ii]->prefix);
                }
                virBufferAddLit(buf, "/>\n");
            }
        }
        if (def->protos[pp]->gateway != NULL) {
1020
            virBufferAsprintf(buf, "%*s    <route gateway='%s'/>\n",
1021
                              level*2, "", def->protos[pp]->gateway);
1022 1023
        }

1024
        virBufferAsprintf(buf, "%*s  </protocol>\n", level*2, "");
1025
    }
1026
    return 0;
1027 1028 1029
}

static int
1030
virInterfaceStartmodeDefFormat(virBufferPtr buf,
1031 1032
                               enum virInterfaceStartMode startmode,
                               int level) {
1033 1034
    const char *mode;
    switch (startmode) {
1035 1036
        case VIR_INTERFACE_START_UNSPECIFIED:
            return 0;
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
        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:
1047 1048
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("virInterfaceDefFormat unknown startmode"));
1049 1050
            return -1;
    }
1051
    virBufferAsprintf(buf, "%*s  <start mode='%s'/>\n", level*2, "", mode);
1052
    return 0;
1053 1054
}

1055
static int
1056
virInterfaceDefDevFormat(virBufferPtr buf,
1057
                         const virInterfaceDefPtr def, int level) {
1058
    const char *type = NULL;
1059

1060
    if (def == NULL) {
1061 1062
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("virInterfaceDefFormat NULL def"));
1063 1064 1065 1066
        goto cleanup;
    }

    if ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN)) {
1067 1068
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("virInterfaceDefFormat missing interface name"));
1069 1070 1071 1072
        goto cleanup;
    }

    if (!(type = virInterfaceTypeToString(def->type))) {
1073 1074
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected interface type %d"), def->type);
1075 1076 1077
        goto cleanup;
    }

1078
    virBufferAsprintf(buf, "%*s<interface type='%s' ", level*2, "", type);
1079
    if (def->name != NULL)
1080 1081
        virBufferEscapeString(buf, "name='%s'", def->name);
    virBufferAddLit(buf, ">\n");
1082 1083 1084

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

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

1125
    if (virBufferError(buf))
1126
        goto no_memory;
1127
    return 0;
1128
no_memory:
1129
    virReportOOMError();
1130
cleanup:
1131 1132 1133
    return -1;
}

1134
char *virInterfaceDefFormat(const virInterfaceDefPtr def)
1135 1136 1137
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

1138
    if (virInterfaceDefDevFormat(&buf, def, 0) < 0) {
1139 1140 1141 1142
        virBufferFreeAndReset(&buf);
        return NULL;
    }
    return virBufferContentAndReset(&buf);
1143 1144
}

1145 1146
/* virInterfaceObj manipulation */

1147 1148 1149 1150 1151 1152 1153 1154 1155
void virInterfaceObjLock(virInterfaceObjPtr obj)
{
    virMutexLock(&obj->lock);
}

void virInterfaceObjUnlock(virInterfaceObjPtr obj)
{
    virMutexUnlock(&obj->lock);
}
1156 1157 1158 1159 1160 1161 1162 1163 1164 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

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;
}

1220 1221 1222 1223 1224 1225 1226 1227 1228 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
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;
}

1258
virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces,
1259 1260
                                         const virInterfaceDefPtr def)
{
1261
    virInterfaceObjPtr iface;
1262

1263
    if ((iface = virInterfaceFindByName(interfaces, def->name))) {
1264
        virInterfaceDefFree(iface->def);
1265
        iface->def = def;
1266

1267
        return iface;
1268 1269
    }

1270
    if (VIR_ALLOC(iface) < 0) {
1271
        virReportOOMError();
1272 1273
        return NULL;
    }
1274
    if (virMutexInit(&iface->lock) < 0) {
1275 1276
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
1277
        VIR_FREE(iface);
1278 1279
        return NULL;
    }
1280 1281
    virInterfaceObjLock(iface);
    iface->def = def;
1282 1283

    if (VIR_REALLOC_N(interfaces->objs, interfaces->count + 1) < 0) {
1284
        virReportOOMError();
1285
        VIR_FREE(iface);
1286 1287 1288
        return NULL;
    }

1289
    interfaces->objs[interfaces->count] = iface;
1290 1291
    interfaces->count++;

1292
    return iface;
1293 1294 1295 1296

}

void virInterfaceRemove(virInterfaceObjListPtr interfaces,
1297
                        const virInterfaceObjPtr iface)
1298 1299 1300
{
    unsigned int i;

1301
    virInterfaceObjUnlock(iface);
1302 1303
    for (i = 0 ; i < interfaces->count ; i++) {
        virInterfaceObjLock(interfaces->objs[i]);
1304
        if (interfaces->objs[i] == iface) {
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
            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]);
    }
}