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;

Reply via email to