[libvirt] [PATCHv5 3/4] net-dhcp-leases: Private implementation inside network

Daniel P. Berrange berrange at redhat.com
Thu Dec 12 11:54:24 UTC 2013


On Tue, Nov 26, 2013 at 02:36:00AM +0530, Nehal J Wani wrote:
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index 83dc931..1aedf86 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c

> @@ -2991,6 +3023,220 @@ cleanup:
>      return ret;
>  }
>  
> +/* This function parses the leases file of dnsmasq.
> + *
> + * An example of custom leases file content:
> + *
> + * 1385245780 52:54:00:2f:ba:76 * 192.168.150.153 * *
> + * 1385245781 52:54:00:2f:ba:76 3127926 2001:db8:ca2:2:1::6c * 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
> + * 1385245964 52:54:00:44:7c:d7 * 192.168.150.219 iiit-ad885e4aa1 01:52:54:00:44:7c:d7
> + * 1385245964 52:54:00:44:7c:d7 * 192.168.150.219 * 01:52:54:00:44:7c:d7
> + * 1385246016 52:54:00:5d:99:92 * 192.168.150.212 iiit-ad885e4aa1 01:52:54:00:5d:99:92
> + * 1385246041 52:54:00:3b:16:e0 * 192.168.150.207 * *
> + * 1385246081 52:54:00:db:dd:98 * 192.168.150.234 * *
> + * 1385246088 52:54:00:db:dd:98 14409112 2001:db8:ca2:2:1::6d * 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
> + *
> + */
> +static int
> +networkGetDHCPLeasesHelper(virNetworkObjPtr obj,
> +                           const char *mac,
> +                           virNetworkDHCPLeasesPtr **leases)
> +{
> +    int rv = -1;
> +    size_t i = 0;
> +    size_t nleases = 0;
> +    char *lease_file = NULL;
> +    char **lease_fields = NULL;
> +    char *lease_entries = NULL;
> +    char *lease_entry = NULL;
> +    virNetworkDHCPLeasesPtr *leases_ret = NULL;
> +    virNetworkDHCPLeasesPtr lease = NULL;
> +    int lease_file_len = 0;
> +    bool ipv6 = false;
> +    bool need_results = !!leases;
> +
> +    /* Retrieve custom leases file location */
> +    lease_file = networkDnsmasqLeaseFileNameCustom(obj->def->bridge);
> +
> +    if ((lease_file_len = virFileReadAll(lease_file,
> +                                        VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX,
> +                                        &lease_entries)) < 0) {

Small indentation alignemnt bug.

> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("No leases available for network: %s"), obj->def->name);

Hmm, if we have started the network, but no VMs have yet booted, then
will we find that the lease file does not exist ?  Or is the lease
file guaranteed to exist, even if no leases have been assigned yet.

Basically we must make sure we don't return an error if no leases
have been handed out yet - just return 0 lease results.

> +        goto cleanup;
> +    }
> +
> +    lease_entry = lease_entries[0] == '\0' ? NULL : lease_entries;
> +
> +    while (lease_entry) {
> +        int nfields = 0;
> +        ipv6 = false;
> +
> +        char *eol = strchr(lease_entry, '\n');
> +        *eol = '\0';
> +
> +        /* Split the lease line */
> +        if (!(lease_fields = virStringSplit(lease_entry, " ",
> +                                            VIR_NETWORK_DHCP_LEASE_FIELDS)))
> +            goto error;
> +
> +        nfields = virStringListLength(lease_fields);
> +
> +        /* Forward lease_entry to the next lease */
> +        lease_entry = strchr(lease_entry, '\0');
> +        if (lease_entry - lease_entries + 1 < lease_file_len)
> +            lease_entry++;
> +        else
> +            lease_entry = NULL;
> +
> +        if (nfields != VIR_NETWORK_DHCP_LEASE_FIELDS) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Number of lease params aren't equal to: %d"),
> +                           VIR_NETWORK_DHCP_LEASE_FIELDS);
> +            goto error;
> +        }
> +
> +        if (mac && virMacAddrCompare(mac, lease_fields[1])) {
> +            virStringFreeList(lease_fields);
> +            continue;
> +        }
> +
> +        if (need_results) {
> +            if (VIR_ALLOC(lease) < 0)
> +                goto error;
> +
> +            /* Convert expirytime here */
> +            if (virStrToLong_ll(lease_fields[0], NULL, 10, &(lease->expirytime)) < 0) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR,
> +                               _("Unable to convert lease expiry time to integer: %s"),
> +                               lease_fields[0]);
> +                goto error;
> +            }
> +
> +            /* Unlike IPv4, IPv6 uses ':' instead of '.' as separator */
> +            ipv6 = strchr(lease_fields[3], ':') ? true : false;
> +
> +            lease->type = ipv6 ? VIR_IP_ADDR_TYPE_IPV6 : VIR_IP_ADDR_TYPE_IPV4;
> +            lease->prefix = virSocketAddrGetIpPrefix(&obj->def->ips->address,
> +                                                     &obj->def->ips->netmask,
> +                                                     obj->def->ips->prefix);
> +
> +            if ((VIR_STRDUP(lease->mac, lease_fields[1]) < 0) ||
> +                (VIR_STRDUP(lease->ipaddr, lease_fields[3]) < 0) ||
> +                (VIR_STRDUP(lease->interface, obj->def->bridge) < 0))
> +                goto error;
> +
> +            /* IAID is NULL in case of ipv4 */
> +            if (STREQ(lease_fields[2], "*"))
> +                lease->iaid = NULL;
> +            else if (VIR_STRDUP(lease->iaid, lease_fields[2]) < 0)
> +                goto error;
> +
> +            /* Only two fields, hostname and clientid can be NULL
> +             * Refer: http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2013q3/007544.html
> +             */
> +            if (STREQ(lease_fields[4], "*"))
> +                lease->hostname = NULL;
> +            else if (VIR_STRDUP(lease->hostname, lease_fields[4]) < 0)
> +                goto error;
> +
> +            if (STREQ(lease_fields[5], "*"))
> +                lease->clientid = NULL;
> +            else if (VIR_STRDUP(lease->clientid, lease_fields[5]) < 0)
> +                goto error;
> +
> +            if (VIR_INSERT_ELEMENT(leases_ret, nleases, nleases, lease) < 0)
> +                goto error;
> +        }
> +        else
> +            nleases++;
> +
> +        VIR_FREE(lease);
> +        virStringFreeList(lease_fields);
> +    }
> +
> +    lease_fields = NULL;
> +
> +    if (need_results && mac && !leases_ret) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("no lease with matching MAC address: %s"), mac);
> +        goto error;
> +    }
> +
> +    if (leases_ret) {
> +        /* NULL terminated array */
> +        ignore_value(VIR_REALLOC_N(leases_ret, nleases + 1));
> +        *leases = leases_ret;
> +        leases_ret = NULL;
> +    }
> +
> +    rv = nleases;
> +
> +cleanup:
> +    VIR_FREE(lease);
> +    VIR_FREE(lease_file);
> +    VIR_FREE(lease_entries);
> +    if (lease_fields)
> +        virStringFreeList(lease_fields);
> +    return rv;
> +
> +error:
> +    if (leases_ret) {
> +        for (i = 0; i < nleases; i++)
> +            virNetworkDHCPLeaseFree(leases_ret[i]);
> +        VIR_FREE(leases_ret);
> +    }
> +    goto cleanup;
> +}
> +
> +static int
> +networkGetDHCPLeases(virNetworkPtr network,
> +                     virNetworkDHCPLeasesPtr **leases,
> +                     unsigned int flags)
> +{
> +    int rv = -1;
> +    virNetworkObjPtr obj;
> +
> +    virCheckFlags(0, -1);
> +
> +    if (!(obj = networkObjFromNetwork(network)))
> +        return rv;
> +
> +    if (virNetworkGetDHCPLeasesEnsureACL(network->conn, obj->def) < 0)
> +        goto cleanup;
> +
> +    rv = networkGetDHCPLeasesHelper(obj, NULL, leases);
> +
> +cleanup:
> +    if (obj)
> +        virNetworkObjUnlock(obj);
> +    return rv;
> +}
> +
> +static int
> +networkGetDHCPLeasesForMAC(virNetworkPtr network,
> +                           const char *mac,
> +                           virNetworkDHCPLeasesPtr **leases,
> +                           unsigned int flags)
> +{
> +    int rv = -1;
> +    virNetworkObjPtr obj;
> +
> +    virCheckFlags(0, -1);
> +
> +    if (!(obj = networkObjFromNetwork(network)))
> +        return rv;
> +
> +    if (virNetworkGetDHCPLeasesForMACEnsureACL(network->conn, obj->def) < 0)
> +        goto cleanup;
> +
> +    rv = networkGetDHCPLeasesHelper(obj, mac, leases);
> +
> +cleanup:
> +    if (obj)
> +        virNetworkObjUnlock(obj);
> +    return rv;
> +}
>  
>  static virNetworkDriver networkDriver = {
>      "Network",
> @@ -3015,6 +3261,8 @@ static virNetworkDriver networkDriver = {
>      .networkSetAutostart = networkSetAutostart, /* 0.2.1 */
>      .networkIsActive = networkIsActive, /* 0.7.3 */
>      .networkIsPersistent = networkIsPersistent, /* 0.7.3 */
> +    .networkGetDHCPLeases = networkGetDHCPLeases, /* 1.1.4 */
> +    .networkGetDHCPLeasesForMAC = networkGetDHCPLeasesForMAC, /* 1.1.4 */

s/1.1.4/1.2.1/ now

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list