Please find attached an updated patch for dnsmasq, I have mostly updated the documentation since the previous version.
> Think of the actions as transactions on a database with primary key = > IP address. > > add -> insert new row, there should not exist a record with this IP > address already > del -> remove row. > old -> update existing row. > Thank you for this explanation, I have used it to write the documentation for the DBUS signals. > For convenience with some applications, an "old" event which changes > the hostname gets split up into two transactions; first an "old" event > with the hostname empty, and the previous value of the hostname passed > in the environment variable DNSMASQ_OLD_HOSTNAME., second, an "old" > event with the new hostname. This is the interface to the script, at > the level of calls to queue_script(), the first event is a call with > hostname=old hostname and action=ACTION_OLD_HOSTNAME, and the second > is call with hostname=new hostname and action=ACTION_OLD > > It might be useful to keep this, or just suppress the > ACTION_OLD_HOSTNAME stuff. > OK, I have dropped ACTION_OLD_HOSTNAME, this will not get sent out as a DBUS signal. I think that since the primary key is the IP address, we shouldn't be making a special case for the hostname change. > I don't have a strong preference, to be honest: since it's a discrete > set of events, maybe different signals fits better. I also prefer going with different signals, this means that applications listening on DBUS can just subscribe to the events they want. > Sorry, no, I'm much too old-fashioned. > Ah, that's a pity. I don't suppose it would make any difference if the repository was provided for you? Cheers, Jeremy
diff --git a/dbus/DBus-interface b/dbus/DBus-interface index 07bffd4..af0fc1a 100644 --- a/dbus/DBus-interface +++ b/dbus/DBus-interface @@ -21,6 +21,9 @@ and avoids startup races with the provider of nameserver information. Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq and a single object: /uk/org/thekelleys/dnsmasq +1. METHODS +---------- + Methods are of the form uk.org.thekelleys.<method> @@ -91,4 +94,37 @@ Each call to SetServers completely replaces the set of servers specified by via the DBus, but it leaves any servers specified via the command line or /etc/dnsmasq.conf or /etc/resolv.conf alone. +2. SIGNALS +---------- + +If dnsmasq's DHCP server is active, it will send signals over DBUS whenever +the DHCP lease database changes. Think of these signals as transactions on +a database with the IP address acting as the primary key. + +Signals are of the form: + +uk.org.thekelleys.<signal> + +and their parameters are: + +STRING "192.168.1.115" +STRING "01:23:45:67:89:ab" +STRING "hostname.or.fqdn" + +Available signals are: + +DhcpLeaseAdded +--------------- + +This signal is emitted when a DHCP lease for a given IP address is created. + +DhcpLeaseDeleted +---------------- + +This signal is emitted when a DHCP lease for a given IP address is deleted. + +DhcpLeaseUpdated +---------------- + +This signal is emitted when a DHCP lease for a given IP address is updated. diff --git a/src/dbus.c b/src/dbus.c index 8349ff9..12961d9 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -352,4 +352,42 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset) } } +void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname) +{ + DBusConnection *connection = (DBusConnection *)daemon->dbus; + DBusMessage* message = NULL; + DBusMessageIter args; + const char *value; + const char *action_str; + + if (!connection) + return; + + if (action == ACTION_DEL) + action_str = "DhcpLeaseDeleted"; + else if (action == ACTION_ADD) + action_str = "DhcpLeaseAdded"; + else if (action == ACTION_OLD) + action_str = "DhcpLeaseUpdated"; + else + return; + + if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str))) + return; + + dbus_message_iter_init_append(message, &args); + + value = inet_ntoa(lease->addr); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &value); + + value = print_mac(daemon->namebuff, lease->hwaddr, lease->hwaddr_len); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &value); + + value = hostname ? hostname : ""; + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &value); + + dbus_connection_send(connection, message, NULL); + dbus_message_unref(message); +} + #endif diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 1c6b2a3..8eca840 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -828,6 +828,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)()); char *dbus_init(void); void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset); void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset); +void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname); #endif /* helper.c */ diff --git a/src/helper.c b/src/helper.c index b053967..2e9fd62 100644 --- a/src/helper.c +++ b/src/helper.c @@ -307,6 +307,10 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n size_t size; unsigned int i, hostname_len = 0, clid_len = 0, vclass_len = 0, uclass_len = 0; +#ifdef HAVE_DBUS + emit_dbus_signal(action, lease, hostname); +#endif + /* no script */ if (daemon->helperfd == -1) return;