Re: [Dnsmasq-discuss] patch proposal: getent support for ethers
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
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
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
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))