On 03/17/2014 03:30 PM, Nehal J Wani wrote: > Introduce helper program to catch events from dnsmasq and maintain a custom > lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as > "<interface-name>.status". > > @@ -243,6 +253,7 @@ networkRemoveInactive(virNetworkDriverStatePtr driver, > virNetworkObjPtr net) > { > char *leasefile = NULL; > + char *customleasefile = NULL; > char *radvdconfigfile = NULL; > char *configfile = NULL; > char *radvdpidbase = NULL; > @@ -261,6 +272,9 @@ networkRemoveInactive(virNetworkDriverStatePtr driver, > if (!(leasefile = networkDnsmasqLeaseFileName(def->name))) > goto cleanup; > > + if (!(customleasefile = networkDnsmasqLeaseFileNameCustom(def->bridge))) > + goto cleanup; > + Memory leak - customleasefile is malloc'd memory, but the cleanup label never frees it. > @@ -1120,6 +1135,10 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, > > cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps)); > virCommandAddArgFormat(cmd, "--conf-file=%s", configfile); > + > + /* This helper is used to create custom leases file for libvirt */ > + virCommandAddArgFormat(cmd, "--dhcp-script=%s", LIBEXECDIR "/libvirt_leaseshelper"); This is a bit hard-coded, and won't play nicely with ./run. Ideally, we should be constructing the name so that if argv[0] is an uninstalled in-tree binary, then we convert to a name relative to the build tree instead of LIBEXECDIR; that way, when using ./run, we test the just-built libvirt_leaseshelper instead of a pre-installed version. > +++ b/src/network/leaseshelper.c > @@ -0,0 +1,328 @@ > +/* > + * leasehelper.c: Helper program to create custom leases file > + * > + * Copyright (C) 2014 Red Hat, Inc. You're allowed to claim copyright if you'd like; you don't have to assign it all to Red Hat. > + > +ATTRIBUTE_NORETURN static void > +usage(int status) > +{ > + if (status) { > + fprintf(stderr, _("%s: try --help for more details\n"), program_name); > + } else { > + printf(_("Usage: %s ACTION MAC|CLIENTID IP HOSTNAME\n" > + " or: %s ACTION MAC|CLIENTID IP\n"), Could be compressed to one line as "%s ACTION MAC|CLIENTID IP [HOSTNAME]". Maybe worth listing the set of valid ACTION verbs. > + size_t i = 0; > + int size = 0; Usually something named 'size' is of type 'size_t' - but I guess I'll have to see how you use it. > + > + if (argc != 4 && argc != 5) { > + /* Refer man page of dnsmasq --dhcp-script for more details */ This comment might also be useful as actual output of the --help option. > + /* Check if it is an IPv6 lease */ > + if (virGetEnvAllowSUID("DNSMASQ_IAID")) { > + mac = virGetEnvAllowSUID("DNSMASQ_MAC"); > + clientid=argv[2]; Space around = > + } > + > + if (virAsprintf(&custom_lease_file, "%s/%s.status", LOCALSTATEDIR > + "/lib/libvirt/dnsmasq/", interface) < 0) Unusual line break; I would have done: if (virAsprintf(&custom_lease_file, "%s/%s.status", LOCALSTATEDIR "/lib/libvirt/dnsmasq/", interface) < 0) or even: if (virAsprintf(&custom_lease_file, LOCALSTATEDIR "/lib/libvirt/dnsmasq/%s.status", interface) < 0) > + > + if (STREQ(action, "add") || STREQ(action, "old") || STREQ(action, "del")) { > + if (mac || STREQ(action, "del")) { This is a lot of repeated STREQ. It might be nicer if you use VIR_ENUM_IMPL earlier on, and convert the incoming string to an enum value; then the rest of your code will use integer comparisons instead of repeat string comparisons. > + > + if ((iaid && virJSONValueObjectAppendString(lease_new, "iaid", > + iaid) < 0) || > + (ip && virJSONValueObjectAppendString(lease_new, "ip-address", > + ip) < 0) || This works, but it's harder to debug (gdb is rather picky about how it puts breakpoints across chains of && and || when optimization gets involved). It may be a bit nicer to have multiple if statements: if (iaid && virJSON...() < 0) goto cleanup; if (ip && virJSON...() < 0) goto cleanup; ... > + > + if ((size = virJSONValueArraySize(leases_array)) < 0) { Ah, so size really is an 'int'. You were right here. > + for (i = 0; i < size; i++) { > + /* Check whether lease has expired or not */ > + if (exptime_tmp < (long long) time(NULL)) This calls time() in a loop, which can get a bit expensive on some hardware, as well as a bit unpredictable (the time changes over the course of the loop). Better might be to call time() outside the loop, then compare against that value inside the loop. Looks like you are converging on something worth applying. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Attachment:
signature.asc
Description: OpenPGP digital signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list