/* Delete all or a specific IP address from an interface. After this
 * call either all or the given IP address will not be associated
 * with the interface anymore.
 *
 * @ifname: The name of the (tap) interface
 * @addr: An IPv4 address in dotted decimal format that the (tap)
 *        interface is not using anymore; provide NULL to remove all IP
 *        addresses associated with the given interface
 *
 * This function returns the number of IP addresses that are still
 * known to be associated with this interface, in case of an error
 * -1 is returned. Error conditions are:
 * - IP addresses is not known to be associated with the interface
 */
int
virNWFilterIPAddrMapDelIPAddr(const char *ifname, const char *ipaddr)
{
    int ret = -1;
    virNWFilterVarValuePtr val = NULL;

    virMutexLock(&ipAddressMapLock);

    if (ipaddr != NULL) {
        val = virHashLookup(ipAddressMap->hashTable, ifname);
        if (val) {
            if (virNWFilterVarValueGetCardinality(val) == 1 &&
                STREQ(ipaddr,
                      virNWFilterVarValueGetNthValue(val, 0)))
                goto remove_entry;
            virNWFilterVarValueDelValue(val, ipaddr);
            ret = virNWFilterVarValueGetCardinality(val);
        }
    } else {
remove_entry:
        /* remove whole entry */
        val = virNWFilterHashTableRemoveEntry(ipAddressMap, ifname);
        virNWFilterVarValueFree(val);
        ret = 0;
    }

    virMutexUnlock(&ipAddressMapLock);

    return ret;
}
static int testSetOneParameter(virNWFilterHashTablePtr vars,
                               const char *name,
                               const char *value)
{
    int ret = -1;
    virNWFilterVarValuePtr val;

    if ((val = virHashLookup(vars->hashTable, name)) == NULL) {
        val = virNWFilterVarValueCreateSimpleCopyValue(value);
        if (!val)
            goto cleanup;
        if (virNWFilterHashTablePut(vars, name, val) < 0) {
            virNWFilterVarValueFree(val);
            goto cleanup;
        }
    } else {
        if (virNWFilterVarValueAddValueCopy(val, value) < 0)
            goto cleanup;
    }
    ret = 0;
 cleanup:
    return ret;
}
virNWFilterVarValuePtr
virNWFilterVarValueCopy(const virNWFilterVarValue *val)
{
    virNWFilterVarValuePtr res;
    size_t i;
    char *str;

    if (VIR_ALLOC(res) < 0)
        return NULL;
    res->valType = val->valType;

    switch (res->valType) {
    case NWFILTER_VALUE_TYPE_SIMPLE:
        if (VIR_STRDUP(res->u.simple.value, val->u.simple.value) < 0)
            goto err_exit;
        break;
    case NWFILTER_VALUE_TYPE_ARRAY:
        if (VIR_ALLOC_N(res->u.array.values, val->u.array.nValues) < 0)
            goto err_exit;
        res->u.array.nValues = val->u.array.nValues;
        for (i = 0; i < val->u.array.nValues; i++) {
            if (VIR_STRDUP(str, val->u.array.values[i]) < 0)
                goto err_exit;
            res->u.array.values[i] = str;
        }
        break;
    case NWFILTER_VALUE_TYPE_LAST:
        break;
    }

    return res;

err_exit:
    virNWFilterVarValueFree(res);
    return NULL;
}