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

Eric Blake eblake at redhat.com
Mon Sep 16 19:00:23 UTC 2013


On 09/15/2013 11:49 PM, Nehal J Wani wrote:
> By querying the driver for the path of the leases file for the given virtual
> network and parsing it to retrieve info.
> 
> src/network/bridge_driver.c:
>   * Implement networkGetDHCPLeases
>   * Implement networkGetDHCPLeasesForMAC
>   * Implement networkGetDHCPLeasesHelper
> 
> ---
>  src/network/bridge_driver.c | 177 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 177 insertions(+)
> 

>  }
>  
> +/* This function parese the leases file of dnsmasq.

s/parese/parses/

> + *
> + * An example of leases file content:
> + *
> + * 1379024255 52:54:00:20:70:3d 192.168.105.240 * *
> + * 1379023351 52:54:00:b1:70:19 192.168.105.201 * *
> + */
> +static int
> +networkGetDHCPLeasesHelper(virNetworkPtr network,
> +                           virNetworkObjPtr obj,
> +                           const char *mac,
> +                           virNetworkDHCPLeasesPtr **leases)
> +{
> +    int rv = -1;
> +    size_t i = 0;
> +    size_t nleases = 0;
> +    char *leasefile;
> +    char **lease_fields;
> +    char dhcpentry[VIR_NETWORK_DHCP_LEASE_LENGTH_MAX];
> +    virNetworkDHCPLeasesPtr *leases_ret = NULL;
> +    FILE *fp = NULL;
> +
> +    if (!network) {
> +        virReportError(VIR_ERR_NO_NETWORK, "%s",
> +                       _("no network with matching name"));
> +        return -1;
> +    }

Dead code (network is always non-NULL if you get here).

> +
> +    /* Retrieve leases file location */
> +    leasefile = networkDnsmasqLeaseFileNameDefault(network->name);
> +    if (!(fp = fopen(leasefile, "r"))) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Unable to open leases file: %s"), leasefile);
> +        goto cleanup;
> +    }
> +
> +    while (fgets(dhcpentry, sizeof(dhcpentry), fp) != NULL) {

Rather than hand-rolling your file reading, I would suggest using
virFileReadAll(leasefile, len, &buf), and then loop over the returned
buffer.  That gives you nicer guarantees about handling things like
interrupts that fgets() might get confused on.

> +        virNetworkDHCPLeasesPtr lease = NULL;
> +
> +        /* Remove newline */
> +        dhcpentry[strlen(dhcpentry) - 1] = '\0';
> +
> +        /* Split the lease line */
> +        lease_fields = virStringSplit(dhcpentry, " ", VIR_NETWORK_DHCP_LEASE_FIELDS);
> +
> +        if (virStringListLength(lease_fields) != 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 && STRNEQ(mac, lease_fields[1]))

This may not do what you want - remember, 'mac' is specified by the
user, whereas lease_fields[1] is specified by dnsmasq.  While we can
reasonably assume that dnsmasq always uses a canonical MAC
representation (such as 52:54:00:1a:0a:6d), the user may have passed in
a non-canonical form that we can still parse and recognize as the same
address (such as 52:54:00:1A:0a:6D, or even 52:54:0:1a:a:6d).  You want
to use virMacAddrCompare() instead of STRNEQ.

> +            continue;

Memleak.  lease_fields is allocated each iteration of the loop, so it
must be freed each iteration of the loop.

> +
> +        if (VIR_EXPAND_N(leases_ret, nleases, 1) < 0)
> +            goto error;
> +
> +        if (VIR_ALLOC(leases_ret[nleases - 1]) < 0)
> +            goto error;

Rather than trying to allocate it into the destination array, it might
be better to allocate into a local variable, and only on successful
population of the entire element, use VIR_INSERT_ELEMENT to move it into
the array at that time.

> +
> +        lease = leases_ret[nleases - 1];
> +
> +        /* 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;
> +        }
> +
> +        /* Hardcoded, as dnsmasq uses ipv4 */
> +        lease->type = 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[2]) < 0) ||
> +            (VIR_STRDUP(lease->hostname, lease_fields[3]) < 0) ||
> +            (VIR_STRDUP(lease->clientid, lease_fields[4]) < 0))
> +            goto error;
> +    }

Transfer semantics rather than VIR_STRDUP might save some memory pressure.

> +
> +    if (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_FORCE_FCLOSE(fp);
> +    VIR_FREE(leasefile);
> +    return rv;
> +
> +error:
> +    if (leases_ret) {
> +        for (i = 0; i < nleases; i++)
> +            virNetworkDHCPLeaseFree(leases_ret[i]);
> +    }
> +    VIR_FREE(leases_ret);
> +    goto cleanup;
> +}
> +


-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 621 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20130916/42858954/attachment-0001.sig>


More information about the libvir-list mailing list