Signed-off-by: Matthias Fischer <matthias.fischer(a)ipfire.org>
---
lfs/dnsmasq | 6 +
.../dnsmasq/001-Debian_init_d_script_fix.patch | 74 +++
.../dnsmasq/002-Add_--help_to_manpage.patch | 66 +++
...nd_dhcp_lease_time_to_contrib_lease_tools.patch | 73 +++
...004-Add_contrib_lease-tools_dhcp_release6.patch | 528 +++++++++++++++++++++
...am_nameservers_when_logging_configuration.patch | 85 ++++
..._interface_when_--bridge-interface_in_use.patch | 70 +++
7 files changed, 902 insertions(+)
create mode 100644 src/patches/dnsmasq/001-Debian_init_d_script_fix.patch
create mode 100644 src/patches/dnsmasq/002-Add_--help_to_manpage.patch
create mode 100644 src/patches/dnsmasq/003-Move_dhcp_release_and_dhcp_lease_time_to_contrib_lease_tools.patch
create mode 100644 src/patches/dnsmasq/004-Add_contrib_lease-tools_dhcp_release6.patch
create mode 100644 src/patches/dnsmasq/005-Limit_number_of_upstream_nameservers_when_logging_configuration.patch
create mode 100644 src/patches/dnsmasq/006-Fix_for_DHCP_in_transmission_interface_when_--bridge-interface_in_use.patch
diff --git a/lfs/dnsmasq b/lfs/dnsmasq
index 3b72746..feb1789 100644
--- a/lfs/dnsmasq
+++ b/lfs/dnsmasq
@@ -73,6 +73,12 @@ $(subst %,%_MD5,$(objects)) :
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/001-Debian_init_d_script_fix.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/002-Add_--help_to_manpage.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/003-Move_dhcp_release_and_dhcp_lease_time_to_contrib_lease_tools.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/004-Add_contrib_lease-tools_dhcp_release6.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/005-Limit_number_of_upstream_nameservers_when_logging_configuration.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/006-Fix_for_DHCP_in_transmission_interface_when_--bridge-interface_in_use.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
cd $(DIR_APP) && sed -i src/config.h \
diff --git a/src/patches/dnsmasq/001-Debian_init_d_script_fix.patch b/src/patches/dnsmasq/001-Debian_init_d_script_fix.patch
new file mode 100644
index 0000000..86d0480
--- /dev/null
+++ b/src/patches/dnsmasq/001-Debian_init_d_script_fix.patch
@@ -0,0 +1,74 @@
+From 332c41e2ff533649dc48b6bab00804d795f348f5 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)thekelleys.org.uk>
+Date: Sun, 1 May 2016 22:36:46 +0100
+Subject: [PATCH] Debian init.d script fix.
+
+---
+ debian/changelog | 8 +++++---
+ debian/init | 14 +++++++-------
+ 2 files changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/debian/changelog b/debian/changelog
+index e727406..8a0341c 100644
+--- a/debian/changelog
++++ b/debian/changelog
+@@ -3,19 +3,21 @@ dnsmasq (2.76-1) unstable; urgency=low
+ * New upstream. (closes: #798586)
+ * Use /run/dnsmasq directly, rather than relying on link from /var/run
+ to avoid problems before /var is mounted. (closes: #800351)
+-
++ * Test for the existance of /usr/share/doc/dnsmasq rather then
++ /etc/dnsmasq.d/README in the daemon startup script. (closes: #819856)
++
+ -- Simon Kelley <simon(a)thekelleys.org.uk> Thur, 10 Sep 2015 23:07:21 +0000
+
+ dnsmasq (2.75-1) unstable; urgency=low
+
+ * New upstream. (closes: #794095)
+-
++
+ -- Simon Kelley <simon(a)thekelleys.org.uk> Thur, 30 Jul 2015 20:58:31 +0000
+
+ dnsmasq (2.74-1) unstable; urgency=low
+
+ * New upstream. (LP: #1468611)
+-
++
+ -- Simon Kelley <simon(a)thekelleys.org.uk> Wed, 15 Jul 2015 21:54:11 +0000
+
+ dnsmasq (2.73-2) unstable; urgency=low
+diff --git a/debian/init b/debian/init
+index 6afe191..10b277c 100644
+--- a/debian/init
++++ b/debian/init
+@@ -8,7 +8,8 @@
+ # Description: DHCP and DNS server
+ ### END INIT INFO
+
+-set +e # Don't exit on error status
++# Don't exit on error status
++set +e
+
+ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+ DAEMON=/usr/sbin/dnsmasq
+@@ -29,12 +30,11 @@ if [ -r /etc/default/locale ]; then
+ export LANG
+ fi
+
+-# /etc/dnsmasq.d/README is a non-conffile installed by the dnsmasq package.
+-# Should the dnsmasq package be removed, the following test ensures that
+-# the daemon is no longer started, even if the dnsmasq-base package is
+-# still in place.
+-test -e /etc/dnsmasq.d/README || exit 0
+-
++# The following test ensures the dnsmasq service is not started, when the
++# package 'dnsmasq' is removed but not purged, even if the dnsmasq-base
++# package is still in place.
++test -d /usr/share/doc/dnsmasq || exit 0
++
+ test -x $DAEMON || exit 0
+
+ # Provide skeleton LSB log functions for backports which don't have LSB functions.
+--
+2.5.5
+
diff --git a/src/patches/dnsmasq/002-Add_--help_to_manpage.patch b/src/patches/dnsmasq/002-Add_--help_to_manpage.patch
new file mode 100644
index 0000000..82de3ee
--- /dev/null
+++ b/src/patches/dnsmasq/002-Add_--help_to_manpage.patch
@@ -0,0 +1,66 @@
+From 09217a1a874c654bfd4d29a1097f44435b4c632d Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)thekelleys.org.uk>
+Date: Tue, 3 May 2016 17:04:35 +0100
+Subject: [PATCH] Add --help to manpage .
+
+---
+ debian/changelog | 1 +
+ man/dnsmasq.8 | 9 ++++++++-
+ src/option.c | 2 +-
+ 3 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/debian/changelog b/debian/changelog
+index 8a0341c..e028f57 100644
+--- a/debian/changelog
++++ b/debian/changelog
+@@ -5,6 +5,7 @@ dnsmasq (2.76-1) unstable; urgency=low
+ to avoid problems before /var is mounted. (closes: #800351)
+ * Test for the existance of /usr/share/doc/dnsmasq rather then
+ /etc/dnsmasq.d/README in the daemon startup script. (closes: #819856)
++ * Add --help to manpage and mention dhcp6 in summary. (closes: #821226)
+
+ -- Simon Kelley <simon(a)thekelleys.org.uk> Thur, 10 Sep 2015 23:07:21 +0000
+
+diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
+index fd4b7c5..dacd9ce 100644
+--- a/man/dnsmasq.8
++++ b/man/dnsmasq.8
+@@ -42,6 +42,13 @@ the configuration file.
+ Read and syntax check configuration file(s). Exit with code 0 if all
+ is OK, or a non-zero code otherwise. Do not start up dnsmasq.
+ .TP
++.B \-w, --help
++Display all command-line options.
++.B --help dhcp
++will display known DHCPv4 configuration options, and
++.B --help dhcp6
++will display DHCPv6 options.
++.TP
+ .B \-h, --no-hosts
+ Don't read the hostnames in /etc/hosts.
+ .TP
+@@ -317,7 +324,7 @@ instead of the correct NXDOMAIN response. This option tells dnsmasq to
+ fake the correct response when it sees this behaviour. As at Sept 2003
+ the IP address being returned by Verisign is 64.94.110.11
+ .TP
+-.B \-B, --ignore-address=<ipaddr>
++.B --ignore-address=<ipaddr>
+ Ignore replies to A-record queries which include the specified address.
+ No error is generated, dnsmasq simply continues to listen for another reply.
+ This is useful to defeat blocking strategies which rely on quickly supplying a
+diff --git a/src/option.c b/src/option.c
+index c66f401..0b35500 100644
+--- a/src/option.c
++++ b/src/option.c
+@@ -402,7 +402,7 @@ static struct {
+ { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
+ { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
+ { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
+- { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
++ { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."), NULL },
+ { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
+ { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
+ { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
+--
+2.5.5
+
diff --git a/src/patches/dnsmasq/003-Move_dhcp_release_and_dhcp_lease_time_to_contrib_lease_tools.patch b/src/patches/dnsmasq/003-Move_dhcp_release_and_dhcp_lease_time_to_contrib_lease_tools.patch
new file mode 100644
index 0000000..6065904
--- /dev/null
+++ b/src/patches/dnsmasq/003-Move_dhcp_release_and_dhcp_lease_time_to_contrib_lease_tools.patch
@@ -0,0 +1,73 @@
+From c6cdf6bbee27d1127847ce7bdff2a22a785f9723 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)thekelleys.org.uk>
+Date: Tue, 3 May 2016 21:14:14 +0100
+Subject: [PATCH] Move dhcp_release and dhcp_lease_time to contrib/lease_tools.
+
+---
+ contrib/{wrt => lease-tools}/Makefile | 0
+ contrib/{wrt => lease-tools}/dhcp_lease_time.1 | 0
+ contrib/{wrt => lease-tools}/dhcp_lease_time.c | 0
+ contrib/{wrt => lease-tools}/dhcp_release.1 | 0
+ contrib/{wrt => lease-tools}/dhcp_release.c | 0
+ debian/rules | 12 ++++++------
+ 6 files changed, 6 insertions(+), 6 deletions(-)
+ rename contrib/{wrt => lease-tools}/Makefile (100%)
+ rename contrib/{wrt => lease-tools}/dhcp_lease_time.1 (100%)
+ rename contrib/{wrt => lease-tools}/dhcp_lease_time.c (100%)
+ rename contrib/{wrt => lease-tools}/dhcp_release.1 (100%)
+ rename contrib/{wrt => lease-tools}/dhcp_release.c (100%)
+
+diff --git a/contrib/wrt/Makefile b/contrib/lease-tools/Makefile
+similarity index 100%
+rename from contrib/wrt/Makefile
+rename to contrib/lease-tools/Makefile
+diff --git a/contrib/wrt/dhcp_lease_time.1 b/contrib/lease-tools/dhcp_lease_time.1
+similarity index 100%
+rename from contrib/wrt/dhcp_lease_time.1
+rename to contrib/lease-tools/dhcp_lease_time.1
+diff --git a/contrib/wrt/dhcp_lease_time.c b/contrib/lease-tools/dhcp_lease_time.c
+similarity index 100%
+rename from contrib/wrt/dhcp_lease_time.c
+rename to contrib/lease-tools/dhcp_lease_time.c
+diff --git a/contrib/wrt/dhcp_release.1 b/contrib/lease-tools/dhcp_release.1
+similarity index 100%
+rename from contrib/wrt/dhcp_release.1
+rename to contrib/lease-tools/dhcp_release.1
+diff --git a/contrib/wrt/dhcp_release.c b/contrib/lease-tools/dhcp_release.c
+similarity index 100%
+rename from contrib/wrt/dhcp_release.c
+rename to contrib/lease-tools/dhcp_release.c
+diff --git a/debian/rules b/debian/rules
+index 8612092..193b30c 100755
+--- a/debian/rules
++++ b/debian/rules
+@@ -93,7 +93,7 @@ clean:
+ $(checkdir)
+ rm -rf debian/daemon debian/base debian/utils debian/*~ debian/files debian/substvars debian/utils-substvars
+ make clean
+- make -C contrib/wrt clean
++ make -C contrib/lease-tools clean
+
+ binary-indep: checkroot
+ $(checkdir)
+@@ -184,12 +184,12 @@ ifeq ($(DEB_HOST_ARCH_OS),linux)
+ -d debian/utils/usr/share/man/man1 \
+ -d debian/utils/usr/bin \
+ -d debian/utils/usr/share/doc/dnsmasq-utils
+- make -C contrib/wrt PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
+- install -m 755 contrib/wrt/dhcp_release debian/utils/usr/bin/dhcp_release
+- install -m 644 contrib/wrt/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
++ make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
++ install -m 755 contrib/lease-tools/dhcp_release debian/utils/usr/bin/dhcp_release
++ install -m 644 contrib/lease-tools/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
+ gzip -9n debian/utils/usr/share/man/man1/dhcp_release.1
+- install -m 755 contrib/wrt/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
+- install -m 644 contrib/wrt/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
++ install -m 755 contrib/lease-tools/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
++ install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
+ install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
+ install -m 644 debian/changelog debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
+ gzip -9n debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
+--
+2.5.5
+
diff --git a/src/patches/dnsmasq/004-Add_contrib_lease-tools_dhcp_release6.patch b/src/patches/dnsmasq/004-Add_contrib_lease-tools_dhcp_release6.patch
new file mode 100644
index 0000000..6426d39
--- /dev/null
+++ b/src/patches/dnsmasq/004-Add_contrib_lease-tools_dhcp_release6.patch
@@ -0,0 +1,528 @@
+From 69cbf78bb676e493f0a4cd6dc7ffec0fcafafed5 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)thekelleys.org.uk>
+Date: Tue, 3 May 2016 21:33:38 +0100
+Subject: [PATCH] Add contrib/lease-tools/dhcp_release6
+
+---
+ CHANGELOG | 6 +
+ contrib/lease-tools/Makefile | 4 +-
+ contrib/lease-tools/dhcp_release6.1 | 38 ++++
+ contrib/lease-tools/dhcp_release6.c | 416 ++++++++++++++++++++++++++++++++++++
+ debian/rules | 3 +
+ 5 files changed, 465 insertions(+), 2 deletions(-)
+ create mode 100644 contrib/lease-tools/dhcp_release6.1
+ create mode 100644 contrib/lease-tools/dhcp_release6.c
+
+diff --git a/CHANGELOG b/CHANGELOG
+index aa53fba..7d4a061 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -65,6 +65,12 @@ version 2.76
+ --servers-file to define upstream DNS servers. Thanks to
+ Scott Bonar for the bug report.
+
++ Move the dhcp_release and dhcp_lease_time tools from
++ contrib/wrt to contrib/lease-tools.
++
++ Add dhcp_release6 to contrib/lease-tools. Many thanks
++ to Sergey Nechaev for this code.
++
+
+ version 2.75
+ Fix reversion on 2.74 which caused 100% CPU use when a
+diff --git a/contrib/lease-tools/Makefile b/contrib/lease-tools/Makefile
+index 68e8d32..f38f2ed 100644
+--- a/contrib/lease-tools/Makefile
++++ b/contrib/lease-tools/Makefile
+@@ -1,6 +1,6 @@
+ CFLAGS?= -O2 -Wall -W
+
+-all: dhcp_release dhcp_lease_time
++all: dhcp_release dhcp_release6 dhcp_lease_time
+
+ clean:
+- rm -f *~ *.o core dhcp_release dhcp_lease_time
++ rm -f *~ *.o core dhcp_release dhcp_release6 dhcp_lease_time
+diff --git a/contrib/lease-tools/dhcp_release6.1 b/contrib/lease-tools/dhcp_release6.1
+new file mode 100644
+index 0000000..763e01c
+--- /dev/null
++++ b/contrib/lease-tools/dhcp_release6.1
+@@ -0,0 +1,38 @@
++.TH DHCP_RELEASE 1
++.SH NAME
++dhcp_release6 \- Release a DHCPv6 lease on a the local dnsmasq DHCP server.
++.SH SYNOPSIS
++.B dhcp_release6 --iface <interface> --client-id <client-id> --server-id
++server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
++.SH "DESCRIPTION"
++A utility which forces the DHCP server running on this machine to release a
++DHCPv6 lease.
++.SS OPTIONS
++.IP "-a, --ip"
++IPv6 address to release.
++.IP "-c, --client-id"
++Colon-separated hex string representing DHCPv6 client id. Normally
++it can be found in leases file both on client and server.
++.IP "-d, --dry-run"
++Print hexadecimal representation of generated DHCPv6 release packet to standard
++output and exit.
++.IP "-h, --help"
++print usage information to standard output and exit.
++.IP "-i, --iaid"
++Decimal representation of DHCPv6 IAID. Normally it can be found in leases file
++both on client and server.
++.IP "-n, --iface"
++Network interface to send a DHCPv6 release packet from.
++.IP "-s, --server-id"
++Colon-separated hex string representing DHCPv6 server id. Normally
++it can be found in leases file both on client and server.
++.SH NOTES
++MUST be run as root - will fail otherwise.
++.SH LIMITATIONS
++Only usable on IPv6 DHCP leases.
++.SH SEE ALSO
++.BR dnsmasq (8)
++.SH AUTHOR
++This manual page was written by Simon Kelley <simon(a)thekelleys.org.uk>.
++
++
+diff --git a/contrib/lease-tools/dhcp_release6.c b/contrib/lease-tools/dhcp_release6.c
+new file mode 100644
+index 0000000..74fb26a
+--- /dev/null
++++ b/contrib/lease-tools/dhcp_release6.c
+@@ -0,0 +1,416 @@
++/*
++ dhcp_release6 --iface <interface> --client-id <client-id> --server-id
++ server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
++ MUST be run as root - will fail othewise
++ */
++
++/* Send a DHCPRELEASE message to IPv6 multicast address via the specified interface
++ to tell the local DHCP server to delete a particular lease.
++
++ The interface argument is the interface in which a DHCP
++ request _would_ be received if it was coming from the client,
++ rather than being faked up here.
++
++ The client-id argument is colon-separated hex string and mandatory. Normally
++ it can be found in leases file both on client and server
++
++ The server-id argument is colon-separated hex string and mandatory. Normally
++ it can be found in leases file both on client and server.
++
++ The iaid argument is numeric string and mandatory. Normally
++ it can be found in leases file both on client and server.
++
++ IP is an IPv6 adress to release
++
++ If --dry-run is specified, dhcp_release6 just prints hexadecimal represantation of
++ packet to send to stdout and exits.
++
++ If --help is specified, dhcp_release6 print usage information to stdout and exits
++
++
++
++ */
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <strings.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <arpa/inet.h>
++#include <getopt.h>
++#include <errno.h>
++#include <unistd.h>
++
++#define NOT_REPLY_CODE 115
++typedef unsigned char u8;
++typedef unsigned short u16;
++typedef unsigned int u32;
++
++enum DHCP6_TYPES{
++ SOLICIT = 1,
++ ADVERTISE = 2,
++ REQUEST = 3,
++ CONFIRM = 4,
++ RENEW = 5,
++ REBIND = 6,
++ REPLY = 7,
++ RELEASE = 8,
++ DECLINE = 9,
++ RECONFIGURE = 10,
++ INFORMATION_REQUEST = 11,
++ RELAY_FORW = 12,
++ RELAY_REPL = 13
++
++};
++enum DHCP6_OPTIONS{
++ CLIENTID = 1,
++ SERVERID = 2,
++ IA_NA = 3,
++ IA_TA = 4,
++ IAADDR = 5,
++ ORO = 6,
++ PREFERENCE = 7,
++ ELAPSED_TIME = 8,
++ RELAY_MSG = 9,
++ AUTH = 11,
++ UNICAST = 12,
++ STATUS_CODE = 13,
++ RAPID_COMMIT = 14,
++ USER_CLASS = 15,
++ VENDOR_CLASS = 16,
++ VENDOR_OPTS = 17,
++ INTERFACE_ID = 18,
++ RECONF_MSG = 19,
++ RECONF_ACCEPT = 20,
++};
++
++enum DHCP6_STATUSES{
++ SUCCESS = 0,
++ UNSPEC_FAIL = 1,
++ NOADDR_AVAIL=2,
++ NO_BINDING = 3,
++ NOT_ON_LINK = 4,
++ USE_MULTICAST =5
++};
++static struct option longopts[] = {
++ {"ip", required_argument, 0, 'a'},
++ {"server-id", required_argument, 0, 's'},
++ {"client-id", required_argument, 0, 'c'},
++ {"iface", required_argument, 0, 'n'},
++ {"iaid", required_argument, 0, 'i'},
++ {"dry-run", no_argument, 0, 'd'},
++ {"help", no_argument, 0, 'h'},
++ {0, 0, 0, 0}
++};
++
++const short DHCP6_CLIENT_PORT = 546;
++const short DHCP6_SERVER_PORT = 547;
++
++const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
++
++struct dhcp6_option{
++ uint16_t type;
++ uint16_t len;
++ char value[1024];
++};
++
++struct dhcp6_iaaddr_option{
++ uint16_t type;
++ uint16_t len;
++ struct in6_addr ip;
++ uint32_t preferred_lifetime;
++ uint32_t valid_lifetime;
++
++
++};
++
++struct dhcp6_iana_option{
++ uint16_t type;
++ uint16_t len;
++ uint32_t iaid;
++ uint32_t t1;
++ uint32_t t2;
++ char options[1024];
++};
++
++
++struct dhcp6_packet{
++ size_t len;
++ char buf[2048];
++
++} ;
++
++size_t pack_duid(const char* str, char* dst){
++
++ char* tmp = strdup(str);
++ char* tmp_to_free = tmp;
++ char *ptr;
++ uint8_t write_pos = 0;
++ while ((ptr = strtok (tmp, ":"))) {
++ dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
++ write_pos += 1;
++ tmp = NULL;
++
++ }
++ free(tmp_to_free);
++ return write_pos;
++}
++
++struct dhcp6_option create_client_id_option(const char* duid){
++ struct dhcp6_option option;
++ option.type = htons(CLIENTID);
++ bzero(option.value, sizeof(option.value));
++ option.len = htons(pack_duid(duid, option.value));
++ return option;
++}
++
++struct dhcp6_option create_server_id_option(const char* duid){
++ struct dhcp6_option option;
++ option.type = htons(SERVERID);
++ bzero(option.value, sizeof(option.value));
++ option.len = htons(pack_duid(duid, option.value));
++ return option;
++}
++
++struct dhcp6_iaaddr_option create_iaadr_option(const char* ip){
++ struct dhcp6_iaaddr_option result;
++ result.type =htons(IAADDR);
++ /* no suboptions needed here, so length is 24 */
++ result.len = htons(24);
++ result.preferred_lifetime = 0;
++ result.valid_lifetime = 0;
++ int s = inet_pton(AF_INET6, ip, &(result.ip));
++ if (s <= 0) {
++ if (s == 0)
++ fprintf(stderr, "Not in presentation format");
++ else
++ perror("inet_pton");
++ exit(EXIT_FAILURE);
++ }
++ return result;
++}
++struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr){
++ struct dhcp6_iana_option result;
++ result.type = htons(IA_NA);
++ result.iaid = htonl(atoi(iaid));
++ result.t1 = 0;
++ result.t2 = 0;
++ result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
++ memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
++ return result;
++}
++
++struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id){
++ struct dhcp6_packet result;
++ bzero(result.buf, sizeof(result.buf));
++ /* message_type */
++ result.buf[0] = RELEASE;
++ /* tx_id */
++ bzero(result.buf+1, 3);
++
++ struct dhcp6_option client_option = create_client_id_option(client_id);
++ struct dhcp6_option server_option = create_server_id_option(server_id);
++ struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
++ struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
++ int offset = 4;
++ memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
++ offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
++ memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
++ offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
++ memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
++ offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
++ result.len = offset;
++ return result;
++}
++
++uint16_t parse_iana_suboption(char* buf, size_t len){
++ size_t current_pos = 0;
++ char option_value[1024];
++ while (current_pos < len) {
++ uint16_t option_type, option_len;
++ memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
++ memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
++ option_type = ntohs(option_type);
++ option_len = ntohs(option_len);
++ current_pos += 2 * sizeof(uint16_t);
++ if (option_type == STATUS_CODE){
++ uint16_t status;
++ memcpy(&status, buf + current_pos, sizeof(uint16_t));
++ status = ntohs(status);
++ if (status != SUCCESS){
++ memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
++ option_value[option_len-sizeof(uint16_t)] ='\0';
++ fprintf(stderr, "Error: %s\n", option_value);
++ }
++ return status;
++ }
++ }
++ return -2;
++}
++
++int16_t parse_packet(char* buf, size_t len){
++ uint8_t type = buf[0];
++ /*skipping tx id. you need it, uncomment following line
++ uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
++ */
++ size_t current_pos = 4;
++ if (type != REPLY ){
++ return NOT_REPLY_CODE;
++ }
++ char option_value[1024];
++ while (current_pos < len) {
++ uint16_t option_type, option_len;
++ memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
++ memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
++ option_type = ntohs(option_type);
++ option_len = ntohs(option_len);
++ current_pos += 2 * sizeof(uint16_t);
++ if (option_type == STATUS_CODE){
++ uint16_t status;
++ memcpy(&status, buf + current_pos, sizeof(uint16_t));
++ status = ntohs(status);
++ if (status != SUCCESS){
++ memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
++ fprintf(stderr, "Error: %d %s\n", status, option_value);
++ return status;
++ }
++
++ }
++ if (option_type == IA_NA ){
++ uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
++ if (result){
++ return result;
++ }
++ }
++ current_pos += option_len;
++
++ }
++ return -1;
++}
++
++void usage(const char* arg, FILE* stream){
++ const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help";
++ fprintf (stream, "Usage: %s %s\n", arg, usage_string);
++
++}
++
++int send_release_packet(const char* iface, struct dhcp6_packet* packet){
++
++ struct sockaddr_in6 server_addr, client_addr;
++ char response[1400];
++ int sock = socket(PF_INET6, SOCK_DGRAM, 0);
++ int i = 0;
++ if (sock < 0) {
++ perror("creating socket");
++ return -1;
++ }
++ if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1) {
++ perror("SO_BINDTODEVICE");
++ close(sock);
++ return -1;
++ }
++ memset(&server_addr, 0, sizeof(server_addr));
++ server_addr.sin6_family = AF_INET6;
++ client_addr.sin6_family = AF_INET6;
++ client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
++ client_addr.sin6_flowinfo = 0;
++ client_addr.sin6_scope_id =0;
++ inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
++ bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
++ inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
++ server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
++ int16_t recv_size = 0;
++ for (i = 0; i < 5; i++) {
++ if (sendto(sock, packet->buf, packet->len, 0,
++ (struct sockaddr *)&server_addr,
++ sizeof(server_addr)) < 0) {
++ perror("sendto failed");
++ exit(4);
++ }
++ recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
++ if (recv_size == -1){
++ if (errno == EAGAIN){
++ sleep(1);
++ continue;
++ }else {
++ perror("recvfrom");
++ }
++ }
++ int16_t result = parse_packet(response, recv_size);
++ if (result == NOT_REPLY_CODE){
++ sleep(1);
++ continue;
++ }
++ return result;
++ }
++ fprintf(stderr, "Response timed out\n");
++ return -1;
++
++}
++
++
++int main(int argc, char * const argv[]) {
++ const char* iface = "";
++ const char* ip = "";
++ const char* client_id = "";
++ const char* server_id = "";
++ const char* iaid = "";
++ int dry_run = 0;
++ while (1) {
++ int option_index = 0;
++ int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
++ if (c == -1){
++ break;
++ }
++ switch(c){
++ case 0:
++ if (longopts[option_index].flag !=0){
++ break;
++ }
++ printf ("option %s", longopts[option_index].name);
++ if (optarg)
++ printf (" with arg %s", optarg);
++ printf ("\n");
++ break;
++ case 'i':
++ iaid = optarg;
++ break;
++ case 'n':
++ iface = optarg;
++ break;
++ case 'a':
++ ip = optarg;
++ break;
++ case 'c':
++ client_id = optarg;
++ break;
++ case 'd':
++ dry_run = 1;
++ break;
++ case 's':
++ server_id = optarg;
++ break;
++ case 'h':
++ usage(argv[0], stdout);
++ break;
++ case '?':
++ usage(argv[0], stderr);
++ return -1;
++ default:
++ abort();
++
++ }
++
++ }
++ struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
++ if (dry_run){
++ uint16_t i;
++ for(i=0;i<packet.len;i++){
++ printf("%hhx", packet.buf[i]);
++ }
++ printf("\n");
++ return 0;
++ }
++ return send_release_packet(iface, &packet);
++
++}
+diff --git a/debian/rules b/debian/rules
+index 193b30c..d748829 100755
+--- a/debian/rules
++++ b/debian/rules
+@@ -188,6 +188,9 @@ ifeq ($(DEB_HOST_ARCH_OS),linux)
+ install -m 755 contrib/lease-tools/dhcp_release debian/utils/usr/bin/dhcp_release
+ install -m 644 contrib/lease-tools/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
+ gzip -9n debian/utils/usr/share/man/man1/dhcp_release.1
++ install -m 755 contrib/lease-tools/dhcp_release6 debian/utils/usr/bin/dhcp_release6
++ install -m 644 contrib/lease-tools/dhcp_release6.1 debian/utils/usr/share/man/man1/dhcp_release6.1
++ gzip -9n debian/utils/usr/share/man/man1/dhcp_release6.1
+ install -m 755 contrib/lease-tools/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
+ install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
+ install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
+--
+2.5.5
+
diff --git a/src/patches/dnsmasq/005-Limit_number_of_upstream_nameservers_when_logging_configuration.patch b/src/patches/dnsmasq/005-Limit_number_of_upstream_nameservers_when_logging_configuration.patch
new file mode 100644
index 0000000..3486104
--- /dev/null
+++ b/src/patches/dnsmasq/005-Limit_number_of_upstream_nameservers_when_logging_configuration.patch
@@ -0,0 +1,85 @@
+From b97026035ecc870ea0f12f537b214237cf3d0af6 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)thekelleys.org.uk>
+Date: Tue, 3 May 2016 22:34:06 +0100
+Subject: [PATCH] Limit number of upstream nameservers when logging
+ configuration.
+
+---
+ CHANGELOG | 5 +++++
+ src/config.h | 1 +
+ src/network.c | 10 ++++++++--
+ 3 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 7d4a061..f3220d8 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -71,6 +71,11 @@ version 2.76
+ Add dhcp_release6 to contrib/lease-tools. Many thanks
+ to Sergey Nechaev for this code.
+
++ To avoid filling logs in configurations which define
++ many upstream nameservers, don't log more that 30 servers.
++ The number to be logged can be changed as SERVERS_LOGGED
++ in src/config.h.
++
+
+ version 2.75
+ Fix reversion on 2.74 which caused 100% CPU use when a
+diff --git a/src/config.h b/src/config.h
+index c3bbbcb..80a50e1 100644
+--- a/src/config.h
++++ b/src/config.h
+@@ -25,6 +25,7 @@
+ #define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
+ #define FORWARD_TEST 50 /* try all servers every 50 queries */
+ #define FORWARD_TIME 20 /* or 20 seconds */
++#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
+ #define RANDOM_SOCKS 64 /* max simultaneous random ports */
+ #define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
+ #define CACHESIZ 150 /* default cache size */
+diff --git a/src/network.c b/src/network.c
+index da8a7f4..e7722fd 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -1429,7 +1429,7 @@ void check_servers(void)
+ {
+ struct irec *iface;
+ struct server *serv;
+- int port = 0;
++ int port = 0, count;
+
+ /* interface may be new since startup */
+ if (!option_bool(OPT_NOWILD))
+@@ -1442,7 +1442,7 @@ void check_servers(void)
+ serv->flags |= SERV_DO_DNSSEC;
+ #endif
+
+- for (serv = daemon->servers; serv; serv = serv->next)
++ for (count = 0, serv = daemon->servers; serv; serv = serv->next)
+ {
+ if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
+ {
+@@ -1509,6 +1509,9 @@ void check_servers(void)
+
+ if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
+ {
++ if (++count > SERVERS_LOGGED)
++ continue;
++
+ if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
+ {
+ char *s1, *s2, *s3 = "";
+@@ -1540,6 +1543,9 @@ void check_servers(void)
+ my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
+ }
+ }
++
++ if (count - 1 > SERVERS_LOGGED)
++ my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
+
+ cleanup_servers();
+ }
+--
+2.5.5
+
diff --git a/src/patches/dnsmasq/006-Fix_for_DHCP_in_transmission_interface_when_--bridge-interface_in_use.patch b/src/patches/dnsmasq/006-Fix_for_DHCP_in_transmission_interface_when_--bridge-interface_in_use.patch
new file mode 100644
index 0000000..3c90ca3
--- /dev/null
+++ b/src/patches/dnsmasq/006-Fix_for_DHCP_in_transmission_interface_when_--bridge-interface_in_use.patch
@@ -0,0 +1,70 @@
+From ff325644c7afae2588583f935f4ea9b9694eb52e Mon Sep 17 00:00:00 2001
+From: Neil Jerram <Neil.Jerram(a)metaswitch.com>
+Date: Tue, 3 May 2016 22:45:14 +0100
+Subject: [PATCH] Fix for DHCP in transmission interface when
+ --bridge-interface in use.
+
+From f3d832b41f44c856003517c583fbd7af4dca722c Mon Sep 17 00:00:00 2001
+From: Neil Jerram <Neil.Jerram(a)metaswitch.com>
+Date: Fri, 8 Apr 2016 19:23:47 +0100
+Subject: [PATCH] Fix DHCPv4 reply via --bridge-interface alias interface
+
+Sending a DHCPv4 reply through a --bridge-interface alias interface
+was inadvertently broken by
+
+ commit 65c721200023ef0023114459a8d12f8b0a24cfd8
+ Author: Lung-Pin Chang <changlp(a)cs.nctu.edu.tw>
+ Date: Thu Mar 19 23:22:21 2015 +0000
+
+ dhcp: set outbound interface via cmsg in unicast reply
+
+ If multiple routes to the same network exist, Linux blindly picks
+ the first interface (route) based on destination address, which might not be
+ the one we're actually offering leases. Rather than relying on this,
+ always set the interface for outgoing unicast DHCP packets.
+
+because in the aliasing case, iface_index is changed from the index of
+the interface on which the packet was received, to be the interface
+index of the 'bridge' interface (where the DHCP context is expected to
+be defined, and so needs to be looked up).
+
+For the cmsg code that the cited commit added, we need the original
+iface_index; so this commit saves that off before the aliasing code
+can change it, as rcvd_iface_index, and then uses rcvd_iface_index
+instead of iface_index for the cmsg code.
+---
+ src/dhcp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/dhcp.c b/src/dhcp.c
+index 00145bc..10f1fb9 100644
+--- a/src/dhcp.c
++++ b/src/dhcp.c
+@@ -146,6 +146,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+ struct iovec iov;
+ ssize_t sz;
+ int iface_index = 0, unicast_dest = 0, is_inform = 0;
++ int rcvd_iface_index;
+ struct in_addr iface_addr;
+ struct iface_param parm;
+ #ifdef HAVE_LINUX_NETWORK
+@@ -230,6 +231,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+ --bridge-interface option), change ifr.ifr_name so that we look
+ for DHCP contexts associated with the aliased interface instead
+ of with the aliasing one. */
++ rcvd_iface_index = iface_index;
+ for (bridge = daemon->bridges; bridge; bridge = bridge->next)
+ {
+ for (alias = bridge->alias; alias; alias = alias->next)
+@@ -387,7 +389,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+ msg.msg_controllen = sizeof(control_u);
+ cmptr = CMSG_FIRSTHDR(&msg);
+ pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
+- pkt->ipi_ifindex = iface_index;
++ pkt->ipi_ifindex = rcvd_iface_index;
+ pkt->ipi_spec_dst.s_addr = 0;
+ msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ cmptr->cmsg_level = IPPROTO_IP;
+--
+2.5.5
+
--
2.8.2