Re: [Dnsmasq-discuss] patch proposal: getent support for ethers

2009-06-29 Thread Gabriel Winckler

 It needs some clean-up, but something like this has some attractions. The
 main drawback I can see is that the get_() library calls can all block for
 arbitrary lengths of time, which leaves the network with no DNS and no DHCP
 and no TFTP. Worse: gethostbyname() and gethostbyaddr() can possibly attempt
 to use DNS to get the host info, routing the queries through dnsmasq, which
 is blocked in the gethost*() call, leading to deadlock.


Yes, it can lead to a deadlock. As many configurations on libNSS and
PAM. But sysadmins are used to deal with this issues.
You can configure timeouts, and you can (must) use the LDAP to resolve
hostnames (hosts) before DNS, so you don't have the deadlock.

 A solution which pulls all the host info from the LDAP database and pushes
 it into a file which is read by dnsmasq (or the named-pipe variant of this)
 avoids that pain.

Sure it does. But the problem of when trigger a HUP signal to dnsmasq remains.

 Maybe something like --read-ethers=nss to switch on read-ethers semantics,
 but via the nss, would be good, if this solution is adopted?

Sure. I think a switch is required, and the nss should not be the default.

But, only to be clear, the NSS for ether doesn't support enumeration,
so you can't extract all information during initialisation. It must
query on demand.

We also may need compilations flags, because not all architectures
support gettent (I think).



Re: [Dnsmasq-discuss] patch proposal: getent support for ethers

2009-06-27 Thread Gabriel Winckler
Hi,

  While your method should work, it definitely won't be efficient.  Since DHCP 
 is a
 polling protocol, requests have to be more frequent than updates
 almost by definition

I'm using a LDAP backend to keep all information in one place. We have
a small team to deal with many hosts, including remote sites. The goal
is to keep all data in a single structure. I'm sure that this
information won't change offen.

The LDAP was designed to handle a large number of querys. Every ls -l,
for example, generates many requests about UID and GID.


 I accomplished this by making /etc/ethers a pipe connected to a perl
 script which reads all assignments from the database.

Using a named pipe is really a smart move, but (If I understand
correctly) you have a daemon or a trigger process to send HUP signal
to dnsmasq, right? Why not use this process to recreate the
/etc/ethers and than give the signal?

 I think you could set up something similar for your environment.

Sure, that's my plan B.

 I guess if the number of assignments in the database is far larger
 than the number of simultaneously connected clients then querying the
 database per-request might be better than transferring the entire
 database after each change.

Yes, the number is larger, and that exactly my point. To avoid
recreate a file with every entry all the time.

I think dnsmasq should provide a way of query a information when
needed, instead of always store the table itself.
We could use a generic external program call, but the getent/libnss is
more efficient, has designed for that and is already available.
It also features NSCD, a cache mechanism to speed up the process.

You could try this method to query SQL DBs. There are nss libs for
MySQL, Postgress and sqllite.

 I don't know if the dbus interface would allow updating individual 
 assignments.

I don't know much about dbus, but you also have to consider that the
LDAP server may not be in the same machine of the dnsmasq.


Thanks and sorry for the late replay,

Winckler



Re: [Dnsmasq-discuss] patch proposal: getent support for ethers

2009-06-27 Thread Gabriel Winckler
Hi again,

 An addition  of  DBus methods which allow dhcp-host-like configuration
 to be supplied would seem to be a winner for this, IMHO.

If I understand correctly, this still require that the full database
has to be updated to dnsmasq before the lease.

My goal is a mechanism that query a backend or a script for the value
if not found. It seams to be a different scenario.

This is not possible by Dbus interface, is it?

Thanks,

Winckler



[Dnsmasq-discuss] patch proposal: getent support for ethers

2009-06-25 Thread Gabriel Winckler
Hi,

I'm new around here, so I'm not sure if this message belongs to this list.

I made a patch for dnsmasq, allowing dynamic query the ether
information using getent calls.

My goal is use dnsmasq in a large cluster deployment (exactly the
original goal of this code), providing DHCP using LDAP as the backend
server.
Many people have asked for a DHCP server with LDAP support, but nobody
make that happen (at least, not with dynamic updates).

Since this is the best DHCP server code on the market (I tried to
implement this using the ISC... not a happy story), I propose a patch.

Just to clarify my plan:

- Store the MAC/IP information on a LDAP server.
- Configure libnss to access this information (yes, libnss provide
infrastructure for the /etc/ethers file)
- Access the data in dnsmasq using getent.

So, no need to link, call or configure LDAP in dnsmasq.

The drawback is the slowdown (I know, this is why dnsmasq read the
ethers file only during the initialization) of nss queries.

So, I'm submitting a draft patch, that adds this support. In my tests,
everything works (with LDAP!).

** I'm a sysadmin, not a C programmer. **
Feel free to change this patch or express how bad I code.

This patch is for the 2.50test3 revision. (Is there a code repository
somewhere?)

Is this a interesting feature? Any chances of something like this to
be included?
If so, we may need a option getent-ethers, or something.

Thanks,

Winckler
diff -ur dnsmasq-2.50test3.orig/src/dhcp.c dnsmasq-2.50test3/src/dhcp.c
--- dnsmasq-2.50test3.orig/src/dhcp.c	2009-06-23 17:02:09.0 -0300
+++ dnsmasq-2.50test3/src/dhcp.c	2009-06-25 17:42:03.0 -0300
@@ -18,6 +18,9 @@
 
 #ifdef HAVE_DHCP
 
+#include netinet/ether.h
+#include netdb.h
+
 struct iface_param {
   struct in_addr relay, primary;
   struct dhcp_context *current;
@@ -699,6 +702,70 @@
 	  is_addr_in_context(context, config))
 	return config;
 
+  /* search the host using getent */
+
+  {
+struct in_addr ip;
+char buffer [1024];
+struct hostent *host;
+char addr[IN6ADDRSZ];
+char buf2[INET6_ADDRSTRLEN];
+
+   /* search for the MAC */
+if (ether_ntohost (buffer, ether_aton(print_mac(buffer, hwaddr, hw_len))) == 0 )
+{
+  /* found! */
+  my_syslog(LOG_INFO, _(MAC found using getent: %s), buffer);
+
+  if (inet_pton (AF_INET, buffer, addr)  0)
+	// address given
+	host = gethostbyaddr (addr, INADDRSZ, AF_INET);	
+  else
+// hostname given
+host = gethostbyname2 (buffer, AF_INET);
+
+  ip.s_addr = inet_addr(inet_ntop (host-h_addrtype, host-h_addr, buf2, sizeof (buf2)));
+  //ip.s_addr = inet_ntop (host-h_addrtype, host-h_addr, buf2, sizeof (buf2));
+
+  /* getent stage done. */
+
+	  /* search for a suitable config */
+
+  if (context  is_same_net(ip, context-start, context-netmask))
+	  {
+		/* Create a new config */
+config = whine_malloc(sizeof(struct dhcp_config));
+
+config-flags = CONFIG_FROM_ETHERS | CONFIG_ADDR;
+config-domain = NULL;
+
+config-addr =  ip;
+if (host-h_name)
+{
+  config-hostname = whine_malloc(strlen(host-h_name)+1);
+  strcpy(config-hostname, host-h_name);
+  config-flags |= CONFIG_NAME;
+}
+
+config-flags |= CONFIG_NOCLID;
+
+config-hwaddr = whine_malloc(sizeof(struct hwaddr_config));
+memcpy(config-hwaddr-hwaddr, hwaddr, hw_len);
+config-hwaddr-hwaddr_len = hw_len;
+config-hwaddr-hwaddr_type = hw_type;
+config-hwaddr-wildcard_mask = 0;
+config-hwaddr-next = NULL;
+
+		
+/* Insert the new config */ 
+		config-next = configs;
+		configs = config;
+		
+return config;
+  }
+}
+  }
+	
   /* use match with fewest wildcast octets */
   for (candidate = NULL, count = 0, config = configs; config; config = config-next)
 if (is_addr_in_context(context, config))