[Dnsmasq-discuss] Active-passive failover for dnsmasq with ldirectord

2020-01-23 Thread Tom Fernandes
Hi,

I read the old threads regarding dnsmasq and high availability and would
like to know if the following setup is possible or if I'm missing something.

Master: dnsmasq A (192.168.1.10)
Slave: dnsmasq B (192.168.1.20)

Loadbalancer virtual IP in ldirectord 192.168.1.30

The clients use the virtual IP 192.168.1.30 as their nameserver.

Host A is a "normally" configured dnsmasq server which also offers DHCP.

Host B is configured the same way like server A with addition of an
iptables rule which blocks incoming DHCP-Requests.

The configuration files + the DHCP leases file are on a shared
(active-active) Cluster-FS available to A and B.

ldirectord is configured with with one realserver (A) and one fallback
server (B). In this configuration a connection to 192.168.1.30 will only
lookup records from host A (as long as A is alive).

When A goes down, the following will happen:
1) The fallback server B will be used when clients lookup records from
192.168.1.30
2) The loadbalancer will connect (through ldirectords "fallbackcommand"
with the "start" parameter) via SSH to server B and remove the iptables
rule which blocks incoming DHCP requests and will restart dnsmasq.

Now server B is offering DHCP and DNS requests in the same way like
server A was doing before.

When server A gets online again the "fallbackcommand" on the
loadbalancer is called again (this time with the "stop" parameter). It
will now connect to server A and restart dnsmasq and to server B and set
the iptables rule again to block incoming DHCP requests. Server B will
become the fallback server again.

What do you think?

Warm regards,


Tom

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] [PATCH V2] Add new extensible D-Bus signal

2020-01-23 Thread Victorien Molle
For our usage, we need to have more informations sent over D-Bus such as the 
interface
name, the vendor class identifier and the lease expiration time.

To achieve this, we add a new D-Bus signal "DhcpLeaseNotification" which 
exports the
requested informations as a dictionnary.
It also has the advantage to be flexible if someone wants to add a new entry in 
the
future.

Note: in order to get leases extradata be populated, we enabled this feature if 
D-Bus
is enabled in configuration file (this was enabled in the past only if a script 
was
ran on leases updates).

Here is an example of the obtained result with a Python3 program:

''' Define our D-Bus callback '''
def cb(action, ipaddr, hwaddr, hostname, info):
print(f'Action: {action}')
print(f'IP: {ipaddr}')
print(f'Hostname: {hostname}')
for k in info:
print(f'{k}: {info.get(k)}')

''' Connect to signal DhcpLeaseNotification on interface 
uk.org.thekelleys.dnsmasq '''
DNSMasq.listen('DhcpLeaseNotification', callback=cb)

''' Run GLib loop '''
GLib.MainLoop().run()

''' When DNSMasq receives a DHCP request, here is the result: '''

Action: 3
IP: 192.168.1.100
Hostname: Nucleus.nucle.us
interface: br-mgmt
vendor_class: LaGrosseBiche
expiration: 1575667431

Signed-off-by: Victorien Molle 
Signed-off-by: Florent Fourcot 
---
 dbus/DBus-interface |   9 
 src/dbus.c  | 118 +++-
 src/dnsmasq.h   |   2 +-
 src/lease.c |   2 +-
 src/rfc2131.c   |  12 ++---
 5 files changed, 134 insertions(+), 9 deletions(-)

diff --git a/dbus/DBus-interface b/dbus/DBus-interface
index 954c5b9..ed42551 100644
--- a/dbus/DBus-interface
+++ b/dbus/DBus-interface
@@ -273,14 +273,23 @@ DhcpLeaseAdded
 ---
 
 This signal is emitted when a DHCP lease for a given IP address is created.
+This will also trigger the DhcpLeaseNotification signal.
 
 DhcpLeaseDeleted
 
 
 This signal is emitted when a DHCP lease for a given IP address is deleted.
+This will also trigger the DhcpLeaseNotification signal.
 
 DhcpLeaseUpdated
 
 
 This signal is emitted when a DHCP lease for a given IP address is updated.
+This will also trigger the DhcpLeaseNotification signal.
+
+DhcpLeaseNotification
+-
+
+This signal is emitted when a DHCP lease action is triggered. It exports,
+as a dictionnary, more informations than the other signals.
  
diff --git a/src/dbus.c b/src/dbus.c
index c0ce903..c906e11 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -55,6 +55,7 @@ const char* introspection_xml_template =
 "\n"
 "  \n"
 "\n"
+#ifdef HAVE_DHCP
 "\n"
 "  \n"
 "  \n"
@@ -70,7 +71,13 @@ const char* introspection_xml_template =
 "  \n"
 "  \n"
 "\n"
-#ifdef HAVE_DHCP
+"\n"
+"  \n"
+"  \n"
+"  \n"
+"  \n"
+"  \n"
+"\n"
 "\n"
 "   \n"
 "   \n"
@@ -98,6 +105,12 @@ struct watch {
   struct watch *next;
 };
 
+struct lease_info {
+  char *key;
+  char *fmt;
+  char dbus_type;
+  DBusBasicValue value;
+};
 
 static dbus_bool_t add_watch(DBusWatch *watch, void *data)
 {
@@ -828,6 +841,106 @@ void check_dbus_listeners()
 }
 
 #ifdef HAVE_DHCP
+/*
+  As this function is called by emit_dbus_signal, we already have access to 
ipaddr, hwaddr and hostname attributes
+  NOTE: connection attribute is currently not NULL as it is verified by 
emit_dbus_signal
+*/
+void emit_dhcplease_notification(DBusConnection *connection, int action, 
struct dhcp_lease *lease, char *ipaddr, char *hwaddr, char *hostname)
+{
+  DBusMessageIter array, dict, iter, variant;
+  dbus_uint64_t expires = lease->expires;
+  unsigned char *buf = lease->extradata;
+  dbus_int32_t act_type = action;
+  char interface[IF_NAMESIZE];
+  DBusMessage* message = NULL;
+  struct lease_info *info;
+  int fd = daemon->dhcpfd;
+#if defined(HAVE_SCRIPT) || defined(HAVE_DBUS)
+  char *vendor_class;
+  int allocated = 0;
+#endif
+
+#ifdef HAVE_DHCP6
+  if (!daemon->dhcp)
+fd = daemon->dhcp6fd;
+#endif
+
+  /* Get interface name */
+  if (!indextoname(fd, lease->last_interface, interface))
+interface[0] = 0;
+
+#if defined(HAVE_SCRIPT) || defined(HAVE_DBUS)
+  vendor_class = "";
+  /* As defined in rfc2131.c, the first data is the vendor class even if it is 
empty */
+  if (buf && *buf != 0)
+{
+  vendor_class = (char*)whine_malloc(lease->extradata_len + 1);
+  if (vendor_class)
+{
+  allocated = 1;
+  strncpy(vendor_class, (const char*)buf, (lease->extradata_len));
+}
+  else
+{
+  vendor_class = "";
+}
+}
+#endif
+
+  struct lease_info infos[] = {{.key = "interface", .fmt = "s", .dbus_type = 
DBUS_TYPE_STRING, .value.str = interface},
+#if defined(HAVE_SCRIPT) || defined(HAVE_DBUS)
+   {.key = "vendor_class", .fmt = "s", .dbus_type 
= DBUS_TYPE_STRING, .value.str = vendor_class},
+#endif
+   {.key =