nwfilter_ipaddrmap.c 4.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * nwfilter_ipaddrmap.c: IP address map for mapping interfaces to their
 *                       detected/expected IP addresses
 *
 * Copyright (C) 2010, 2012 IBM Corp.
 *
 * Author:
 *     Stefan Berger <stefanb@linux.vnet.ibm.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library.  If not, see
O
Osier Yang 已提交
22
 * <http://www.gnu.org/licenses/>.
23 24 25 26 27 28
 */

#include <config.h>

#include "internal.h"

29
#include "viralloc.h"
30
#include "virerror.h"
31
#include "virstring.h"
32 33 34 35 36 37
#include "datatypes.h"
#include "nwfilter_params.h"
#include "nwfilter_ipaddrmap.h"

#define VIR_FROM_THIS VIR_FROM_NWFILTER

38
static virMutex ipAddressMapLock = VIR_MUTEX_INITIALIZER;
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
static virNWFilterHashTablePtr ipAddressMap;


/* Add an IP address to the list of IP addresses an interface is
 * known to use. This function feeds the per-interface cache that
 * is used to instantiate filters with variable '$IP'.
 *
 * @ifname: The name of the (tap) interface
 * @addr: An IPv4 address in dotted decimal format that the (tap)
 *        interface is known to use.
 *
 * This function returns 0 on success, -1 otherwise
 */
int
virNWFilterIPAddrMapAddIPAddr(const char *ifname, char *addr)
{
    int ret = -1;
56
    char *addrCopy;
57 58
    virNWFilterVarValuePtr val;

59 60 61
    if (VIR_STRDUP(addrCopy, addr) < 0)
        return -1;

62 63
    virMutexLock(&ipAddressMapLock);

64
    val = virHashLookup(ipAddressMap, ifname);
65
    if (!val) {
66
        val = virNWFilterVarValueCreateSimple(addrCopy);
67
        if (!val)
68
            goto cleanup;
69
        addrCopy = NULL;
70
        ret = virNWFilterHashTablePut(ipAddressMap, ifname, val);
71 72
        if (ret < 0)
            virNWFilterVarValueFree(val);
73 74
        goto cleanup;
    } else {
75
        if (virNWFilterVarValueAddValue(val, addrCopy) < 0)
76
            goto cleanup;
77
        addrCopy = NULL;
78 79 80 81
    }

    ret = 0;

82
 cleanup:
83
    virMutexUnlock(&ipAddressMapLock);
84
    VIR_FREE(addrCopy);
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

    return ret;
}

/* 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) {
112
        val = virHashLookup(ipAddressMap, ifname);
113 114 115 116 117 118 119 120 121
        if (val) {
            if (virNWFilterVarValueGetCardinality(val) == 1 &&
                STREQ(ipaddr,
                      virNWFilterVarValueGetNthValue(val, 0)))
                goto remove_entry;
            virNWFilterVarValueDelValue(val, ipaddr);
            ret = virNWFilterVarValueGetCardinality(val);
        }
    } else {
122
 remove_entry:
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
        /* remove whole entry */
        val = virNWFilterHashTableRemoveEntry(ipAddressMap, ifname);
        virNWFilterVarValueFree(val);
        ret = 0;
    }

    virMutexUnlock(&ipAddressMapLock);

    return ret;
}

/* Get the list of IP addresses known to be in use by an interface
 *
 * This function returns NULL in case no IP address is known to be
 * associated with the interface, a virNWFilterVarValuePtr otherwise
 * that then can contain one or multiple entries.
 */
virNWFilterVarValuePtr
virNWFilterIPAddrMapGetIPAddr(const char *ifname)
{
    virNWFilterVarValuePtr res;

    virMutexLock(&ipAddressMapLock);

147
    res = virHashLookup(ipAddressMap, ifname);
148 149 150 151 152 153 154 155 156 157

    virMutexUnlock(&ipAddressMapLock);

    return res;
}

int
virNWFilterIPAddrMapInit(void)
{
    ipAddressMap = virNWFilterHashTableCreate(0);
158
    if (!ipAddressMap)
159 160 161 162 163 164 165 166 167 168 169
        return -1;

    return 0;
}

void
virNWFilterIPAddrMapShutdown(void)
{
    virNWFilterHashTableFree(ipAddressMap);
    ipAddressMap = NULL;
}