--- /dev/null
+From 6d95099c56a926d672e0407d6017fef9714f40c4 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Thu, 11 Aug 2016 23:38:54 +0100
+Subject: [PATCH] Handle v4-mapped IPv6 addresses sanely for --synth-domain.
+
+---
+ CHANGELOG | 7 ++++++-
+ man/dnsmasq.8 | 2 ++
+ src/domain.c | 34 ++++++++++++++++++++++++----------
+ 3 files changed, 32 insertions(+), 11 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 4f89799..2731cc4 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -24,7 +24,12 @@ version 2.77
+ Bump zone serial on reloading /etc/hosts and friends
+ when providing authoritative DNS. Thanks to Harrald
+ Dunkel for spotting this.
+-
++
++ Handle v4-mapped IPv6 addresses sanely in --synth-domain.
++ These have standard representation like ::ffff:1.2.3.4
++ and are now converted to names like
++ <prefix>--ffff-1-2-3-4.<domain>
++
+
+ version 2.76
+ Include 0.0.0.0/8 in DNS rebind checks. This range
+diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
+index 8910947..91fe672 100644
+--- a/man/dnsmasq.8
++++ b/man/dnsmasq.8
+@@ -619,6 +619,8 @@ but IPv6 addresses may start with '::'
+ but DNS labels may not start with '-' so in this case if no prefix is
+ configured a zero is added in front of the label. ::1 becomes 0--1.
+
++V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
++
+ The address range can be of the form
+ <ip address>,<ip address> or <ip address>/<netmask>
+ .TP
+diff --git a/src/domain.c b/src/domain.c
+index 1dd5027..a007acd 100644
+--- a/src/domain.c
++++ b/src/domain.c
+@@ -77,18 +77,31 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
+
+ *p = 0;
+
+- /* swap . or : for - */
+- for (p = tail; *p; p++)
+- if (*p == '-')
+- {
+- if (prot == AF_INET)
++ #ifdef HAVE_IPV6
++ if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
++ {
++ /* special hack for v4-mapped. */
++ memcpy(tail, "::ffff:", 7);
++ for (p = tail + 7; *p; p++)
++ if (*p == '-')
+ *p = '.';
++ }
++ else
++#endif
++ {
++ /* swap . or : for - */
++ for (p = tail; *p; p++)
++ if (*p == '-')
++ {
++ if (prot == AF_INET)
++ *p = '.';
+ #ifdef HAVE_IPV6
+- else
+- *p = ':';
++ else
++ *p = ':';
+ #endif
+- }
+-
++ }
++ }
++
+ if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
+ {
+ if (prot == AF_INET)
+@@ -169,8 +182,9 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
+ inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
+ }
+
++ /* V4-mapped have periods.... */
+ for (p = name; *p; p++)
+- if (*p == ':')
++ if (*p == ':' || *p == '.')
+ *p = '-';
+
+ strncat(name, ".", MAXDNAME);
+--
+1.7.10.4
+
--- /dev/null
+From 396750cef533cf72c7e6a72e47a9c93e2e431cb7 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Sat, 13 Aug 2016 22:34:11 +0100
+Subject: [PATCH] Refactor openBSD pftables code to remove blatant copyright
+ violation.
+
+---
+ src/tables.c | 90 +++++++++++++++++++++-------------------------------------
+ 1 file changed, 32 insertions(+), 58 deletions(-)
+
+diff --git a/src/tables.c b/src/tables.c
+index aae1252..4fa3487 100644
+--- a/src/tables.c
++++ b/src/tables.c
+@@ -53,52 +53,6 @@ static char *pfr_strerror(int errnum)
+ }
+ }
+
+-static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
+-{
+- struct pfioc_table io;
+-
+- if (size < 0 || (size && tbl == NULL))
+- {
+- errno = EINVAL;
+- return (-1);
+- }
+- bzero(&io, sizeof io);
+- io.pfrio_flags = flags;
+- io.pfrio_buffer = tbl;
+- io.pfrio_esize = sizeof(*tbl);
+- io.pfrio_size = size;
+- if (ioctl(dev, DIOCRADDTABLES, &io))
+- return (-1);
+- if (nadd != NULL)
+- *nadd = io.pfrio_nadd;
+- return (0);
+-}
+-
+-static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
+- if ( !addr || !ipaddr)
+- {
+- my_syslog(LOG_ERR, _("error: fill_addr missused"));
+- return -1;
+- }
+- bzero(addr, sizeof(*addr));
+-#ifdef HAVE_IPV6
+- if (flags & F_IPV6)
+- {
+- addr->pfra_af = AF_INET6;
+- addr->pfra_net = 0x80;
+- memcpy(&(addr->pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
+- }
+- else
+-#endif
+- {
+- addr->pfra_af = AF_INET;
+- addr->pfra_net = 0x20;
+- addr->pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
+- }
+- return 1;
+-}
+-
+-/*****************************************************************************/
+
+ void ipset_init(void)
+ {
+@@ -111,14 +65,13 @@ void ipset_init(void)
+ }
+
+ int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
+- int flags, int remove)
++ int flags, int remove)
+ {
+ struct pfr_addr addr;
+ struct pfioc_table io;
+ struct pfr_table table;
+- int n = 0, rc = 0;
+
+- if ( dev == -1 )
++ if (dev == -1)
+ {
+ my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
+ return -1;
+@@ -126,31 +79,52 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
+
+ bzero(&table, sizeof(struct pfr_table));
+ table.pfrt_flags |= PFR_TFLAG_PERSIST;
+- if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
++ if (strlen(setname) >= PF_TABLE_NAME_SIZE)
+ {
+ my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+- if ( strlcpy(table.pfrt_name, setname,
+- sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
++ if (strlcpy(table.pfrt_name, setname,
++ sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
+ {
+ my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
+ return -1;
+ }
+
+- if ((rc = pfr_add_tables(&table, 1, &n, 0)))
++ bzero(&io, sizeof io);
++ io.pfrio_flags = 0;
++ io.pfrio_buffer = &table;
++ io.pfrio_esize = sizeof(table);
++ io.pfrio_size = 1;
++ if (ioctl(dev, DIOCRADDTABLES, &io))
+ {
+- my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"),
+- pfr_strerror(errno),rc);
++ my_syslog(LOG_WARNING, _("IPset: error:%s"), pfr_strerror(errno));
++
+ return -1;
+ }
++
+ table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
+- if (n)
++ if (io.pfrio_nadd)
+ my_syslog(LOG_INFO, _("info: table created"));
+-
+- fill_addr(ipaddr,flags,&addr);
++
++ bzero(&addr, sizeof(addr));
++#ifdef HAVE_IPV6
++ if (flags & F_IPV6)
++ {
++ addr.pfra_af = AF_INET6;
++ addr.pfra_net = 0x80;
++ memcpy(&(addr.pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
++ }
++ else
++#endif
++ {
++ addr.pfra_af = AF_INET;
++ addr.pfra_net = 0x20;
++ addr.pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
++ }
++
+ bzero(&io, sizeof(io));
+ io.pfrio_flags = 0;
+ io.pfrio_table = table;
+--
+1.7.10.4
+