On 12/17/13, Simon Kelley <si...@thekelleys.org.uk> wrote:
> On 16/12/13 21:26, Nehal J Wani wrote:
>> Is the environment variable DNSMASQ_INTERFACE set when "del" action is
>> called? If not, why?
>
> It _may_ be, if the interface associated with the lease is known. That
> information is not stored in the lease file, so restarting dnsmasq will
> lose the knowledge of the interface and DNSMASQ_INTERFACE will not be
> set, unless there's an intervening event that provides the information.
>
> So
>
> <restart dnsmasq>
> <renew DHCP lease>
> <DHCP lease expires>
> <del event sent>
>
> will set DNSMASQ_INTERFACE
>
> but
>
> <stop dnsmasq>
> <wait whilst lease expires>
> <start dnsmasq>
> <dnsmasq notices that lease has expired and sends del event>
>
> won't.
>
> This is also true of many of the other data supplied, eg
> DNSMASQ_VENDOR_CLASS, DNSMASQ_SUPPLIED_HOSTNAME, DNSMASQ_CIRCUIT_ID
>
> Cheers,
>
>
> Simon.
>
>
>
>
>>
>> On 12/17/13, Simon Kelley <si...@thekelleys.org.uk> wrote:
>>> On 16/12/13 19:06, Nehal J Wani wrote:
>>>> Suppose I am using the script for dnsmasq lease-change hook
>>>> ([dnsmasq.git] / contrib / mactable / macscript) and 3 leases have
>>>> been handed out for a particular network. Now, if I shutdown the
>>>> network and start dnsmasq again after these 3 leases have expired, the
>>>> leases file has zero entries, but the "/tmp/dnsmasq-ip-mac.status"
>>>> file will have those old entries. How will I clean them up? Will I
>>>> have to manually check the timestamps and remove those entries or
>>>> dnsmasq provides something that I am missing?
>>>>
>>>
>>> You'll see "del" events for the leases, either when they actually
>>> expire, or (if dnsmasq isn't running then) when dnsmasq is started
>>> again.
>>>
>>>
>>> Cheers,
>>>
>>> Simon.
>>>
>>>
>>> _______________________________________________
>>> Dnsmasq-discuss mailing list
>>> Dnsmasq-discuss@lists.thekelleys.org.uk
>>> http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
>>>
>>
>>
>
>

Actually, while developing the leases API for libvirt, I have to keep
separate custom-leases file for each network. (One active network is
mapped to one interface only) So, I thought, why not use the env
DNSMASQ_INTERFACE to differentiate? I have attached the source code of
script. The problem arises during:
<restart dnsmasq>
<renew DHCP lease>
<DHCP lease expires>
<del event sent>
Now, since the interface is not known, I'll have to compare IP address
in each file! Is there no way of knowing which file it should
correspond to?

I want to keep leases in different files to ease my task, so that once
a network is completely destroyed and undefined, its leases can also
be deleted easily (by just using unlink() on the desired file).

-- 
Nehal J Wani
/*
 * leasehelper.c:
 *
 * Copyright (C) 2013-2014 Red Hat, Inc.
 *
 * 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
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * Author: Nehal J Wani <nehaljw.k...@gmail.com>
 *
 */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>

#include "virutil.h"
#include "virfile.h"
#include "virbuffer.h"
#include "virstring.h"
#include "virerror.h"
#include "viralloc.h"
#include "configmake.h"

#define VIR_FROM_THIS VIR_FROM_NETWORK

/**
 * VIR_NETWORK_DHCP_LEASE_FIELDS:
 *
 * Macro providing the maximum number of fields in an entry in
 * the leases file
 */
#define VIR_NETWORK_DHCP_LEASE_FIELDS 6
/**
 * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
 *
 * Macro providing the upper limit on the size of leases file
 */
#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX 2097152

/*
 * Use this when passing possibly-NULL strings to printf-a-likes.
 */
# define NULL_STR(s) ((s) ? (s) : "*")

int
main(int argc, char **argv) {

    /* Doesn't hurt to check */
    if (argc < 4)
        return -1;

    const char *action = argv[1];
    const char *interface = NULL_STR(getenv("DNSMASQ_INTERFACE"));
    const char *expirytime = NULL_STR(getenv("DNSMASQ_LEASE_EXPIRES"));
    const char *mac = argv[2];
    const char *ip = argv[3];
    const char *iaid = NULL_STR(getenv("DNSMASQ_IAID"));
    const char *hostname = NULL_STR(getenv("DNSMASQ_SUPPLIED_HOSTNAME"));
    const char *clientid = NULL_STR(getenv("DNSMASQ_CLIENT_ID"));
    const char *leases_str = NULL;
    char *lease_file = NULL;
    char *lease_entries = NULL;
    char *lease_entry = NULL;
    char **lease_fields = NULL;
    bool delete = false;
    bool add = false;
    int rv = -1;
    int lease_file_len = 0;
    FILE *fp = NULL;
    virBuffer buf_new_lease = VIR_BUFFER_INITIALIZER;
    virBuffer buf_all_leases = VIR_BUFFER_INITIALIZER;

    if (virAsprintf(&lease_file, "%s/%s.status", LOCALSTATEDIR
                    "/lib/libvirt/dnsmasq/", interface) < 0)
        goto cleanup;

    if (getenv("DNSMASQ_IAID")) {
        mac = NULL_STR(getenv("DNSMASQ_MAC"));
        clientid = argv[2];
    }

    /* Make sure the file exists. If not, 'touch' it */
    fp = fopen(lease_file, "a+");
    fclose(fp);

    /* Read entire contents */
    if ((lease_file_len = virFileReadAll(lease_file,
                                        VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX,
                                        &lease_entries)) < 0) {
        goto cleanup;
    }


    if (STREQ(action, "add") || STREQ(action, "old") || STREQ(action, "del")) {
        if (mac || STREQ(action, "del")) {
            /* Delete the corresponding lease */
            delete = true;
            if (STREQ(action, "add") || STREQ(action, "old")) {
                add = true;
                /* Enter new lease */
                virBufferAsprintf(&buf_new_lease, "%s %s %s %s %s %s\n",
                                  expirytime, mac, iaid, ip, hostname, clientid);

                if (virBufferError(&buf_new_lease)) {
                    virBufferFreeAndReset(&buf_new_lease);
                    virReportOOMError();
                    goto cleanup;
                }
            }
        }
    }

    lease_entry = lease_entries[0] == '\0' ? NULL : lease_entries;

    while (lease_entry) {
        int nfields = 0;

        char *eol = strchr(lease_entry, '\n');
        *eol = '\0';

        /* Split the lease line */
        if (!(lease_fields = virStringSplit(lease_entry, " ",
                                            VIR_NETWORK_DHCP_LEASE_FIELDS)))
            goto cleanup;

        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)
            goto cleanup;

        if (delete && STREQ(lease_fields[4], ip))
            continue;
        else {
            virBufferAsprintf(&buf_all_leases, "%s %s %s %s %s %s\n",
                              lease_fields[0], lease_fields[1], lease_fields[2],
                              lease_fields[3], lease_fields[4], lease_fields[5]);

            if (virBufferError(&buf_all_leases)) {
                virBufferFreeAndReset(&buf_all_leases);
                virReportOOMError();
                goto cleanup;
            }
        }
    }

    if (add)
        virBufferAsprintf(&buf_all_leases, "%s", virBufferContentAndReset(&buf_new_lease));

    rv = 0;

    /* Write to file */
    leases_str = virBufferContentAndReset(&buf_all_leases);
    if (!leases_str)
        leases_str = "";

    if (virFileWriteStr(lease_file, leases_str, 0) < 0)
        rv = -1;

cleanup:
    VIR_FREE(lease_file);
    VIR_FREE(lease_entries);
    if (lease_fields)
        virStringFreeList(lease_fields);
    return rv;
}
_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

Reply via email to