diff --git a/package/ctcgfw/luci-theme-argonv3/Makefile b/package/ctcgfw/luci-theme-argonv3/Makefile index ff5c927b87..5a5ce47e51 100644 --- a/package/ctcgfw/luci-theme-argonv3/Makefile +++ b/package/ctcgfw/luci-theme-argonv3/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Argon Theme LUCI_DEPENDS:= -PKG_VERSION:=1.5.1 -PKG_RELEASE:=01-20200331 +PKG_VERSION:=1.5.2 +PKG_RELEASE:=01-2020401 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/package/ctcgfw/luci-theme-argonv3/htdocs/luci-static/argon/css/style.css b/package/ctcgfw/luci-theme-argonv3/htdocs/luci-static/argon/css/style.css index 0834175cbb..db3f89c17f 100644 --- a/package/ctcgfw/luci-theme-argonv3/htdocs/luci-static/argon/css/style.css +++ b/package/ctcgfw/luci-theme-argonv3/htdocs/luci-static/argon/css/style.css @@ -1133,6 +1133,7 @@ input[name="nslookup"] { #xhr_poll_status { + cursor: pointer; display: inline-block; } @@ -1577,7 +1578,7 @@ footer>a { } } -[id^="cbi-apply-"] { +fieldset[id^="cbi-apply-"] { position: fixed; z-index: 200; width: 20rem; @@ -1586,8 +1587,9 @@ footer>a { height: 10rem; left: 50%; top: 50%; + padding: 1rem; + box-sizing: border-box; font-size: 1.2rem; - border-color: #5e72e4; text-align: center; } @@ -2287,6 +2289,10 @@ form.inline+form.inline, border-color: #5e72e4 !important; } +.node-services-vssr .ssr-button{ + margin-left: 0.3rem; + +} .cbi-section-remove>.cbi-button, .cbi-button-remove { @@ -3480,6 +3486,10 @@ header>.container>.pull-right>* { font-size: 0.875rem; } +/* fix nlbw/display*/ +#detail-bubble.in{ + z-index: 500; +} @media screen and (max-width: 1600px) { @@ -4145,6 +4155,7 @@ header>.container>.pull-right>* { .node-services-vssr .block{ background-color: #3c3c3c !important; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); } .node-services-vssr .block h4 { @@ -4160,6 +4171,12 @@ header>.container>.pull-right>* { .node-services-vssr .cbi-section-table-row{ color: #ccc; background-color: #3c3c3c !important; + box-shadow: 0 0 5px 0 rgba(0, 0, 0, .35) + } + + .node-services-vssr .cbi-section-table-row.fast { + background: darkslateblue !important; + color: #fff; } .node-services-vssr .ssr-button{ @@ -4200,6 +4217,12 @@ header>.container>.pull-right>* { border-bottom: 0.18751rem solid darkslateblue; color: darkslateblue; } + + fieldset[id^="cbi-apply-"] { + background-color: #333333; + } + + } @media (prefers-color-scheme: dark) and (max-width: 480px){ diff --git a/package/ctcgfw/luci-theme-argonv3/htdocs/luci-static/argon/favicon.ico b/package/ctcgfw/luci-theme-argonv3/htdocs/luci-static/argon/favicon.ico index b407d18455..e69a88eb1d 100644 Binary files a/package/ctcgfw/luci-theme-argonv3/htdocs/luci-static/argon/favicon.ico and b/package/ctcgfw/luci-theme-argonv3/htdocs/luci-static/argon/favicon.ico differ diff --git a/package/ctcgfw/luci-theme-argonv3/luasrc/view/themes/argon/header.htm b/package/ctcgfw/luci-theme-argonv3/luasrc/view/themes/argon/header.htm index d123851958..e200f7b638 100644 --- a/package/ctcgfw/luci-theme-argonv3/luasrc/view/themes/argon/header.htm +++ b/package/ctcgfw/luci-theme-argonv3/luasrc/view/themes/argon/header.htm @@ -278,9 +278,9 @@
- <% if striptags( node.title ) == nil then %> +
- <% end -%> +
diff --git a/package/libs/nghttp2/Makefile b/package/libs/nghttp2/Makefile index 99555a57db..2cef96dd76 100644 --- a/package/libs/nghttp2/Makefile +++ b/package/libs/nghttp2/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nghttp2 -PKG_VERSION:=1.40.0 +PKG_VERSION:=1.41.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://github.com/nghttp2/nghttp2/releases/download/v$(PKG_VERSION) -PKG_HASH:=09fc43d428ff237138733c737b29fb1a7e49d49de06d2edbed3bc4cdcee69073 +PKG_HASH:=abc25b8dc601f5b3fefe084ce50fcbdc63e3385621bee0cbfa7b57f9ec3e67c2 PKG_LICENSE:=MIT PKG_LICENSE_FILES:=COPYING diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index c1a36d4240..debfbc20c7 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq -PKG_VERSION:=2.80 -PKG_RELEASE:=12 +PKG_VERSION:=2.81 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq -PKG_HASH:=cdaba2785e92665cf090646cba6f94812760b9d7d8c8d0cfb07ac819377a63bb +PKG_HASH:=749ca903537c5197c26444ac24b0dce242cf42595fdfe6b9a5b9e4c7ad32f8fb PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING diff --git a/package/network/services/dnsmasq/patches/0001-Impove-cache-behaviour-for-TCP-connections.patch b/package/network/services/dnsmasq/patches/0001-Impove-cache-behaviour-for-TCP-connections.patch deleted file mode 100644 index 453c2924b2..0000000000 --- a/package/network/services/dnsmasq/patches/0001-Impove-cache-behaviour-for-TCP-connections.patch +++ /dev/null @@ -1,495 +0,0 @@ -From a799ca0c6314ad73a97bc6c89382d2712a9c0b0e Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Thu, 18 Oct 2018 19:35:29 +0100 -Subject: [PATCH 01/11] Impove cache behaviour for TCP connections. - -For ease of implementaion, dnsmasq has always forked a new process to -handle each incoming TCP connection. A side-effect of this is that any -DNS queries answered from TCP connections are not cached: when TCP -connections were rare, this was not a problem. With the coming of -DNSSEC, it's now the case that some DNSSEC queries have answers which -spill to TCP, and if, for instance, this applies to the keys for the -root then those never get cached, and performance is very bad. This -fix passes cache entries back from the TCP child process to the main -server process, and fixes the problem. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - CHANGELOG | 14 ++++ - src/blockdata.c | 37 ++++++++- - src/cache.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++-- - src/dnsmasq.c | 58 ++++++++++++-- - src/dnsmasq.h | 5 ++ - 5 files changed, 291 insertions(+), 19 deletions(-) - ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -1,3 +1,17 @@ -+version 2.81 -+ Impove cache behaviour for TCP connections. For ease of -+ implementaion, dnsmasq has always forked a new process to handle -+ each incoming TCP connection. A side-effect of this is that -+ any DNS queries answered from TCP connections are not cached: -+ when TCP connections were rare, this was not a problem. -+ With the coming of DNSSEC, it's now the case that some -+ DNSSEC queries have answers which spill to TCP, and if, -+ for instance, this applies to the keys for the root then -+ those never get cached, and performance is very bad. -+ This fix passes cache entries back from the TCP child process to -+ the main server process, and fixes the problem. -+ -+ - version 2.80 - Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method - for the initial patch and motivation. ---- a/src/blockdata.c -+++ b/src/blockdata.c -@@ -61,7 +61,7 @@ void blockdata_report(void) - blockdata_alloced * sizeof(struct blockdata)); - } - --struct blockdata *blockdata_alloc(char *data, size_t len) -+static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len) - { - struct blockdata *block, *ret = NULL; - struct blockdata **prev = &ret; -@@ -89,8 +89,17 @@ struct blockdata *blockdata_alloc(char * - blockdata_hwm = blockdata_count; - - blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len; -- memcpy(block->key, data, blen); -- data += blen; -+ if (data) -+ { -+ memcpy(block->key, data, blen); -+ data += blen; -+ } -+ else if (!read_write(fd, block->key, blen, 1)) -+ { -+ /* failed read free partial chain */ -+ blockdata_free(ret); -+ return NULL; -+ } - len -= blen; - *prev = block; - prev = &block->next; -@@ -100,6 +109,10 @@ struct blockdata *blockdata_alloc(char * - return ret; - } - -+struct blockdata *blockdata_alloc(char *data, size_t len) -+{ -+ return blockdata_alloc_real(0, data, len); -+} - - void blockdata_free(struct blockdata *blocks) - { -@@ -148,5 +161,21 @@ void *blockdata_retrieve(struct blockdat - - return data; - } -- -+ -+ -+void blockdata_write(struct blockdata *block, size_t len, int fd) -+{ -+ for (; len > 0 && block; block = block->next) -+ { -+ size_t blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len; -+ read_write(fd, block->key, blen, 0); -+ len -= blen; -+ } -+} -+ -+struct blockdata *blockdata_read(int fd, size_t len) -+{ -+ return blockdata_alloc_real(fd, NULL, len); -+} -+ - #endif ---- a/src/cache.c -+++ b/src/cache.c -@@ -26,6 +26,8 @@ static union bigname *big_free = NULL; - static int bignames_left, hash_size; - - static void make_non_terminals(struct crec *source); -+static struct crec *really_insert(char *name, struct all_addr *addr, -+ time_t now, unsigned long ttl, unsigned short flags); - - /* type->string mapping: this is also used by the name-hash function as a mixing table. */ - static const struct { -@@ -464,16 +466,10 @@ void cache_start_insert(void) - new_chain = NULL; - insert_error = 0; - } -- -+ - struct crec *cache_insert(char *name, struct all_addr *addr, - time_t now, unsigned long ttl, unsigned short flags) - { -- struct crec *new, *target_crec = NULL; -- union bigname *big_name = NULL; -- int freed_all = flags & F_REVERSE; -- int free_avail = 0; -- unsigned int target_uid; -- - /* Don't log DNSSEC records here, done elsewhere */ - if (flags & (F_IPV4 | F_IPV6 | F_CNAME)) - { -@@ -484,7 +480,20 @@ struct crec *cache_insert(char *name, st - if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl) - ttl = daemon->min_cache_ttl; - } -+ -+ return really_insert(name, addr, now, ttl, flags); -+} - -+ -+static struct crec *really_insert(char *name, struct all_addr *addr, -+ time_t now, unsigned long ttl, unsigned short flags) -+{ -+ struct crec *new, *target_crec = NULL; -+ union bigname *big_name = NULL; -+ int freed_all = flags & F_REVERSE; -+ int free_avail = 0; -+ unsigned int target_uid; -+ - /* if previous insertion failed give up now. */ - if (insert_error) - return NULL; -@@ -645,12 +654,185 @@ void cache_end_insert(void) - cache_hash(new_chain); - cache_link(new_chain); - daemon->metrics[METRIC_DNS_CACHE_INSERTED]++; -+ -+ /* If we're a child process, send this cache entry up the pipe to the master. -+ The marshalling process is rather nasty. */ -+ if (daemon->pipe_to_parent != -1) -+ { -+ char *name = cache_get_name(new_chain); -+ ssize_t m = strlen(name); -+ unsigned short flags = new_chain->flags; -+#ifdef HAVE_DNSSEC -+ u16 class = new_chain->uid; -+#endif -+ -+ read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)name, m, 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0); -+ -+ if (flags & (F_IPV4 | F_IPV6)) -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0); -+#ifdef HAVE_DNSSEC -+ else if (flags & F_DNSKEY) -+ { -+ read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.algo, sizeof(new_chain->addr.key.algo), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keytag, sizeof(new_chain->addr.key.keytag), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.flags, sizeof(new_chain->addr.key.flags), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keylen, sizeof(new_chain->addr.key.keylen), 0); -+ blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent); -+ } -+ else if (flags & F_DS) -+ { -+ read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0); -+ /* A negative DS entry is possible and has no data, obviously. */ -+ if (!(flags & F_NEG)) -+ { -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.algo, sizeof(new_chain->addr.ds.algo), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keytag, sizeof(new_chain->addr.ds.keytag), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.digest, sizeof(new_chain->addr.ds.digest), 0); -+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keylen, sizeof(new_chain->addr.ds.keylen), 0); -+ blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent); -+ } -+ } -+#endif -+ -+ } - } -+ - new_chain = tmp; - } -+ -+ /* signal end of cache insert in master process */ -+ if (daemon->pipe_to_parent != -1) -+ { -+ ssize_t m = -1; -+ read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0); -+ } -+ - new_chain = NULL; - } - -+ -+/* A marshalled cache entry arrives on fd, read, unmarshall and insert into cache of master process. */ -+int cache_recv_insert(time_t now, int fd) -+{ -+ ssize_t m; -+ struct all_addr addr; -+ unsigned long ttl; -+ time_t ttd; -+ unsigned short flags; -+ struct crec *crecp = NULL; -+ -+ cache_start_insert(); -+ -+ while(1) -+ { -+ -+ if (!read_write(fd, (unsigned char *)&m, sizeof(m), 1)) -+ return 0; -+ -+ if (m == -1) -+ { -+ cache_end_insert(); -+ return 1; -+ } -+ -+ if (!read_write(fd, (unsigned char *)daemon->namebuff, m, 1) || -+ !read_write(fd, (unsigned char *)&ttd, sizeof(ttd), 1) || -+ !read_write(fd, (unsigned char *)&flags, sizeof(flags), 1)) -+ return 0; -+ -+ daemon->namebuff[m] = 0; -+ -+ ttl = difftime(ttd, now); -+ -+ if (flags & (F_IPV4 | F_IPV6)) -+ { -+ if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1)) -+ return 0; -+ crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags); -+ } -+ else if (flags & F_CNAME) -+ { -+ struct crec *newc = really_insert(daemon->namebuff, NULL, now, ttl, flags); -+ /* This relies on the fact the the target of a CNAME immediately preceeds -+ it because of the order of extraction in extract_addresses, and -+ the order reversal on the new_chain. */ -+ if (newc) -+ { -+ if (!crecp) -+ { -+ newc->addr.cname.target.cache = NULL; -+ /* anything other than zero, to avoid being mistaken for CNAME to interface-name */ -+ newc->addr.cname.uid = 1; -+ } -+ else -+ { -+ next_uid(crecp); -+ newc->addr.cname.target.cache = crecp; -+ newc->addr.cname.uid = crecp->uid; -+ } -+ } -+ } -+#ifdef HAVE_DNSSEC -+ else if (flags & (F_DNSKEY | F_DS)) -+ { -+ unsigned short class, keylen, keyflags, keytag; -+ unsigned char algo, digest; -+ struct blockdata *keydata; -+ -+ if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1)) -+ return 0; -+ /* Cache needs to known class for DNSSEC stuff */ -+ addr.addr.dnssec.class = class; -+ -+ crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags); -+ -+ if (flags & F_DNSKEY) -+ { -+ if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) || -+ !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) || -+ !read_write(fd, (unsigned char *)&keyflags, sizeof(keyflags), 1) || -+ !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) || -+ !(keydata = blockdata_read(fd, keylen))) -+ return 0; -+ } -+ else if (!(flags & F_NEG)) -+ { -+ if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) || -+ !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) || -+ !read_write(fd, (unsigned char *)&digest, sizeof(digest), 1) || -+ !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) || -+ !(keydata = blockdata_read(fd, keylen))) -+ return 0; -+ } -+ -+ if (crecp) -+ { -+ if (flags & F_DNSKEY) -+ { -+ crecp->addr.key.algo = algo; -+ crecp->addr.key.keytag = keytag; -+ crecp->addr.key.flags = flags; -+ crecp->addr.key.keylen = keylen; -+ crecp->addr.key.keydata = keydata; -+ } -+ else if (!(flags & F_NEG)) -+ { -+ crecp->addr.ds.algo = algo; -+ crecp->addr.ds.keytag = keytag; -+ crecp->addr.ds.digest = digest; -+ crecp->addr.ds.keylen = keylen; -+ crecp->addr.ds.keydata = keydata; -+ } -+ } -+ } -+#endif -+ } -+} -+ - int cache_find_non_terminal(char *name, time_t now) - { - struct crec *crecp; ---- a/src/dnsmasq.c -+++ b/src/dnsmasq.c -@@ -930,6 +930,10 @@ int main (int argc, char **argv) - check_servers(); - - pid = getpid(); -+ -+ daemon->pipe_to_parent = -1; -+ for (i = 0; i < MAX_PROCS; i++) -+ daemon->tcp_pipes[i] = -1; - - #ifdef HAVE_INOTIFY - /* Using inotify, have to select a resolv file at startup */ -@@ -1611,7 +1615,7 @@ static int set_dns_listeners(time_t now) - we don't need to explicitly arrange to wake up here */ - if (listener->tcpfd != -1) - for (i = 0; i < MAX_PROCS; i++) -- if (daemon->tcp_pids[i] == 0) -+ if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) - { - poll_listen(listener->tcpfd, POLLIN); - break; -@@ -1624,6 +1628,13 @@ static int set_dns_listeners(time_t now) - - } - -+#ifndef NO_FORK -+ if (!option_bool(OPT_DEBUG)) -+ for (i = 0; i < MAX_PROCS; i++) -+ if (daemon->tcp_pipes[i] != -1) -+ poll_listen(daemon->tcp_pipes[i], POLLIN); -+#endif -+ - return wait; - } - -@@ -1632,7 +1643,10 @@ static void check_dns_listeners(time_t n - struct serverfd *serverfdp; - struct listener *listener; - int i; -- -+#ifndef NO_FORK -+ int pipefd[2]; -+#endif -+ - for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) - if (poll_check(serverfdp->fd, POLLIN)) - reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now); -@@ -1642,7 +1656,26 @@ static void check_dns_listeners(time_t n - if (daemon->randomsocks[i].refcount != 0 && - poll_check(daemon->randomsocks[i].fd, POLLIN)) - reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now); -- -+ -+#ifndef NO_FORK -+ /* Races. The child process can die before we read all of the data from the -+ pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the -+ process, and tcp_pipes to -1 and close the FD when we read the last -+ of the data - indicated by cache_recv_insert returning zero. -+ The order of these events is indeterminate, and both are needed -+ to free the process slot. Once the child process has gone, poll() -+ returns POLLHUP, not POLLIN, so have to check for both here. */ -+ if (!option_bool(OPT_DEBUG)) -+ for (i = 0; i < MAX_PROCS; i++) -+ if (daemon->tcp_pipes[i] != -1 && -+ poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) && -+ !cache_recv_insert(now, daemon->tcp_pipes[i])) -+ { -+ close(daemon->tcp_pipes[i]); -+ daemon->tcp_pipes[i] = -1; -+ } -+#endif -+ - for (listener = daemon->listeners; listener; listener = listener->next) - { - if (listener->fd != -1 && poll_check(listener->fd, POLLIN)) -@@ -1736,15 +1769,20 @@ static void check_dns_listeners(time_t n - while (retry_send(close(confd))); - } - #ifndef NO_FORK -- else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0) -+ else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0) - { -- if (p != -1) -+ close(pipefd[1]); /* parent needs read pipe end. */ -+ if (p == -1) -+ close(pipefd[0]); -+ else - { - int i; -+ - for (i = 0; i < MAX_PROCS; i++) -- if (daemon->tcp_pids[i] == 0) -+ if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) - { - daemon->tcp_pids[i] = p; -+ daemon->tcp_pipes[i] = pipefd[0]; - break; - } - } -@@ -1761,7 +1799,7 @@ static void check_dns_listeners(time_t n - int flags; - struct in_addr netmask; - int auth_dns; -- -+ - if (iface) - { - netmask = iface->netmask; -@@ -1777,7 +1815,11 @@ static void check_dns_listeners(time_t n - /* Arrange for SIGALRM after CHILD_LIFETIME seconds to - terminate the process. */ - if (!option_bool(OPT_DEBUG)) -- alarm(CHILD_LIFETIME); -+ { -+ alarm(CHILD_LIFETIME); -+ close(pipefd[0]); /* close read end in child. */ -+ daemon->pipe_to_parent = pipefd[1]; -+ } - #endif - - /* start with no upstream connections. */ ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -1091,6 +1091,8 @@ extern struct daemon { - size_t packet_len; /* " " */ - struct randfd *rfd_save; /* " " */ - pid_t tcp_pids[MAX_PROCS]; -+ int tcp_pipes[MAX_PROCS]; -+ int pipe_to_parent; - struct randfd randomsocks[RANDOM_SOCKS]; - int v6pktinfo; - struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */ -@@ -1152,6 +1154,7 @@ struct crec *cache_find_by_name(struct c - char *name, time_t now, unsigned int prot); - void cache_end_insert(void); - void cache_start_insert(void); -+int cache_recv_insert(time_t now, int fd); - struct crec *cache_insert(char *name, struct all_addr *addr, - time_t now, unsigned long ttl, unsigned short flags); - void cache_reload(void); -@@ -1174,6 +1177,8 @@ void blockdata_init(void); - void blockdata_report(void); - struct blockdata *blockdata_alloc(char *data, size_t len); - void *blockdata_retrieve(struct blockdata *block, size_t len, void *data); -+struct blockdata *blockdata_read(int fd, size_t len); -+void blockdata_write(struct blockdata *block, size_t len, int fd); - void blockdata_free(struct blockdata *blocks); - #endif - diff --git a/package/network/services/dnsmasq/patches/0002-Ensure-that-AD-bit-is-reset-on-answers-from-address-.patch b/package/network/services/dnsmasq/patches/0002-Ensure-that-AD-bit-is-reset-on-answers-from-address-.patch deleted file mode 100644 index e3178b8dfd..0000000000 --- a/package/network/services/dnsmasq/patches/0002-Ensure-that-AD-bit-is-reset-on-answers-from-address-.patch +++ /dev/null @@ -1,26 +0,0 @@ -From a220545c4277cba534be5ef4638b5076fc7d2cf4 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Mon, 22 Oct 2018 18:21:48 +0100 -Subject: [PATCH 02/11] Ensure that AD bit is reset on answers from - --address=//
. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/rfc1035.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -938,9 +938,9 @@ size_t setup_reply(struct dns_header *he - return 0; - - /* clear authoritative and truncated flags, set QR flag */ -- header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR; -- /* set RA flag */ -- header->hb4 |= HB4_RA; -+ header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC )) | HB3_QR; -+ /* clear AD flag, set RA flag */ -+ header->hb4 = (header->hb4 & ~HB4_AD) | HB4_RA; - - header->nscount = htons(0); - header->arcount = htons(0); diff --git a/package/network/services/dnsmasq/patches/0003-Remove-ability-to-compile-without-IPv6-support.patch b/package/network/services/dnsmasq/patches/0003-Remove-ability-to-compile-without-IPv6-support.patch deleted file mode 100644 index be3c4116b6..0000000000 --- a/package/network/services/dnsmasq/patches/0003-Remove-ability-to-compile-without-IPv6-support.patch +++ /dev/null @@ -1,2192 +0,0 @@ -From ee8750451b49d27b180517a4e35b636be0fae575 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Tue, 23 Oct 2018 22:10:17 +0100 -Subject: [PATCH 03/11] Remove ability to compile without IPv6 support. - -This was the source of a large number of #ifdefs, originally -included for use with old embedded libc versions. I'm -sure no-one wants or needs IPv6-free code these days, so this -is a move towards more maintainable code. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/arp.c | 13 ---------- - src/auth.c | 53 ++++++++++---------------------------- - src/bpf.c | 10 ++------ - src/cache.c | 31 ++++------------------ - src/config.h | 30 +++------------------- - src/conntrack.c | 2 -- - src/dbus.c | 4 --- - src/dnsmasq.c | 6 ++--- - src/dnsmasq.h | 20 ++------------- - src/domain.c | 28 +++----------------- - src/dump.c | 4 --- - src/edns0.c | 14 +--------- - src/forward.c | 68 ++++--------------------------------------------- - src/helper.c | 8 ------ - src/ipset.c | 9 +------ - src/netlink.c | 5 +--- - src/network.c | 54 +++------------------------------------ - src/option.c | 34 ------------------------- - src/rfc1035.c | 50 +++++++----------------------------- - src/tables.c | 3 +-- - src/tftp.c | 17 ++----------- - src/util.c | 13 +--------- - 22 files changed, 57 insertions(+), 419 deletions(-) - ---- a/src/arp.c -+++ b/src/arp.c -@@ -44,11 +44,6 @@ static int filter_mac(int family, char * - if (maclen > DHCP_CHADDR_MAX) - return 1; - --#ifndef HAVE_IPV6 -- if (family != AF_INET) -- return 1; --#endif -- - /* Look for existing entry */ - for (arp = arps; arp; arp = arp->next) - { -@@ -60,13 +55,11 @@ static int filter_mac(int family, char * - if (arp->addr.addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr) - continue; - } --#ifdef HAVE_IPV6 - else - { - if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, (struct in6_addr *)addrp)) - continue; - } --#endif - - if (arp->status == ARP_EMPTY) - { -@@ -103,10 +96,8 @@ static int filter_mac(int family, char * - memcpy(arp->hwaddr, mac, maclen); - if (family == AF_INET) - arp->addr.addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr; --#ifdef HAVE_IPV6 - else - memcpy(&arp->addr.addr.addr6, addrp, IN6ADDRSZ); --#endif - } - - return 1; -@@ -136,11 +127,9 @@ int find_mac(union mysockaddr *addr, uns - arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr) - continue; - --#ifdef HAVE_IPV6 - if (arp->family == AF_INET6 && - !IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr)) - continue; --#endif - - /* Only accept positive entries unless in lazy mode. */ - if (arp->status != ARP_EMPTY || lazy || updated) -@@ -203,10 +192,8 @@ int find_mac(union mysockaddr *addr, uns - - if (addr->sa.sa_family == AF_INET) - arp->addr.addr.addr4.s_addr = addr->in.sin_addr.s_addr; --#ifdef HAVE_IPV6 - else - memcpy(&arp->addr.addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ); --#endif - } - - return 0; ---- a/src/auth.c -+++ b/src/auth.c -@@ -33,10 +33,8 @@ static struct addrlist *find_addrlist(st - if (is_same_net(addr, list->addr.addr.addr4, netmask)) - return list; - } --#ifdef HAVE_IPV6 - else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen)) - return list; --#endif - - } while ((list = list->next)); - -@@ -189,7 +187,6 @@ size_t answer_auth(struct dns_header *he - while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) - intr = intr->next; - } --#ifdef HAVE_IPV6 - else if (flag == F_IPV6) - for (intr = daemon->int_names; intr; intr = intr->next) - { -@@ -205,7 +202,6 @@ size_t answer_auth(struct dns_header *he - while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) - intr = intr->next; - } --#endif - - if (intr) - { -@@ -378,10 +374,8 @@ size_t answer_auth(struct dns_header *he - if (qtype == T_A) - flag = F_IPV4; - --#ifdef HAVE_IPV6 - if (qtype == T_AAAA) - flag = F_IPV6; --#endif - - for (intr = daemon->int_names; intr; intr = intr->next) - if ((rc = hostname_issubdomain(name, intr->name))) -@@ -395,10 +389,9 @@ size_t answer_auth(struct dns_header *he - if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype && - (local_query || filter_zone(zone, flag, &addrlist->addr))) - { --#ifdef HAVE_IPV6 - if (addrlist->flags & ADDRLIST_REVONLY) - continue; --#endif -+ - found = 1; - log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL); - if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, -@@ -424,13 +417,11 @@ size_t answer_auth(struct dns_header *he - - if (peer_addr->sa.sa_family == AF_INET) - peer_addr->in.sin_port = 0; --#ifdef HAVE_IPV6 - else - { - peer_addr->in6.sin6_port = 0; - peer_addr->in6.sin6_scope_id = 0; - } --#endif - - for (peers = daemon->auth_peers; peers; peers = peers->next) - if (sockaddr_isequal(peer_addr, &peers->addr)) -@@ -442,10 +433,8 @@ size_t answer_auth(struct dns_header *he - { - if (peer_addr->sa.sa_family == AF_INET) - inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN); --#ifdef HAVE_IPV6 - else - inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN); --#endif - - my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff); - return 0; -@@ -603,7 +592,6 @@ size_t answer_auth(struct dns_header *he - p += sprintf(p, "%u.in-addr.arpa", a & 0xff); - - } --#ifdef HAVE_IPV6 - else - { - char *p = name; -@@ -617,7 +605,6 @@ size_t answer_auth(struct dns_header *he - p += sprintf(p, "ip6.arpa"); - - } --#endif - } - - /* handle NS and SOA in auth section or for explicit queries */ -@@ -754,14 +741,12 @@ size_t answer_auth(struct dns_header *he - daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr)) - anscount++; - --#ifdef HAVE_IPV6 - for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) - if ((addrlist->flags & ADDRLIST_IPV6) && - (local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) && - add_resource_record(header, limit, &trunc, -axfroffset, &ansp, - daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr)) - anscount++; --#endif - - /* restore config data */ - if (cut) -@@ -798,18 +783,11 @@ size_t answer_auth(struct dns_header *he - { - char *cache_name = cache_get_name(crecp); - if (!strchr(cache_name, '.') && -- (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))) -- { -- qtype = T_A; --#ifdef HAVE_IPV6 -- if (crecp->flags & F_IPV6) -- qtype = T_AAAA; --#endif -- if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, -- daemon->auth_ttl, NULL, qtype, C_IN, -- (crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr)) -- anscount++; -- } -+ (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))) && -+ add_resource_record(header, limit, &trunc, -axfroffset, &ansp, -+ daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN, -+ (crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr)) -+ anscount++; - } - - if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN)))) -@@ -818,18 +796,13 @@ size_t answer_auth(struct dns_header *he - if (in_zone(zone, name, &cut) && - (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))) - { -- qtype = T_A; --#ifdef HAVE_IPV6 -- if (crecp->flags & F_IPV6) -- qtype = T_AAAA; --#endif -- if (cut) -- *cut = 0; -- -- if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, -- daemon->auth_ttl, NULL, qtype, C_IN, -- (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr)) -- anscount++; -+ if (cut) -+ *cut = 0; -+ -+ if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, -+ daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN, -+ (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr)) -+ anscount++; - } - } - } ---- a/src/bpf.c -+++ b/src/bpf.c -@@ -31,9 +31,7 @@ - # include - #endif - #include --#ifdef HAVE_IPV6 --# include --#endif -+#include - - #ifndef SA_SIZE - #define SA_SIZE(sa) \ -@@ -121,7 +119,7 @@ int iface_enumerate(int family, void *pa - if (getifaddrs(&head) == -1) - return 0; - --#if defined(HAVE_BSD_NETWORK) && defined(HAVE_IPV6) -+#if defined(HAVE_BSD_NETWORK) - if (family == AF_INET6) - fd = socket(PF_INET6, SOCK_DGRAM, 0); - #endif -@@ -152,7 +150,6 @@ int iface_enumerate(int family, void *pa - if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm))) - goto err; - } --#ifdef HAVE_IPV6 - else if (family == AF_INET6) - { - struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr; -@@ -219,7 +216,6 @@ int iface_enumerate(int family, void *pa - (int) preferred, (int)valid, parm))) - goto err; - } --#endif /* HAVE_IPV6 */ - - #ifdef HAVE_DHCP6 - else if (family == AF_LINK) -@@ -427,10 +423,8 @@ void route_sock(void) - del_family = sa->sa_family; - if (del_family == AF_INET) - del_addr.addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr; --#ifdef HAVE_IPV6 - else if (del_family == AF_INET6) - del_addr.addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr; --#endif - else - del_family = 0; - } ---- a/src/cache.c -+++ b/src/cache.c -@@ -410,11 +410,8 @@ static struct crec *cache_scan_free(char - else - { - int i; --#ifdef HAVE_IPV6 - int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ; --#else -- int addrlen = INADDRSZ; --#endif -+ - for (i = 0; i < hash_size; i++) - for (crecp = hash_table[i], up = &hash_table[i]; - crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL)); -@@ -512,11 +509,9 @@ static struct crec *really_insert(char * - if ((flags & F_IPV4) && (new->flags & F_IPV4) && - new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr) - return new; --#ifdef HAVE_IPV6 - else if ((flags & F_IPV6) && (new->flags & F_IPV6) && - IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6)) - return new; --#endif - } - - insert_error = 1; -@@ -938,11 +933,7 @@ struct crec *cache_find_by_addr(struct c - time_t now, unsigned int prot) - { - struct crec *ans; --#ifdef HAVE_IPV6 - int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ; --#else -- int addrlen = INADDRSZ; --#endif - - if (crecp) /* iterating */ - ans = crecp->next; -@@ -1171,14 +1162,12 @@ int read_hostsfile(char *filename, unsig - addrlen = INADDRSZ; - domain_suffix = get_domain(addr.addr.addr4); - } --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, token, &addr) > 0) - { - flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6; - addrlen = IN6ADDRSZ; - domain_suffix = get_domain6(&addr.addr.addr6); - } --#endif - else - { - my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno); -@@ -1343,7 +1332,7 @@ void cache_reload(void) - cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG; - add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz); - } --#ifdef HAVE_IPV6 -+ - if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) && - (cache = whine_malloc(SIZEOF_POINTER_CREC))) - { -@@ -1352,7 +1341,6 @@ void cache_reload(void) - cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG; - add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz); - } --#endif - } - - if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts) -@@ -1451,13 +1439,11 @@ void cache_add_dhcp_entry(char *host_nam - int in_hosts = 0; - size_t addrlen = sizeof(struct in_addr); - --#ifdef HAVE_IPV6 - if (prot == AF_INET6) - { - flags = F_IPV6; - addrlen = sizeof(struct in6_addr); - } --#endif - - inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN); - -@@ -1810,10 +1796,8 @@ void dump_cache(time_t now) - a = daemon->addrbuff; - if (cache->flags & F_IPV4) - inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN); --#ifdef HAVE_IPV6 - else if (cache->flags & F_IPV6) - inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN); --#endif - } - - if (cache->flags & F_IPV4) -@@ -1954,14 +1938,9 @@ void log_query(unsigned int flags, char - sprintf(daemon->addrbuff, "%u", rcode); - } - else -- { --#ifdef HAVE_IPV6 -- inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, -- addr, daemon->addrbuff, ADDRSTRLEN); --#else -- strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN); --#endif -- } -+ inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, -+ addr, daemon->addrbuff, ADDRSTRLEN); -+ - } - else - dest = arg; ---- a/src/config.h -+++ b/src/config.h -@@ -131,7 +131,6 @@ HAVE_INOTIFY - - NO_ID - Don't report *.bind CHAOS info to clients, forward such requests upstream instead. --NO_IPV6 - NO_TFTP - NO_DHCP - NO_DHCP6 -@@ -141,8 +140,8 @@ NO_AUTH - NO_DUMPFILE - NO_INOTIFY - these are available to explicitly disable compile time options which would -- otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or -- which are enabled by default in the distributed source tree. Building dnsmasq -+ otherwise be enabled automatically or which are enabled by default -+ in the distributed source tree. Building dnsmasq - with something like "make COPTS=-DNO_SCRIPT" will do the trick. - NO_GMP - Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp. -@@ -308,29 +307,9 @@ HAVE_SOCKADDR_SA_LEN - - #endif - --/* Decide if we're going to support IPv6 */ --/* We assume that systems which don't have IPv6 -- headers don't have ntop and pton either */ -- --#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY) --# define HAVE_IPV6 --# define ADDRSTRLEN INET6_ADDRSTRLEN --#else --# if !defined(INET_ADDRSTRLEN) --# define INET_ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */ --# endif --# undef HAVE_IPV6 --# define ADDRSTRLEN INET_ADDRSTRLEN --#endif -- -- - /* rules to implement compile-time option dependencies and - the NO_XXX flags */ - --#ifdef NO_IPV6 --#undef HAVE_IPV6 --#endif -- - #ifdef NO_TFTP - #undef HAVE_TFTP - #endif -@@ -340,7 +319,7 @@ HAVE_SOCKADDR_SA_LEN - #undef HAVE_DHCP6 - #endif - --#if defined(NO_DHCP6) || !defined(HAVE_IPV6) -+#if defined(NO_DHCP6) - #undef HAVE_DHCP6 - #endif - -@@ -385,9 +364,6 @@ HAVE_SOCKADDR_SA_LEN - #ifdef DNSMASQ_COMPILE_OPTS - - static char *compile_opts = --#ifndef HAVE_IPV6 --"no-" --#endif - "IPv6 " - #ifndef HAVE_GETOPT_LONG - "no-" ---- a/src/conntrack.c -+++ b/src/conntrack.c -@@ -36,7 +36,6 @@ int get_incoming_mark(union mysockaddr * - nfct_set_attr_u8(ct, ATTR_L4PROTO, istcp ? IPPROTO_TCP : IPPROTO_UDP); - nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(daemon->port)); - --#ifdef HAVE_IPV6 - if (peer_addr->sa.sa_family == AF_INET6) - { - nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6); -@@ -45,7 +44,6 @@ int get_incoming_mark(union mysockaddr * - nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr.addr6.s6_addr); - } - else --#endif - { - nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); - nfct_set_attr_u32(ct, ATTR_IPV4_SRC, peer_addr->in.sin_addr.s_addr); ---- a/src/dbus.c -+++ b/src/dbus.c -@@ -185,9 +185,6 @@ static void dbus_read_servers(DBusMessag - } - } - --#ifndef HAVE_IPV6 -- my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support")); --#else - if (i == sizeof(struct in6_addr)) - { - memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr)); -@@ -202,7 +199,6 @@ static void dbus_read_servers(DBusMessag - source_addr.in6.sin6_port = htons(daemon->query_port); - skip = 0; - } --#endif - } - else - /* At the end */ ---- a/src/dnsmasq.c -+++ b/src/dnsmasq.c -@@ -1730,11 +1730,11 @@ static void check_dns_listeners(time_t n - indextoname(listener->tcpfd, if_index, intr_name)) - { - struct all_addr addr; -- addr.addr.addr4 = tcp_addr.in.sin_addr; --#ifdef HAVE_IPV6 -+ - if (tcp_addr.sa.sa_family == AF_INET6) - addr.addr.addr6 = tcp_addr.in6.sin6_addr; --#endif -+ else -+ addr.addr.addr4 = tcp_addr.in.sin_addr; - - for (iface = daemon->interfaces; iface; iface = iface->next) - if (iface->index == if_index) ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -126,9 +126,7 @@ typedef unsigned long long u64; - #include - #include - #include --#ifdef HAVE_IPV6 - #include --#endif - #include - #include - #include -@@ -159,6 +157,8 @@ extern int capget(cap_user_header_t head - /* daemon is function in the C library.... */ - #define daemon dnsmasq_daemon - -+#define ADDRSTRLEN INET6_ADDRSTRLEN -+ - /* Async event queue */ - struct event_desc { - int event, data, msg_sz; -@@ -273,9 +273,7 @@ struct event_desc { - struct all_addr { - union { - struct in_addr addr4; --#ifdef HAVE_IPV6 - struct in6_addr addr6; --#endif - /* for log_query */ - struct { - unsigned short keytag, algo, digest; -@@ -383,9 +381,7 @@ struct host_record { - struct name_list *next; - } *names; - struct in_addr addr; --#ifdef HAVE_IPV6 - struct in6_addr addr6; --#endif - struct host_record *next; - }; - -@@ -496,9 +492,7 @@ struct crec { - union mysockaddr { - struct sockaddr sa; - struct sockaddr_in in; --#if defined(HAVE_IPV6) - struct sockaddr_in6 in6; --#endif - }; - - /* bits in flag param to IPv6 callbacks from iface_enumerate() */ -@@ -660,9 +654,7 @@ struct frec { - struct all_addr dest; - struct server *sentto; /* NULL means free */ - struct randfd *rfd4; --#ifdef HAVE_IPV6 - struct randfd *rfd6; --#endif - unsigned int iface; - unsigned short orig_id, new_id; - int log_id, fd, forwardall, flags; -@@ -877,9 +869,7 @@ struct dhcp_bridge { - struct cond_domain { - char *domain, *prefix; - struct in_addr start, end; --#ifdef HAVE_IPV6 - struct in6_addr start6, end6; --#endif - int is6, indexed; - struct cond_domain *next; - }; -@@ -1184,9 +1174,7 @@ void blockdata_free(struct blockdata *bl - - /* domain.c */ - char *get_domain(struct in_addr addr); --#ifdef HAVE_IPV6 - char *get_domain6(struct in6_addr *addr); --#endif - int is_name_synthetic(int flags, char *name, struct all_addr *addr); - int is_rev_synth(int flag, struct all_addr *addr, char *name); - -@@ -1270,11 +1258,9 @@ int hostname_issubdomain(char *a, char * - time_t dnsmasq_time(void); - int netmask_length(struct in_addr mask); - int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask); --#ifdef HAVE_IPV6 - int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen); - u64 addr6part(struct in6_addr *addr); - void setaddr6part(struct in6_addr *addr, u64 host); --#endif - int retry_send(ssize_t rc); - void prettyprint_time(char *buf, unsigned int t); - int prettyprint_addr(union mysockaddr *addr, char *buf); -@@ -1353,9 +1339,7 @@ int loopback_exception(int fd, int famil - int label_exception(int index, int family, struct all_addr *addr); - int fix_fd(int fd); - int tcp_interface(int fd, int af); --#ifdef HAVE_IPV6 - int set_ipv6pktinfo(int fd); --#endif - #ifdef HAVE_DHCP6 - void join_multicast(int dienow); - #endif ---- a/src/domain.c -+++ b/src/domain.c -@@ -18,21 +18,14 @@ - - - static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c); --#ifdef HAVE_IPV6 - static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c); --#endif - - - int is_name_synthetic(int flags, char *name, struct all_addr *addr) - { - char *p; - struct cond_domain *c = NULL; -- int prot = AF_INET; -- --#ifdef HAVE_IPV6 -- if (flags & F_IPV6) -- prot = AF_INET6; --#endif -+ int prot = (flags & F_IPV6) ? AF_INET6 : AF_INET; - - for (c = daemon->synth_domains; c; c = c->next) - { -@@ -83,8 +76,7 @@ int is_name_synthetic(int flags, char *n - addr->addr.addr4.s_addr = htonl(ntohl(c->start.s_addr) + index); - found = 1; - } -- } --#ifdef HAVE_IPV6 -+ } - else - { - u64 index = atoll(tail); -@@ -98,7 +90,6 @@ int is_name_synthetic(int flags, char *n - found = 1; - } - } --#endif - } - } - else -@@ -111,10 +102,8 @@ int is_name_synthetic(int flags, char *n - if ((c >='0' && c <= '9') || c == '-') - continue; - --#ifdef HAVE_IPV6 - if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f'))) - continue; --#endif - - break; - } -@@ -124,7 +113,6 @@ int is_name_synthetic(int flags, char *n - - *p = 0; - --#ifdef HAVE_IPV6 - if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail) - { - /* special hack for v4-mapped. */ -@@ -134,7 +122,6 @@ int is_name_synthetic(int flags, char *n - *p = '.'; - } - else --#endif - { - /* swap . or : for - */ - for (p = tail; *p; p++) -@@ -142,10 +129,8 @@ int is_name_synthetic(int flags, char *n - { - if (prot == AF_INET) - *p = '.'; --#ifdef HAVE_IPV6 - else - *p = ':'; --#endif - } - } - -@@ -158,7 +143,6 @@ int is_name_synthetic(int flags, char *n - ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr)) - found = 1; - } --#ifdef HAVE_IPV6 - else - { - u64 addrpart = addr6part(&addr->addr.addr6); -@@ -169,7 +153,6 @@ int is_name_synthetic(int flags, char *n - addrpart <= addr6part(&c->end6)) - found = 1; - } --#endif - } - - } -@@ -221,8 +204,7 @@ int is_rev_synth(int flag, struct all_ad - return 1; - } - --#ifdef HAVE_IPV6 -- if (flag & F_IPV6 && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains))) -+ if ((flag & F_IPV6) && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains))) - { - char *p; - -@@ -259,7 +241,6 @@ int is_rev_synth(int flag, struct all_ad - - return 1; - } --#endif - - return 0; - } -@@ -286,7 +267,7 @@ char *get_domain(struct in_addr addr) - return daemon->domain_suffix; - } - --#ifdef HAVE_IPV6 -+ - static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c) - { - u64 addrpart = addr6part(addr); -@@ -310,4 +291,3 @@ char *get_domain6(struct in6_addr *addr) - - return daemon->domain_suffix; - } --#endif ---- a/src/dump.c -+++ b/src/dump.c -@@ -82,10 +82,8 @@ void dump_init(void) - void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst) - { - struct ip ip; --#ifdef HAVE_IPV6 - struct ip6_hdr ip6; - int family; --#endif - struct udphdr { - u16 uh_sport; /* source port */ - u16 uh_dport; /* destination port */ -@@ -105,7 +103,6 @@ void dump_packet(int mask, void *packet, - /* So wireshark can Id the packet. */ - udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT); - --#ifdef HAVE_IPV6 - if (src) - family = src->sa.sa_family; - else -@@ -139,7 +136,6 @@ void dump_packet(int mask, void *packet, - sum += ((u16 *)&ip6.ip6_src)[i]; - } - else --#endif - { - iphdr = &ip; - ipsz = sizeof(ip); ---- a/src/edns0.c -+++ b/src/edns0.c -@@ -301,20 +301,14 @@ static size_t add_mac(struct dns_header - - struct subnet_opt { - u16 family; -- u8 source_netmask, scope_netmask; --#ifdef HAVE_IPV6 -+ u8 source_netmask, scope_netmask; - u8 addr[IN6ADDRSZ]; --#else -- u8 addr[INADDRSZ]; --#endif - }; - - static void *get_addrp(union mysockaddr *addr, const short family) - { --#ifdef HAVE_IPV6 - if (family == AF_INET6) - return &addr->in6.sin6_addr; --#endif - - return &addr->in.sin_addr; - } -@@ -330,7 +324,6 @@ static size_t calc_subnet_opt(struct sub - opt->source_netmask = 0; - opt->scope_netmask = 0; - --#ifdef HAVE_IPV6 - if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6) - { - opt->source_netmask = daemon->add_subnet6->mask; -@@ -342,7 +335,6 @@ static size_t calc_subnet_opt(struct sub - else - addrp = &source->in6.sin6_addr; - } --#endif - - if (source->sa.sa_family == AF_INET && daemon->add_subnet4) - { -@@ -356,11 +348,7 @@ static size_t calc_subnet_opt(struct sub - addrp = &source->in.sin_addr; - } - --#ifdef HAVE_IPV6 - opt->family = htons(sa_family == AF_INET6 ? 2 : 1); --#else -- opt->family = htons(1); --#endif - - len = 0; - ---- a/src/forward.c -+++ b/src/forward.c -@@ -38,9 +38,7 @@ int send_from(int fd, int nowild, char * - #elif defined(IP_SENDSRCADDR) - char control[CMSG_SPACE(sizeof(struct in_addr))]; - #endif --#ifdef HAVE_IPV6 - char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; --#endif - } control_u; - - iov[0].iov_base = packet; -@@ -79,7 +77,6 @@ int send_from(int fd, int nowild, char * - #endif - } - else --#ifdef HAVE_IPV6 - { - struct in6_pktinfo p; - p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */ -@@ -89,9 +86,6 @@ int send_from(int fd, int nowild, char * - cmptr->cmsg_type = daemon->v6pktinfo; - cmptr->cmsg_level = IPPROTO_IPV6; - } --#else -- (void)iface; /* eliminate warning */ --#endif - } - - while (retry_send(sendmsg(fd, &msg, 0))); -@@ -144,10 +138,8 @@ static unsigned int search_servers(time_ - flags = sflag; - if (serv->addr.sa.sa_family == AF_INET) - *addrpp = (struct all_addr *)&serv->addr.in.sin_addr; --#ifdef HAVE_IPV6 - else - *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr; --#endif - } - else if (!flags || (flags & F_NXDOMAIN)) - flags = F_NOERR; -@@ -204,10 +196,8 @@ static unsigned int search_servers(time_ - flags = sflag; - if (serv->addr.sa.sa_family == AF_INET) - *addrpp = (struct all_addr *)&serv->addr.in.sin_addr; --#ifdef HAVE_IPV6 - else - *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr; --#endif - } - else if (!flags || (flags & F_NXDOMAIN)) - flags = F_NOERR; -@@ -236,10 +226,8 @@ static unsigned int search_servers(time_ - /* handle F_IPV4 and F_IPV6 set on ANY query to 0.0.0.0/:: domain. */ - if (flags & F_IPV4) - log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, qdomain, *addrpp, NULL); --#ifdef HAVE_IPV6 - if (flags & F_IPV6) - log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, qdomain, *addrpp, NULL); --#endif - } - } - else if ((*type) & SERV_USE_RESOLV) -@@ -302,20 +290,17 @@ static int forward_query(int udpfd, unio - - if (forward->sentto->addr.sa.sa_family == AF_INET) - log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec"); --#ifdef HAVE_IPV6 - else - log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec"); --#endif -+ - - if (forward->sentto->sfd) - fd = forward->sentto->sfd->fd; - else - { --#ifdef HAVE_IPV6 - if (forward->sentto->addr.sa.sa_family == AF_INET6) - fd = forward->rfd6->fd; - else --#endif - fd = forward->rfd4->fd; - } - -@@ -475,7 +460,6 @@ static int forward_query(int udpfd, unio - fd = start->sfd->fd; - else - { --#ifdef HAVE_IPV6 - if (start->addr.sa.sa_family == AF_INET6) - { - if (!forward->rfd6 && -@@ -485,7 +469,6 @@ static int forward_query(int udpfd, unio - fd = forward->rfd6->fd; - } - else --#endif - { - if (!forward->rfd4 && - !(forward->rfd4 = allocate_rfd(AF_INET))) -@@ -541,11 +524,9 @@ static int forward_query(int udpfd, unio - if (start->addr.sa.sa_family == AF_INET) - log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, - (struct all_addr *)&start->addr.in.sin_addr, NULL); --#ifdef HAVE_IPV6 - else - log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, - (struct all_addr *)&start->addr.in6.sin6_addr, NULL); --#endif - start->queries++; - forwarded = 1; - forward->sentto = start; -@@ -788,11 +769,8 @@ void reply_query(int fd, int family, tim - daemon->srv_save = NULL; - - /* Determine the address of the server replying so that we can mark that as good */ -- serveraddr.sa.sa_family = family; --#ifdef HAVE_IPV6 -- if (serveraddr.sa.sa_family == AF_INET6) -+ if ((serveraddr.sa.sa_family = family) == AF_INET6) - serveraddr.in6.sin6_flowinfo = 0; --#endif - - header = (struct dns_header *)daemon->packet; - -@@ -878,7 +856,6 @@ void reply_query(int fd, int family, tim - fd = start->sfd->fd; - else - { --#ifdef HAVE_IPV6 - if (start->addr.sa.sa_family == AF_INET6) - { - /* may have changed family */ -@@ -887,7 +864,6 @@ void reply_query(int fd, int family, tim - fd = forward->rfd6->fd; - } - else --#endif - { - /* may have changed family */ - if (!forward->rfd4) -@@ -902,10 +878,8 @@ void reply_query(int fd, int family, tim - - if (start->addr.sa.sa_family == AF_INET) - log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&start->addr.in.sin_addr, "dnssec"); --#ifdef HAVE_IPV6 - else - log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&start->addr.in6.sin6_addr, "dnssec"); --#endif - - return; - } -@@ -1099,9 +1073,7 @@ void reply_query(int fd, int family, tim - - new->sentto = server; - new->rfd4 = NULL; --#ifdef HAVE_IPV6 - new->rfd6 = NULL; --#endif - new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA); - new->forwardall = 0; - -@@ -1125,11 +1097,9 @@ void reply_query(int fd, int family, tim - if (server->addr.sa.sa_family == AF_INET) - log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, daemon->keyname, (struct all_addr *)&(server->addr.in.sin_addr), - querystr("dnssec-query", querytype)); --#ifdef HAVE_IPV6 - else - log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, daemon->keyname, (struct all_addr *)&(server->addr.in6.sin6_addr), - querystr("dnssec-query", querytype)); --#endif - - if ((hash = hash_questions(header, nn, daemon->namebuff))) - memcpy(new->hash, hash, HASH_SIZE); -@@ -1147,14 +1117,12 @@ void reply_query(int fd, int family, tim - else - { - fd = -1; --#ifdef HAVE_IPV6 - if (server->addr.sa.sa_family == AF_INET6) - { - if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6))) - fd = new->rfd6->fd; - } - else --#endif - { - if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET))) - fd = new->rfd4->fd; -@@ -1290,9 +1258,7 @@ void receive_query(struct listener *list - struct cmsghdr *cmptr; - union { - struct cmsghdr align; /* this ensures alignment */ --#ifdef HAVE_IPV6 - char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; --#endif - #if defined(HAVE_LINUX_NETWORK) - char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; - #elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK) -@@ -1303,12 +1269,8 @@ void receive_query(struct listener *list - CMSG_SPACE(sizeof(struct sockaddr_dl))]; - #endif - } control_u; --#ifdef HAVE_IPV6 - /* Can always get recvd interface for IPv6 */ - int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6; --#else -- int check_dst = !option_bool(OPT_NOWILD); --#endif - - /* packet buffer overwritten */ - daemon->srv_save = NULL; -@@ -1359,7 +1321,6 @@ void receive_query(struct listener *list - if (source_addr.in.sin_port == 0) - return; - } --#ifdef HAVE_IPV6 - else - { - /* Source-port == 0 is an error, we can't send back to that. */ -@@ -1367,13 +1328,12 @@ void receive_query(struct listener *list - return; - source_addr.in6.sin6_flowinfo = 0; - } --#endif - - /* We can be configured to only accept queries from at-most-one-hop-away addresses. */ - if (option_bool(OPT_LOCAL_SERVICE)) - { - struct addrlist *addr; --#ifdef HAVE_IPV6 -+ - if (listen->family == AF_INET6) - { - for (addr = daemon->interface_addrs; addr; addr = addr->next) -@@ -1382,7 +1342,6 @@ void receive_query(struct listener *list - break; - } - else --#endif - { - struct in_addr netmask; - for (addr = daemon->interface_addrs; addr; addr = addr->next) -@@ -1451,7 +1410,6 @@ void receive_query(struct listener *list - } - #endif - --#ifdef HAVE_IPV6 - if (listen->family == AF_INET6) - { - for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) -@@ -1467,7 +1425,6 @@ void receive_query(struct listener *list - if_index = p.p->ipi6_ifindex; - } - } --#endif - - /* enforce available interface configuration */ - -@@ -1531,11 +1488,9 @@ void receive_query(struct listener *list - if (listen->family == AF_INET) - log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, - (struct all_addr *)&source_addr.in.sin_addr, types); --#ifdef HAVE_IPV6 - else - log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, - (struct all_addr *)&source_addr.in6.sin6_addr, types); --#endif - - #ifdef HAVE_AUTH - /* find queries for zones we're authoritative for, and answer them directly */ -@@ -1744,11 +1699,9 @@ static int tcp_key_recurse(time_t now, i - if (server->addr.sa.sa_family == AF_INET) - log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (struct all_addr *)&(server->addr.in.sin_addr), - querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS)); --#ifdef HAVE_IPV6 - else - log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (struct all_addr *)&(server->addr.in6.sin6_addr), - querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS)); --#endif - - server->flags |= SERV_GOT_TCP; - -@@ -1813,11 +1766,10 @@ unsigned char *tcp_request(int confd, ti - if (option_bool(OPT_CONNTRACK)) - { - struct all_addr local; --#ifdef HAVE_IPV6 -+ - if (local_addr->sa.sa_family == AF_INET6) - local.addr.addr6 = local_addr->in6.sin6_addr; - else --#endif - local.addr.addr4 = local_addr->in.sin_addr; - - have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark); -@@ -1828,7 +1780,7 @@ unsigned char *tcp_request(int confd, ti - if (option_bool(OPT_LOCAL_SERVICE)) - { - struct addrlist *addr; --#ifdef HAVE_IPV6 -+ - if (peer_addr.sa.sa_family == AF_INET6) - { - for (addr = daemon->interface_addrs; addr; addr = addr->next) -@@ -1837,7 +1789,6 @@ unsigned char *tcp_request(int confd, ti - break; - } - else --#endif - { - struct in_addr netmask; - for (addr = daemon->interface_addrs; addr; addr = addr->next) -@@ -1892,11 +1843,9 @@ unsigned char *tcp_request(int confd, ti - if (peer_addr.sa.sa_family == AF_INET) - log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, - (struct all_addr *)&peer_addr.in.sin_addr, types); --#ifdef HAVE_IPV6 - else - log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, - (struct all_addr *)&peer_addr.in6.sin6_addr, types); --#endif - - #ifdef HAVE_AUTH - /* find queries for zones we're authoritative for, and answer them directly */ -@@ -2072,11 +2021,9 @@ unsigned char *tcp_request(int confd, ti - if (last_server->addr.sa.sa_family == AF_INET) - log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, - (struct all_addr *)&last_server->addr.in.sin_addr, NULL); --#ifdef HAVE_IPV6 - else - log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, - (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL); --#endif - - #ifdef HAVE_DNSSEC - if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC)) -@@ -2175,9 +2122,7 @@ static struct frec *allocate_frec(time_t - f->sentto = NULL; - f->rfd4 = NULL; - f->flags = 0; --#ifdef HAVE_IPV6 - f->rfd6 = NULL; --#endif - #ifdef HAVE_DNSSEC - f->dependent = NULL; - f->blocking_query = NULL; -@@ -2237,11 +2182,8 @@ static void free_frec(struct frec *f) - f->rfd4 = NULL; - f->sentto = NULL; - f->flags = 0; -- --#ifdef HAVE_IPV6 - free_rfd(f->rfd6); - f->rfd6 = NULL; --#endif - - #ifdef HAVE_DNSSEC - if (f->stash) ---- a/src/helper.c -+++ b/src/helper.c -@@ -64,9 +64,7 @@ struct script_data - #ifdef HAVE_TFTP - off_t file_len; - #endif --#ifdef HAVE_IPV6 - struct in6_addr addr6; --#endif - #ifdef HAVE_DHCP6 - int iaid, vendorclass_count; - #endif -@@ -302,10 +300,8 @@ int create_helper(int event_fd, int err_ - - if (!is6) - inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN); --#ifdef HAVE_IPV6 - else - inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN); --#endif - - #ifdef HAVE_TFTP - /* file length */ -@@ -826,10 +822,8 @@ void queue_tftp(off_t file_len, char *fi - - if ((buf->flags = peer->sa.sa_family) == AF_INET) - buf->addr = peer->in.sin_addr; --#ifdef HAVE_IPV6 - else - buf->addr6 = peer->in6.sin6_addr; --#endif - - memcpy((unsigned char *)(buf+1), filename, filename_len); - -@@ -851,10 +845,8 @@ void queue_arp(int action, unsigned char - buf->hwaddr_type = ARPHRD_ETHER; - if ((buf->flags = family) == AF_INET) - buf->addr = addr->addr.addr4; --#ifdef HAVE_IPV6 - else - buf->addr6 = addr->addr.addr6; --#endif - - memcpy(buf->hwaddr, mac, maclen); - ---- a/src/ipset.c -+++ b/src/ipset.c -@@ -120,13 +120,8 @@ static int new_add_to_ipset(const char * - struct my_nfgenmsg *nfg; - struct my_nlattr *nested[2]; - uint8_t proto; -- int addrsz = INADDRSZ; -+ int addrsz = (af == AF_INET6) ? INADDRSZ : IN6ADDRSZ; - --#ifdef HAVE_IPV6 -- if (af == AF_INET6) -- addrsz = IN6ADDRSZ; --#endif -- - if (strlen(setname) >= IPSET_MAXNAMELEN) - { - errno = ENAMETOOLONG; -@@ -213,7 +208,6 @@ int add_to_ipset(const char *setname, co - { - int ret = 0, af = AF_INET; - --#ifdef HAVE_IPV6 - if (flags & F_IPV6) - { - af = AF_INET6; -@@ -224,7 +218,6 @@ int add_to_ipset(const char *setname, co - ret = -1; - } - } --#endif - - if (ret != -1) - ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove); ---- a/src/netlink.c -+++ b/src/netlink.c -@@ -51,11 +51,10 @@ void netlink_init(void) - addr.nl_groups = RTMGRP_IPV4_ROUTE; - if (option_bool(OPT_CLEVERBIND)) - addr.nl_groups |= RTMGRP_IPV4_IFADDR; --#ifdef HAVE_IPV6 - addr.nl_groups |= RTMGRP_IPV6_ROUTE; - if (option_bool(OPT_CLEVERBIND)) - addr.nl_groups |= RTMGRP_IPV6_IFADDR; --#endif -+ - #ifdef HAVE_DHCP6 - if (daemon->doing_ra || daemon->doing_dhcp6) - addr.nl_groups |= RTMGRP_IPV6_IFADDR; -@@ -235,7 +234,6 @@ int iface_enumerate(int family, void *pa - if (!((*callback)(addr, ifa->ifa_index, label, netmask, broadcast, parm))) - callback_ok = 0; - } --#ifdef HAVE_IPV6 - else if (ifa->ifa_family == AF_INET6) - { - struct in6_addr *addrp = NULL; -@@ -270,7 +268,6 @@ int iface_enumerate(int family, void *pa - (int) preferred, (int)valid, parm))) - callback_ok = 0; - } --#endif - } - } - else if (h->nlmsg_type == RTM_NEWNEIGH && family == AF_UNSPEC) ---- a/src/network.c -+++ b/src/network.c -@@ -137,12 +137,10 @@ int iface_check(int family, struct all_a - if (family == AF_INET && - tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) - ret = match_addr = tmp->used = 1; --#ifdef HAVE_IPV6 - else if (family == AF_INET6 && - IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, - &addr->addr.addr6)) - ret = match_addr = tmp->used = 1; --#endif - } - } - -@@ -162,11 +160,9 @@ int iface_check(int family, struct all_a - else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET && - tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) - break; --#ifdef HAVE_IPV6 - else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 && - IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6)) - break; --#endif - - if (tmp && auth) - { -@@ -200,11 +196,8 @@ int loopback_exception(int fd, int famil - if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) - return 1; - } --#ifdef HAVE_IPV6 - else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6)) - return 1; --#endif -- - } - } - return 0; -@@ -292,19 +285,15 @@ static int iface_allowed(struct iface_pa - al->addr.addr.addr4 = addr->in.sin_addr; - al->flags = 0; - } --#ifdef HAVE_IPV6 - else - { - al->addr.addr.addr6 = addr->in6.sin6_addr; - al->flags = ADDRLIST_IPV6; - } --#endif - } - } - --#ifdef HAVE_IPV6 - if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr)) --#endif - { - struct interface_name *int_name; - struct addrlist *al; -@@ -337,7 +326,6 @@ static int iface_allowed(struct iface_pa - } - } - --#ifdef HAVE_IPV6 - if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6)) - { - if (param->spare) -@@ -357,8 +345,6 @@ static int iface_allowed(struct iface_pa - al->flags = ADDRLIST_IPV6; - } - } --#endif -- - } - #endif - -@@ -386,7 +372,6 @@ static int iface_allowed(struct iface_pa - al->addr.addr.addr4 = addr->in.sin_addr; - al->flags = 0; - } --#ifdef HAVE_IPV6 - else - { - al->addr.addr.addr6 = addr->in6.sin6_addr; -@@ -396,7 +381,6 @@ static int iface_allowed(struct iface_pa - if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE))) - al->flags |= ADDRLIST_REVONLY; - } --#endif - } - } - } -@@ -438,11 +422,9 @@ static int iface_allowed(struct iface_pa - !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns)) - return 1; - --#ifdef HAVE_IPV6 - if (addr->sa.sa_family == AF_INET6 && - !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns)) - return 1; --#endif - - #ifdef HAVE_DHCP - /* No DHCP where we're doing auth DNS. */ -@@ -501,7 +483,6 @@ static int iface_allowed(struct iface_pa - return 0; - } - --#ifdef HAVE_IPV6 - static int iface_allowed_v6(struct in6_addr *local, int prefix, - int scope, int if_index, int flags, - int preferred, int valid, void *vparam) -@@ -529,7 +510,6 @@ static int iface_allowed_v6(struct in6_a - - return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags); - } --#endif - - static int iface_allowed_v4(struct in_addr local, int if_index, char *label, - struct in_addr netmask, struct in_addr broadcast, void *vparam) -@@ -633,9 +613,7 @@ int enumerate_interfaces(int reset) - - param.spare = spare; - --#ifdef HAVE_IPV6 - ret = iface_enumerate(AF_INET6, ¶m, iface_allowed_v6); --#endif - - if (ret) - ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4); -@@ -740,10 +718,8 @@ static int make_sock(union mysockaddr *a - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd)) - goto err; - --#ifdef HAVE_IPV6 - if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) - goto err; --#endif - - if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1) - goto err; -@@ -767,15 +743,12 @@ static int make_sock(union mysockaddr *a - #endif - } - } --#ifdef HAVE_IPV6 - else if (!set_ipv6pktinfo(fd)) - goto err; --#endif - - return fd; - } - --#ifdef HAVE_IPV6 - int set_ipv6pktinfo(int fd) - { - int opt = 1; -@@ -802,7 +775,6 @@ int set_ipv6pktinfo(int fd) - - return 0; - } --#endif - - - /* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */ -@@ -842,7 +814,6 @@ int tcp_interface(int fd, int af) - } - } - } --#ifdef HAVE_IPV6 - else - { - /* Only the RFC-2292 API has the ability to find the interface for TCP connections, -@@ -874,7 +845,6 @@ int tcp_interface(int fd, int af) - } - } - } --#endif /* IPV6 */ - #endif /* Linux */ - - return if_index; -@@ -904,7 +874,6 @@ static struct listener *create_listeners - tftpfd = make_sock(addr, SOCK_DGRAM, dienow); - addr->in.sin_port = save; - } --# ifdef HAVE_IPV6 - else - { - short save = addr->in6.sin6_port; -@@ -912,7 +881,6 @@ static struct listener *create_listeners - tftpfd = make_sock(addr, SOCK_DGRAM, dienow); - addr->in6.sin6_port = save; - } --# endif - } - #endif - -@@ -945,11 +913,10 @@ void create_wildcard_listeners(void) - - l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1); - --#ifdef HAVE_IPV6 - memset(&addr, 0, sizeof(addr)); --# ifdef HAVE_SOCKADDR_SA_LEN -+#ifdef HAVE_SOCKADDR_SA_LEN - addr.in6.sin6_len = sizeof(addr.in6); --# endif -+#endif - addr.in6.sin6_family = AF_INET6; - addr.in6.sin6_addr = in6addr_any; - addr.in6.sin6_port = htons(daemon->port); -@@ -959,7 +926,6 @@ void create_wildcard_listeners(void) - l->next = l6; - else - l = l6; --#endif - - daemon->listeners = l; - } -@@ -1159,7 +1125,6 @@ int random_sock(int family) - addr.in.sin_len = sizeof(struct sockaddr_in); - #endif - } --#ifdef HAVE_IPV6 - else - { - addr.in6.sin6_addr = in6addr_any; -@@ -1168,7 +1133,6 @@ int random_sock(int family) - addr.in6.sin6_len = sizeof(struct sockaddr_in6); - #endif - } --#endif - - if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0) - return fd; -@@ -1193,10 +1157,8 @@ int local_bind(int fd, union mysockaddr - { - if (addr_copy.sa.sa_family == AF_INET) - addr_copy.in.sin_port = 0; --#ifdef HAVE_IPV6 - else - addr_copy.in6.sin6_port = 0; --#endif - } - - if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1) -@@ -1211,7 +1173,7 @@ int local_bind(int fd, union mysockaddr - return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0; - } - #endif --#if defined(HAVE_IPV6) && defined (IPV6_UNICAST_IF) -+#if defined (IPV6_UNICAST_IF) - if (addr_copy.sa.sa_family == AF_INET6) - { - uint32_t ifindex_opt = htonl(ifindex); -@@ -1247,12 +1209,10 @@ static struct serverfd *allocate_sfd(uni - addr->in.sin_port == htons(0)) - return NULL; - --#ifdef HAVE_IPV6 - if (addr->sa.sa_family == AF_INET6 && - memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 && - addr->in6.sin6_port == htons(0)) - return NULL; --#endif - } - - if (intname && strlen(intname) != 0) -@@ -1315,7 +1275,7 @@ void pre_allocate_sfds(void) - #endif - if ((sfd = allocate_sfd(&addr, ""))) - sfd->preallocated = 1; --#ifdef HAVE_IPV6 -+ - memset(&addr, 0, sizeof(addr)); - addr.in6.sin6_family = AF_INET6; - addr.in6.sin6_addr = in6addr_any; -@@ -1325,7 +1285,6 @@ void pre_allocate_sfds(void) - #endif - if ((sfd = allocate_sfd(&addr, ""))) - sfd->preallocated = 1; --#endif - } - - for (srv = daemon->servers; srv; srv = srv->next) -@@ -1658,7 +1617,6 @@ int reload_servers(char *fname) - source_addr.in.sin_addr.s_addr = INADDR_ANY; - source_addr.in.sin_port = htons(daemon->query_port); - } --#ifdef HAVE_IPV6 - else - { - int scope_index = 0; -@@ -1686,10 +1644,6 @@ int reload_servers(char *fname) - else - continue; - } --#else /* IPV6 */ -- else -- continue; --#endif - - add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL); - gotone = 1; ---- a/src/option.c -+++ b/src/option.c -@@ -764,10 +764,8 @@ static char *parse_mysockaddr(char *arg, - { - if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0) - addr->sa.sa_family = AF_INET; --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) - addr->sa.sa_family = AF_INET6; --#endif - else - return _("bad address"); - -@@ -779,10 +777,8 @@ char *parse_server(char *arg, union myso - int source_port = 0, serv_port = NAMESERVER_PORT; - char *portno, *source; - char *interface_opt = NULL; --#ifdef HAVE_IPV6 - int scope_index = 0; - char *scope_id; --#endif - - if (!arg || strlen(arg) == 0) - { -@@ -800,9 +796,7 @@ char *parse_server(char *arg, union myso - !atoi_check16(portno, &serv_port)) - return _("bad port"); - --#ifdef HAVE_IPV6 - scope_id = split_chr(arg, '%'); --#endif - - if (source) { - interface_opt = split_chr(source, '@'); -@@ -846,7 +840,6 @@ char *parse_server(char *arg, union myso - } - } - } --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) - { - if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0) -@@ -881,7 +874,6 @@ char *parse_server(char *arg, union myso - } - } - } --#endif - else - return _("bad address"); - -@@ -1914,10 +1906,8 @@ static int one_opt(int option, char *arg - unhide_metas(arg); - if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0) - new->addr.sa.sa_family = AF_INET; --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0) - new->addr.sa.sa_family = AF_INET6; --#endif - else - { - char *fam = split_chr(arg, '/'); -@@ -1927,10 +1917,8 @@ static int one_opt(int option, char *arg - { - if (strcmp(fam, "4") == 0) - new->addr.sa.sa_family = AF_INET; --#ifdef HAVE_IPV6 - else if (strcmp(fam, "6") == 0) - new->addr.sa.sa_family = AF_INET6; --#endif - else - ret_err(gen_err); - } -@@ -1996,14 +1984,12 @@ static int one_opt(int option, char *arg - subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen; - subnet->flags = ADDRLIST_LITERAL; - } --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, arg, &addr.addr.addr6)) - { - subnet = opt_malloc(sizeof(struct addrlist)); - subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen; - subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6; - } --#endif - else - { - struct auth_name_list *name = opt_malloc(sizeof(struct auth_name_list)); -@@ -2015,10 +2001,8 @@ static int one_opt(int option, char *arg - { - if (prefixlen == 4) - name->flags &= ~AUTH6; --#ifdef HAVE_IPV6 - else if (prefixlen == 6) - name->flags &= ~AUTH4; --#endif - else - ret_err(gen_err); - } -@@ -2139,7 +2123,6 @@ static int one_opt(int option, char *arg - } - } - } --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, comma, &new->start6)) - { - u64 mask = (1LLU << (128 - msize)) - 1LLU; -@@ -2183,7 +2166,6 @@ static int one_opt(int option, char *arg - } - } - } --#endif - else - ret_err(gen_err); - } -@@ -2201,7 +2183,6 @@ static int one_opt(int option, char *arg - else if (!inet_pton(AF_INET, arg, &new->end)) - ret_err(gen_err); - } --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, comma, &new->start6)) - { - new->is6 = 1; -@@ -2210,7 +2191,6 @@ static int one_opt(int option, char *arg - else if (!inet_pton(AF_INET6, arg, &new->end6)) - ret_err(gen_err); - } --#endif - else - ret_err(gen_err); - -@@ -2369,7 +2349,6 @@ static int one_opt(int option, char *arg - new->addr.in.sin_len = sizeof(new->addr.in); - #endif - } --#ifdef HAVE_IPV6 - else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0) - { - new->addr.sa.sa_family = AF_INET6; -@@ -2380,7 +2359,6 @@ static int one_opt(int option, char *arg - new->addr.in6.sin6_len = sizeof(new->addr.in6); - #endif - } --#endif - else - ret_err(gen_err); - -@@ -2493,9 +2471,7 @@ static int one_opt(int option, char *arg - int size; - struct server *serv; - struct in_addr addr4; --#ifdef HAVE_IPV6 - struct in6_addr addr6; --#endif - - unhide_metas(arg); - if (!arg || !(comma=split(arg)) || !(string = split_chr(arg, '/')) || !atoi_check(string, &size)) -@@ -2507,10 +2483,8 @@ static int one_opt(int option, char *arg - if (!serv) - ret_err(_("bad prefix")); - } --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, arg, &addr6)) - serv = add_rev6(&addr6, size); --#endif - else - ret_err(gen_err); - -@@ -3863,10 +3837,8 @@ err: - { - if (strcmp(arg, "4") == 0) - new->family = AF_INET; --#ifdef HAVE_IPV6 - else if (strcmp(arg, "6") == 0) - new->family = AF_INET6; --#endif - else - ret_err(gen_err); - } -@@ -4156,10 +4128,8 @@ err: - new->ttl = atoi(arg); - else if (inet_pton(AF_INET, arg, &addr)) - new->addr = addr.addr.addr4; --#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, arg, &addr)) - new->addr6 = addr.addr.addr6; --#endif - else - { - int nomem; -@@ -4866,10 +4836,8 @@ void read_opts(int argc, char **argv, ch - { - if (tmp->source_addr.sa.sa_family == AF_INET) - tmp->source_addr.in.sin_port = htons(daemon->query_port); --#ifdef HAVE_IPV6 - else if (tmp->source_addr.sa.sa_family == AF_INET6) - tmp->source_addr.in6.sin6_port = htons(daemon->query_port); --#endif - } - } - -@@ -4930,10 +4898,8 @@ void read_opts(int argc, char **argv, ch - for(tmp = daemon->if_addrs; tmp; tmp = tmp->next) - if (tmp->addr.sa.sa_family == AF_INET) - tmp->addr.in.sin_port = htons(daemon->port); --#ifdef HAVE_IPV6 - else if (tmp->addr.sa.sa_family == AF_INET6) - tmp->addr.in6.sin6_port = htons(daemon->port); --#endif /* IPv6 */ - } - - /* create default, if not specified */ ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -198,7 +198,6 @@ int in_arpa_name_2_addr(char *namein, st - - return F_IPV4; - } --#ifdef HAVE_IPV6 - else if (hostname_isequal(penchunk, "ip6") && - (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa"))) - { -@@ -243,7 +242,6 @@ int in_arpa_name_2_addr(char *namein, st - return F_IPV6; - } - } --#endif - - return 0; - } -@@ -426,7 +424,6 @@ int private_net(struct in_addr addr, int - ((ip_addr & 0xFFFFFFFF) == 0xFFFFFFFF) /* 255.255.255.255/32 (broadcast)*/ ; - } - --#ifdef HAVE_IPV6 - static int private_net6(struct in6_addr *a) - { - return -@@ -436,8 +433,6 @@ static int private_net6(struct in6_addr - ((unsigned char *)a)[0] == 0xfd || /* RFC 6303 4.4 */ - ((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */ - } --#endif -- - - static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name, int *doctored) - { -@@ -738,13 +733,11 @@ int extract_addresses(struct dns_header - addrlen = INADDRSZ; - flags |= F_IPV4; - } --#ifdef HAVE_IPV6 - else if (qtype == T_AAAA) - { - addrlen = IN6ADDRSZ; - flags |= F_IPV6; - } --#endif - else - continue; - -@@ -818,7 +811,6 @@ int extract_addresses(struct dns_header - private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND))) - return 1; - --#ifdef HAVE_IPV6 - if ((flags & F_IPV6) && - IN6_IS_ADDR_V4MAPPED(&addr.addr.addr6)) - { -@@ -827,7 +819,6 @@ int extract_addresses(struct dns_header - if (private_net(v4, !option_bool(OPT_LOCAL_REBIND))) - return 1; - } --#endif - } - - #ifdef HAVE_IPSET -@@ -966,7 +957,6 @@ size_t setup_reply(struct dns_header *he - add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp); - } - --#ifdef HAVE_IPV6 - if (flags & F_IPV6) - { - SET_RCODE(header, NOERROR); -@@ -974,7 +964,6 @@ size_t setup_reply(struct dns_header *he - header->hb3 |= HB3_AA; - add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp); - } --#endif - } - else /* nowhere to forward to */ - { -@@ -1164,14 +1153,12 @@ int add_resource_record(struct dns_heade - for (; *format; format++) - switch (*format) - { --#ifdef HAVE_IPV6 - case '6': - CHECK_LIMIT(IN6ADDRSZ); - sval = va_arg(ap, char *); - memcpy(p, sval, IN6ADDRSZ); - p += IN6ADDRSZ; - break; --#endif - - case '4': - CHECK_LIMIT(INADDRSZ); -@@ -1413,7 +1400,6 @@ size_t answer_request(struct dns_header - while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) - intr = intr->next; - } --#ifdef HAVE_IPV6 - else if (is_arpa == F_IPV6) - for (intr = daemon->int_names; intr; intr = intr->next) - { -@@ -1429,7 +1415,6 @@ size_t answer_request(struct dns_header - while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) - intr = intr->next; - } --#endif - - if (intr) - { -@@ -1521,9 +1506,7 @@ size_t answer_request(struct dns_header - } - } - else if (option_bool(OPT_BOGUSPRIV) && ( --#ifdef HAVE_IPV6 - (is_arpa == F_IPV6 && private_net6(&addr.addr.addr6)) || --#endif - (is_arpa == F_IPV4 && private_net(addr.addr.addr4, 1)))) - { - struct server *serv; -@@ -1564,16 +1547,9 @@ size_t answer_request(struct dns_header - - for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0) - { -- unsigned short type = T_A; -+ unsigned short type = (flag == F_IPV6) ? T_AAAA : T_A; - struct interface_name *intr; - -- if (flag == F_IPV6) --#ifdef HAVE_IPV6 -- type = T_AAAA; --#else -- break; --#endif -- - if (qtype != type && qtype != T_ANY) - continue; - -@@ -1596,31 +1572,26 @@ size_t answer_request(struct dns_header - for (intr = daemon->int_names; intr; intr = intr->next) - if (hostname_isequal(name, intr->name)) - for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) --#ifdef HAVE_IPV6 -- if (!(addrlist->flags & ADDRLIST_IPV6)) --#endif -- if (is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask)) -- { -- localise = 1; -- break; -- } -+ if (!(addrlist->flags & ADDRLIST_IPV6) && -+ is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask)) -+ { -+ localise = 1; -+ break; -+ } - - for (intr = daemon->int_names; intr; intr = intr->next) - if (hostname_isequal(name, intr->name)) - { - for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) --#ifdef HAVE_IPV6 - if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type) --#endif - { - if (localise && - !is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask)) - continue; - --#ifdef HAVE_IPV6 - if (addrlist->flags & ADDRLIST_REVONLY) - continue; --#endif -+ - ans = 1; - sec_data = 0; - if (!dryrun) -@@ -1904,11 +1875,8 @@ size_t answer_request(struct dns_header - crecp = NULL; - while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6))) - { --#ifdef HAVE_IPV6 - int type = crecp->flags & F_IPV4 ? T_A : T_AAAA; --#else -- int type = T_A; --#endif -+ - if (crecp->flags & F_NEG) - continue; - ---- a/src/tables.c -+++ b/src/tables.c -@@ -108,7 +108,7 @@ int add_to_ipset(const char *setname, co - my_syslog(LOG_INFO, _("info: table created")); - - bzero(&addr, sizeof(addr)); --#ifdef HAVE_IPV6 -+ - if (flags & F_IPV6) - { - addr.pfra_af = AF_INET6; -@@ -116,7 +116,6 @@ int add_to_ipset(const char *setname, co - memcpy(&(addr.pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr)); - } - else --#endif - { - addr.pfra_af = AF_INET; - addr.pfra_net = 0x20; ---- a/src/tftp.c -+++ b/src/tftp.c -@@ -60,17 +60,11 @@ void tftp_request(struct listener *liste - char *prefix = daemon->tftp_prefix; - struct tftp_prefix *pref; - struct all_addr addra; --#ifdef HAVE_IPV6 - /* Can always get recvd interface for IPv6 */ - int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6; --#else -- int check_dest = !option_bool(OPT_NOWILD); --#endif - union { - struct cmsghdr align; /* this ensures alignment */ --#ifdef HAVE_IPV6 - char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; --#endif - #if defined(HAVE_LINUX_NETWORK) - char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; - #elif defined(HAVE_SOLARIS_NETWORK) -@@ -174,7 +168,6 @@ void tftp_request(struct listener *liste - - #endif - --#ifdef HAVE_IPV6 - if (listen->family == AF_INET6) - { - for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) -@@ -190,7 +183,6 @@ void tftp_request(struct listener *liste - if_index = p.p->ipi6_ifindex; - } - } --#endif - - if (!indextoname(listen->tftpfd, if_index, namebuff)) - return; -@@ -199,10 +191,8 @@ void tftp_request(struct listener *liste - - addra.addr.addr4 = addr.in.sin_addr; - --#ifdef HAVE_IPV6 - if (listen->family == AF_INET6) - addra.addr.addr6 = addr.in6.sin6_addr; --#endif - - if (daemon->tftp_interfaces) - { -@@ -262,7 +252,6 @@ void tftp_request(struct listener *liste - addr.in.sin_len = sizeof(addr.in); - #endif - } --#ifdef HAVE_IPV6 - else - { - addr.in6.sin6_port = htons(port); -@@ -272,7 +261,6 @@ void tftp_request(struct listener *liste - addr.in6.sin6_len = sizeof(addr.in6); - #endif - } --#endif - - if (!(transfer = whine_malloc(sizeof(struct tftp_transfer)))) - return; -@@ -310,10 +298,9 @@ void tftp_request(struct listener *liste - { - if (listen->family == AF_INET) - addr.in.sin_port = htons(port); --#ifdef HAVE_IPV6 - else -- addr.in6.sin6_port = htons(port); --#endif -+ addr.in6.sin6_port = htons(port); -+ - continue; - } - my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP")); ---- a/src/util.c -+++ b/src/util.c -@@ -320,13 +320,12 @@ int sockaddr_isequal(union mysockaddr *s - s1->in.sin_port == s2->in.sin_port && - s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr) - return 1; --#ifdef HAVE_IPV6 -+ - if (s1->sa.sa_family == AF_INET6 && - s1->in6.sin6_port == s2->in6.sin6_port && - s1->in6.sin6_scope_id == s2->in6.sin6_scope_id && - IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr)) - return 1; --#endif - } - return 0; - } -@@ -336,11 +335,9 @@ int sa_len(union mysockaddr *addr) - #ifdef HAVE_SOCKADDR_SA_LEN - return addr->sa.sa_len; - #else --#ifdef HAVE_IPV6 - if (addr->sa.sa_family == AF_INET6) - return sizeof(addr->in6); - else --#endif - return sizeof(addr->in); - #endif - } -@@ -437,7 +434,6 @@ int is_same_net(struct in_addr a, struct - return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); - } - --#ifdef HAVE_IPV6 - int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen) - { - int pfbytes = prefixlen >> 3; -@@ -476,15 +472,12 @@ void setaddr6part(struct in6_addr *addr, - } - } - --#endif -- - - /* returns port number from address */ - int prettyprint_addr(union mysockaddr *addr, char *buf) - { - int port = 0; - --#ifdef HAVE_IPV6 - if (addr->sa.sa_family == AF_INET) - { - inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN); -@@ -503,10 +496,6 @@ int prettyprint_addr(union mysockaddr *a - } - port = ntohs(addr->in6.sin6_port); - } --#else -- strcpy(buf, inet_ntoa(addr->in.sin_addr)); -- port = ntohs(addr->in.sin_port); --#endif - - return port; - } diff --git a/package/network/services/dnsmasq/patches/0004-Don-t-forward-.bind-.server-queries-upstream.patch b/package/network/services/dnsmasq/patches/0004-Don-t-forward-.bind-.server-queries-upstream.patch deleted file mode 100644 index 497b4c3df2..0000000000 --- a/package/network/services/dnsmasq/patches/0004-Don-t-forward-.bind-.server-queries-upstream.patch +++ /dev/null @@ -1,52 +0,0 @@ -From cf5984367bc6a949e3803a576512c5a7bc48ebab Mon Sep 17 00:00:00 2001 -From: Vladislav Grishenko -Date: Thu, 18 Oct 2018 04:55:21 +0500 -Subject: [PATCH 04/11] Don't forward *.bind/*.server queries upstream - -Chaos .bind and .server (RFC4892) zones are local, therefore -don't forward queries upstream to avoid mixing with supported -locally and false replies with NO_ID enabled. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/rfc1035.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1276,7 +1276,7 @@ size_t answer_request(struct dns_header - int q, ans, anscount = 0, addncount = 0; - int dryrun = 0; - struct crec *crecp; -- int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1; -+ int nxdomain = 0, notimp = 0, auth = 1, trunc = 0, sec_data = 1; - struct mx_srv_record *rec; - size_t len; - -@@ -1355,6 +1355,17 @@ size_t answer_request(struct dns_header - } - } - -+ if (qclass == C_CHAOS) -+ { -+ /* don't forward *.bind and *.server chaos queries */ -+ if (hostname_issubdomain("bind", name) || hostname_issubdomain("server", name)) -+ { -+ if (!ans) -+ notimp = 1, auth = 0; -+ ans = 1; -+ } -+ } -+ - if (qclass == C_IN) - { - struct txt_record *t; -@@ -1903,6 +1914,8 @@ size_t answer_request(struct dns_header - - if (nxdomain) - SET_RCODE(header, NXDOMAIN); -+ else if (notimp) -+ SET_RCODE(header, NOTIMP); - else - SET_RCODE(header, NOERROR); /* no error */ - header->ancount = htons(anscount); diff --git a/package/network/services/dnsmasq/patches/0005-Fix-logging-in-cf5984367bc6a949e3803a576512c5a7bc48e.patch b/package/network/services/dnsmasq/patches/0005-Fix-logging-in-cf5984367bc6a949e3803a576512c5a7bc48e.patch deleted file mode 100644 index b9be306118..0000000000 --- a/package/network/services/dnsmasq/patches/0005-Fix-logging-in-cf5984367bc6a949e3803a576512c5a7bc48e.patch +++ /dev/null @@ -1,63 +0,0 @@ -From cbb5b17ad8e03e08ade62376a4f6a2066e55960d Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Tue, 23 Oct 2018 23:45:57 +0100 -Subject: [PATCH 05/11] Fix logging in cf5984367bc6a949e3803a576512c5a7bc48ebab - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/rfc1035.c | 27 ++++++++++++++++++--------- - 1 file changed, 18 insertions(+), 9 deletions(-) - ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1335,7 +1335,6 @@ size_t answer_request(struct dns_header - { - unsigned long ttl = daemon->local_ttl; - int ok = 1; -- log_query(F_CONFIG | F_RRNAME, name, NULL, ""); - #ifndef NO_ID - /* Dynamically generate stat record */ - if (t->stat != 0) -@@ -1345,11 +1344,14 @@ size_t answer_request(struct dns_header - ok = 0; - } - #endif -- if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp, -- ttl, NULL, -- T_TXT, t->class, "t", t->len, t->txt)) -- anscount++; -- -+ if (ok) -+ { -+ log_query(F_CONFIG | F_RRNAME, name, NULL, ""); -+ if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, -+ ttl, NULL, -+ T_TXT, t->class, "t", t->len, t->txt)) -+ anscount++; -+ } - } - } - } -@@ -1357,12 +1359,19 @@ size_t answer_request(struct dns_header - - if (qclass == C_CHAOS) - { -- /* don't forward *.bind and *.server chaos queries */ -+ /* don't forward *.bind and *.server chaos queries - always reply with NOTIMP */ - if (hostname_issubdomain("bind", name) || hostname_issubdomain("server", name)) - { - if (!ans) -- notimp = 1, auth = 0; -- ans = 1; -+ { -+ notimp = 1, auth = 0; -+ if (!dryrun) -+ { -+ addr.addr.rcode.rcode = NOTIMP; -+ log_query(F_CONFIG | F_RCODE, name, &addr, NULL); -+ } -+ ans = 1; -+ } - } - } - diff --git a/package/network/services/dnsmasq/patches/0006-Fix-spurious-AD-flags-in-some-DNS-replies-from-local.patch b/package/network/services/dnsmasq/patches/0006-Fix-spurious-AD-flags-in-some-DNS-replies-from-local.patch deleted file mode 100644 index 3271a5f3af..0000000000 --- a/package/network/services/dnsmasq/patches/0006-Fix-spurious-AD-flags-in-some-DNS-replies-from-local.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 6f7812d97bc8f87004c0a5069c6c94c64af78106 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Tue, 23 Oct 2018 23:54:44 +0100 -Subject: [PATCH 06/11] Fix spurious AD flags in some DNS replies from local - config. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/rfc1035.c | 42 ++++++++++++++++++++++++------------------ - 1 file changed, 24 insertions(+), 18 deletions(-) - ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1330,7 +1330,7 @@ size_t answer_request(struct dns_header - { - if (t->class == qclass && hostname_isequal(name, t->name)) - { -- ans = 1; -+ ans = 1, sec_data = 0; - if (!dryrun) - { - unsigned long ttl = daemon->local_ttl; -@@ -1370,7 +1370,7 @@ size_t answer_request(struct dns_header - addr.addr.rcode.rcode = NOTIMP; - log_query(F_CONFIG | F_RCODE, name, &addr, NULL); - } -- ans = 1; -+ ans = 1, sec_data = 0; - } - } - } -@@ -1725,7 +1725,7 @@ size_t answer_request(struct dns_header - } - else if (is_name_synthetic(flag, name, &addr)) - { -- ans = 1; -+ ans = 1, sec_data = 0; - if (!dryrun) - { - log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL); -@@ -1763,25 +1763,27 @@ size_t answer_request(struct dns_header - for (rec = daemon->mxnames; rec; rec = rec->next) - if (!rec->issrv && hostname_isequal(name, rec->name)) - { -- ans = found = 1; -- if (!dryrun) -- { -- int offset; -- log_query(F_CONFIG | F_RRNAME, name, NULL, ""); -- if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, -- &offset, T_MX, C_IN, "sd", rec->weight, rec->target)) -- { -- anscount++; -- if (rec->target) -- rec->offset = offset; -- } -- } -+ ans = found = 1; -+ sec_data = 0; -+ if (!dryrun) -+ { -+ int offset; -+ log_query(F_CONFIG | F_RRNAME, name, NULL, ""); -+ if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, -+ &offset, T_MX, C_IN, "sd", rec->weight, rec->target)) -+ { -+ anscount++; -+ if (rec->target) -+ rec->offset = offset; -+ } -+ } - } - - if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && - cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR)) - { - ans = 1; -+ sec_data = 0; - if (!dryrun) - { - log_query(F_CONFIG | F_RRNAME, name, NULL, ""); -@@ -1802,6 +1804,7 @@ size_t answer_request(struct dns_header - if (rec->issrv && hostname_isequal(name, rec->name)) - { - found = ans = 1; -+ sec_data = 0; - if (!dryrun) - { - int offset; -@@ -1838,6 +1841,7 @@ size_t answer_request(struct dns_header - if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_')))) - { - ans = 1; -+ sec_data = 0; - if (!dryrun) - log_query(F_CONFIG | F_NEG, name, NULL, NULL); - } -@@ -1850,6 +1854,7 @@ size_t answer_request(struct dns_header - if (hostname_isequal(name, na->name)) - { - ans = 1; -+ sec_data = 0; - if (!dryrun) - { - log_query(F_CONFIG | F_RRNAME, name, NULL, ""); -@@ -1862,11 +1867,12 @@ size_t answer_request(struct dns_header - } - - if (qtype == T_MAILB) -- ans = 1, nxdomain = 1; -+ ans = 1, nxdomain = 1, sec_data = 0; - - if (qtype == T_SOA && option_bool(OPT_FILTER)) - { -- ans = 1; -+ ans = 1; -+ sec_data = 0; - if (!dryrun) - log_query(F_CONFIG | F_NEG, name, &addr, NULL); - } diff --git a/package/network/services/dnsmasq/patches/0007-Do-not-rely-on-dead-code-elimination-use-array-inste.patch b/package/network/services/dnsmasq/patches/0007-Do-not-rely-on-dead-code-elimination-use-array-inste.patch deleted file mode 100644 index 55ea917c39..0000000000 --- a/package/network/services/dnsmasq/patches/0007-Do-not-rely-on-dead-code-elimination-use-array-inste.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 24b87607c1353e94689e8a2190571ab3f3b36f31 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= -Date: Wed, 24 Oct 2018 22:30:18 +0100 -Subject: [PATCH 07/11] Do not rely on dead code elimination, use array - instead. Make options bits derived from size and count. Use size of option - bits and last supported bit in computation. No new change would be required - when new options are added. Just change OPT_LAST constant. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/dnsmasq.h | 11 +++++++---- - src/option.c | 10 ++-------- - 2 files changed, 9 insertions(+), 12 deletions(-) - ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -200,9 +200,6 @@ struct event_desc { - #define EC_MISC 5 - #define EC_INIT_OFFSET 10 - --/* Trust the compiler dead-code eliminator.... */ --#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32))) -- - #define OPT_BOGUSPRIV 0 - #define OPT_FILTER 1 - #define OPT_LOG 2 -@@ -264,6 +261,12 @@ struct event_desc { - #define OPT_UBUS 58 - #define OPT_LAST 59 - -+#define OPTION_BITS (sizeof(unsigned int)*8) -+#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) -+#define option_var(x) (daemon->options[(x) / OPTION_BITS]) -+#define option_val(x) ((1u) << ((x) % OPTION_BITS)) -+#define option_bool(x) (option_var(x) & option_val(x)) -+ - /* extra flags for my_syslog, we use a couple of facilities since they are known - not to occupy the same bits as priorities, no matter how syslog.h is set up. */ - #define MS_TFTP LOG_USER -@@ -978,7 +981,7 @@ extern struct daemon { - config file arguments. All set (including defaults) - in option.c */ - -- unsigned int options, options2; -+ unsigned int options[OPTION_SIZE]; - struct resolvc default_resolv, *resolv_files; - time_t last_resolv; - char *servers_file; ---- a/src/option.c -+++ b/src/option.c -@@ -1490,18 +1490,12 @@ static int parse_dhcp_opt(char *errstr, - - void set_option_bool(unsigned int opt) - { -- if (opt < 32) -- daemon->options |= 1u << opt; -- else -- daemon->options2 |= 1u << (opt - 32); -+ option_var(opt) |= option_val(opt); - } - - void reset_option_bool(unsigned int opt) - { -- if (opt < 32) -- daemon->options &= ~(1u << opt); -- else -- daemon->options2 &= ~(1u << (opt - 32)); -+ option_var(opt) &= ~(option_val(opt)); - } - - static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only) diff --git a/package/network/services/dnsmasq/patches/0008-Fix-Makefile-lines-generating-UBUS-linker-config.patch b/package/network/services/dnsmasq/patches/0008-Fix-Makefile-lines-generating-UBUS-linker-config.patch deleted file mode 100644 index 91b465fd1c..0000000000 --- a/package/network/services/dnsmasq/patches/0008-Fix-Makefile-lines-generating-UBUS-linker-config.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 3a5a84cdd1488bad118eeac72d09a60299bca744 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Wed, 31 Oct 2018 21:30:13 +0000 -Subject: [PATCH 08/11] Fix Makefile lines generating UBUS linker config. - -If arg2 of pkg-wrapper is "--copy", then arg1 is NOT the name of -the package manager (--copy doesn't invoke it) it's a secondary -config string that inhibts the copy if found. This patch allows that -to be the empty string, for unconditional copy, and modifies the -ubus linker config to use it. It worked by coincidence before, because -there was no config string called "pkg-config". - -Signed-off-by: Kevin Darbyshire-Bryant ---- - Makefile | 2 +- - bld/pkg-wrapper | 14 ++++++++------ - 2 files changed, 9 insertions(+), 7 deletions(-) - ---- a/Makefile -+++ b/Makefile -@@ -53,7 +53,7 @@ top?=$(CURDIR) - - dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1` - dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1` --ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS $(PKG_CONFIG) --copy -lubox -lubus` -+ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS "" --copy -lubox -lubus` - idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn` - idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn` - idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2` ---- a/bld/pkg-wrapper -+++ b/bld/pkg-wrapper -@@ -11,23 +11,25 @@ in=`cat` - - if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \ - echo $in | grep $search >/dev/null 2>&1; then --# Nasty, nasty, in --copy, arg 2 is another config to search for, use with NO_GMP -+# Nasty, nasty, in --copy, arg 2 (if non-empty) is another config to search for, used with NO_GMP - if [ $op = "--copy" ]; then -- if grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \ -- echo $in | grep $pkg >/dev/null 2>&1; then -+ if [ -z "$pkg" ]; then -+ pkg="$*" -+ elif grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \ -+ echo $in | grep $pkg >/dev/null 2>&1; then - pkg="" - else - pkg="$*" - fi - elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \ -- echo $in | grep ${search}_STATIC >/dev/null 2>&1; then -+ echo $in | grep ${search}_STATIC >/dev/null 2>&1; then - pkg=`$pkg --static $op $*` - else - pkg=`$pkg $op $*` - fi -- -+ - if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \ -- echo $in | grep ${search}_STATIC >/dev/null 2>&1; then -+ echo $in | grep ${search}_STATIC >/dev/null 2>&1; then - if [ $op = "--libs" ] || [ $op = "--copy" ]; then - echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic" - else diff --git a/package/network/services/dnsmasq/patches/0009-Revert-68f6312d4bae30b78daafcd6f51dc441b8685b1e.patch b/package/network/services/dnsmasq/patches/0009-Revert-68f6312d4bae30b78daafcd6f51dc441b8685b1e.patch deleted file mode 100644 index ff9ddd842c..0000000000 --- a/package/network/services/dnsmasq/patches/0009-Revert-68f6312d4bae30b78daafcd6f51dc441b8685b1e.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 122392e0b352507cabb9e982208d35d2e56902e0 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Wed, 31 Oct 2018 22:24:02 +0000 -Subject: [PATCH 09/11] Revert 68f6312d4bae30b78daafcd6f51dc441b8685b1e - -The above is intended to increase robustness, but actually does the -opposite. The problem is that by ignoring SERVFAIL messages and hoping -for a better answer from another of the servers we've forwarded to, -we become vulnerable in the case that one or more of the configured -servers is down or not responding. - -Consider the case that a domain is indeed BOGUS, and we've send the -query to n servers. With 68f6312d4bae30b78daafcd6f51dc441b8685b1e -we ignore the first n-1 SERVFAIL replies, and only return the -final n'th answer to the client. Now, if one of the servers we are -forwarding to is down, then we won't get all n replies, and the -client will never get an answer! This is a far more likely scenario -than a temporary SERVFAIL from only one of a set of notionally identical -servers, so, on the ground of robustness, we have to believe -any SERVFAIL answers we get, and return them to the client. - -The client could be using the same recursive servers we are, -so it should, in theory, retry on SERVFAIL anyway. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/forward.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/src/forward.c -+++ b/src/forward.c -@@ -957,8 +957,7 @@ void reply_query(int fd, int family, tim - we get a good reply from another server. Kill it when we've - had replies from all to avoid filling the forwarding table when - everything is broken */ -- if (forward->forwardall == 0 || --forward->forwardall == 1 || -- (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL)) -+ if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED) - { - int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0; - diff --git a/package/network/services/dnsmasq/patches/0010-Remove-the-NO_FORK-compile-time-option-and-support-f.patch b/package/network/services/dnsmasq/patches/0010-Remove-the-NO_FORK-compile-time-option-and-support-f.patch deleted file mode 100644 index 1110d4c5fa..0000000000 --- a/package/network/services/dnsmasq/patches/0010-Remove-the-NO_FORK-compile-time-option-and-support-f.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 48d12f14c9c0fc8cf943b52774c3892517dd72d4 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Fri, 2 Nov 2018 21:55:04 +0000 -Subject: [PATCH 10/11] Remove the NO_FORK compile-time option, and support for - uclinux. - -In an era where everything has an MMU, this looks like -an anachronism, and it adds to (Ok, multiplies!) the -combinatorial explosion of compile-time options. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - CHANGELOG | 6 ++++++ - src/config.h | 21 ++------------------- - src/dnsmasq.c | 14 -------------- - src/option.c | 4 +--- - 4 files changed, 9 insertions(+), 36 deletions(-) - ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -11,6 +11,12 @@ version 2.81 - This fix passes cache entries back from the TCP child process to - the main server process, and fixes the problem. - -+ Remove the NO_FORK compile-time option, and support for uclinux. -+ In an era where everything has an MMU, this looks like -+ an anachronism, and it adds to (Ok, multiplies!) the -+ combinatorial explosion of compile-time options. Thanks to -+ Kevin Darbyshire-Bryant for the patch. -+ - - version 2.80 - Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method ---- a/src/config.h -+++ b/src/config.h -@@ -239,27 +239,13 @@ HAVE_SOCKADDR_SA_LEN - defined if struct sockaddr has sa_len field (*BSD) - */ - --/* Must precede __linux__ since uClinux defines __linux__ too. */ --#if defined(__uClinux__) --#define HAVE_LINUX_NETWORK --#define HAVE_GETOPT_LONG --#undef HAVE_SOCKADDR_SA_LEN --/* Never use fork() on uClinux. Note that this is subtly different from the -- --keep-in-foreground option, since it also suppresses forking new -- processes for TCP connections and disables the call-a-script on leasechange -- system. It's intended for use on MMU-less kernels. */ --#define NO_FORK -- --#elif defined(__UCLIBC__) -+#if defined(__UCLIBC__) - #define HAVE_LINUX_NETWORK - #if defined(__UCLIBC_HAS_GNU_GETOPT__) || \ - ((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21)) - # define HAVE_GETOPT_LONG - #endif - #undef HAVE_SOCKADDR_SA_LEN --#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__) --# define NO_FORK --#endif - #if defined(__UCLIBC_HAS_IPV6__) - # ifndef IPV6_V6ONLY - # define IPV6_V6ONLY 26 -@@ -328,7 +314,7 @@ HAVE_SOCKADDR_SA_LEN - #define HAVE_DHCP - #endif - --#if defined(NO_SCRIPT) || defined(NO_FORK) -+#if defined(NO_SCRIPT) - #undef HAVE_SCRIPT - #undef HAVE_LUASCRIPT - #endif -@@ -372,9 +358,6 @@ static char *compile_opts = - #ifdef HAVE_BROKEN_RTC - "no-RTC " - #endif --#ifdef NO_FORK --"no-MMU " --#endif - #ifndef HAVE_DBUS - "no-" - #endif ---- a/src/dnsmasq.c -+++ b/src/dnsmasq.c -@@ -485,7 +485,6 @@ int main (int argc, char **argv) - if (chdir("/") != 0) - die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC); - --#ifndef NO_FORK - if (!option_bool(OPT_NO_FORK)) - { - pid_t pid; -@@ -525,7 +524,6 @@ int main (int argc, char **argv) - if (pid != 0) - _exit(0); - } --#endif - - /* write pidfile _after_ forking ! */ - if (daemon->runfile) -@@ -1628,12 +1626,10 @@ static int set_dns_listeners(time_t now) - - } - --#ifndef NO_FORK - if (!option_bool(OPT_DEBUG)) - for (i = 0; i < MAX_PROCS; i++) - if (daemon->tcp_pipes[i] != -1) - poll_listen(daemon->tcp_pipes[i], POLLIN); --#endif - - return wait; - } -@@ -1643,9 +1639,7 @@ static void check_dns_listeners(time_t n - struct serverfd *serverfdp; - struct listener *listener; - int i; --#ifndef NO_FORK - int pipefd[2]; --#endif - - for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) - if (poll_check(serverfdp->fd, POLLIN)) -@@ -1657,7 +1651,6 @@ static void check_dns_listeners(time_t n - poll_check(daemon->randomsocks[i].fd, POLLIN)) - reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now); - --#ifndef NO_FORK - /* Races. The child process can die before we read all of the data from the - pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the - process, and tcp_pipes to -1 and close the FD when we read the last -@@ -1674,7 +1667,6 @@ static void check_dns_listeners(time_t n - close(daemon->tcp_pipes[i]); - daemon->tcp_pipes[i] = -1; - } --#endif - - for (listener = daemon->listeners; listener; listener = listener->next) - { -@@ -1768,7 +1760,6 @@ static void check_dns_listeners(time_t n - shutdown(confd, SHUT_RDWR); - while (retry_send(close(confd))); - } --#ifndef NO_FORK - else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0) - { - close(pipefd[1]); /* parent needs read pipe end. */ -@@ -1791,7 +1782,6 @@ static void check_dns_listeners(time_t n - /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */ - daemon->log_id += TCP_MAX_QUERIES; - } --#endif - else - { - unsigned char *buff; -@@ -1811,7 +1801,6 @@ static void check_dns_listeners(time_t n - auth_dns = 0; - } - --#ifndef NO_FORK - /* Arrange for SIGALRM after CHILD_LIFETIME seconds to - terminate the process. */ - if (!option_bool(OPT_DEBUG)) -@@ -1820,7 +1809,6 @@ static void check_dns_listeners(time_t n - close(pipefd[0]); /* close read end in child. */ - daemon->pipe_to_parent = pipefd[1]; - } --#endif - - /* start with no upstream connections. */ - for (s = daemon->servers; s; s = s->next) -@@ -1846,13 +1834,11 @@ static void check_dns_listeners(time_t n - shutdown(s->tcpfd, SHUT_RDWR); - while (retry_send(close(s->tcpfd))); - } --#ifndef NO_FORK - if (!option_bool(OPT_DEBUG)) - { - flush_log(); - _exit(0); - } --#endif - } - } - } ---- a/src/option.c -+++ b/src/option.c -@@ -1828,9 +1828,7 @@ static int one_opt(int option, char *arg - /* Sorry about the gross pre-processor abuse */ - case '6': /* --dhcp-script */ - case LOPT_LUASCRIPT: /* --dhcp-luascript */ --# if defined(NO_FORK) -- ret_err(_("cannot run scripts under uClinux")); --# elif !defined(HAVE_SCRIPT) -+# if !defined(HAVE_SCRIPT) - ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts")); - # else - if (option == LOPT_LUASCRIPT) diff --git a/package/network/services/dnsmasq/patches/0011-Free-config-file-values-on-parsing-errors.patch b/package/network/services/dnsmasq/patches/0011-Free-config-file-values-on-parsing-errors.patch deleted file mode 100644 index 3ba971fe72..0000000000 --- a/package/network/services/dnsmasq/patches/0011-Free-config-file-values-on-parsing-errors.patch +++ /dev/null @@ -1,1199 +0,0 @@ -From 59e470381f84f2fdf0640c7bc67827f3f0c64784 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= -Date: Fri, 2 Nov 2018 22:39:39 +0000 -Subject: [PATCH 11/11] Free config file values on parsing errors. - -This time I have a little bit more controversal patches. But I think -still useful. They fixes memory leaks that might occur in some cases. -Most dnsmasq errors is fatal, so it does not matter. But some are not. -Some parts are reloaded on SIGHUP signal, so it might leak more than once. - -Some example when it changes the failures. Use dhcp-options file with -this content: - -tag:error,vendor:redhat -option:ntp-server,1.2.3.4.5 -option6:ntp-server,[:::] - -Is not fatal and dnsmasq will start. On each reload command, it would -leak some memory. I validated it using valgrind --leak-check=full -dnsmasq -d. This patch fixes it. It introduces something that might be -considered constructor and destructor of selected structures. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/option.c | 533 ++++++++++++++++++++++++++++++++++----------------- - 1 file changed, 352 insertions(+), 181 deletions(-) - ---- a/src/option.c -+++ b/src/option.c -@@ -577,14 +577,15 @@ static void *opt_malloc(size_t size) - return ret; - } - --static char *opt_string_alloc(char *cp) -+static char *opt_string_alloc(const char *cp) - { - char *ret = NULL; -+ size_t len; - -- if (cp && strlen(cp) != 0) -+ if (cp && (len = strlen(cp)) != 0) - { -- ret = opt_malloc(strlen(cp)+1); -- strcpy(ret, cp); -+ ret = opt_malloc(len+1); -+ memcpy(ret, cp, len+1); - - /* restore hidden metachars */ - unhide_metas(ret); -@@ -759,6 +760,8 @@ static void do_usage(void) - } - - #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0) -+#define ret_err_free(x,m) do { strcpy(errstr, (x)); free((m)); return 0; } while (0) -+#define goto_err(x) do { strcpy(errstr, (x)); goto on_error; } while (0) - - static char *parse_mysockaddr(char *arg, union mysockaddr *addr) - { -@@ -904,6 +907,8 @@ static struct server *add_rev4(struct in - p += sprintf(p, "%d.", (a >> 24) & 0xff); - break; - default: -+ free(serv->domain); -+ free(serv); - return NULL; - } - -@@ -958,6 +963,97 @@ static char *set_prefix(char *arg) - return arg; - } - -+static struct dhcp_netid * -+dhcp_netid_create(const char *net, struct dhcp_netid *next) -+{ -+ struct dhcp_netid *tt; -+ tt = opt_malloc(sizeof (struct dhcp_netid)); -+ tt->net = opt_string_alloc(net); -+ tt->next = next; -+ return tt; -+} -+ -+static void dhcp_netid_free(struct dhcp_netid *nid) -+{ -+ while (nid) -+ { -+ struct dhcp_netid *tmp = nid; -+ nid = nid->next; -+ free(tmp->net); -+ free(tmp); -+ } -+} -+ -+/* Parse one or more tag:s before parameters. -+ * Moves arg to the end of tags. */ -+static struct dhcp_netid * dhcp_tags(char **arg) -+{ -+ struct dhcp_netid *id = NULL; -+ -+ while (is_tag_prefix(*arg)) -+ { -+ char *comma = split(*arg); -+ id = dhcp_netid_create((*arg)+4, id); -+ *arg = comma; -+ }; -+ if (!*arg) -+ { -+ dhcp_netid_free(id); -+ id = NULL; -+ } -+ return id; -+} -+ -+static void dhcp_netid_list_free(struct dhcp_netid_list *netid) -+{ -+ while (netid) -+ { -+ struct dhcp_netid_list *tmplist = netid; -+ netid = netid->next; -+ dhcp_netid_free(tmplist->list); -+ free(tmplist); -+ } -+} -+ -+static void dhcp_config_free(struct dhcp_config *config) -+{ -+ if (config) -+ { -+ struct hwaddr_config *hwaddr = config->hwaddr; -+ while (hwaddr) -+ { -+ struct hwaddr_config *tmp = hwaddr; -+ hwaddr = hwaddr->next; -+ free(tmp); -+ } -+ dhcp_netid_list_free(config->netid); -+ if (config->flags & CONFIG_CLID) -+ free(config->clid); -+ free(config); -+ } -+} -+ -+static void dhcp_context_free(struct dhcp_context *ctx) -+{ -+ if (ctx) -+ { -+ dhcp_netid_free(ctx->filter); -+ free(ctx->netid.net); -+ free(ctx->template_interface); -+ free(ctx); -+ } -+} -+ -+static void dhcp_opt_free(struct dhcp_opt *opt) -+{ -+ if (opt->flags & DHOPT_VENDOR) -+ free(opt->u.vendor_class); -+ dhcp_netid_free(opt->netid); -+ free(opt->val); -+ free(opt); -+} -+ -+ - /* This is too insanely large to keep in-line in the switch */ - static int parse_dhcp_opt(char *errstr, char *arg, int flags) - { -@@ -965,7 +1061,6 @@ static int parse_dhcp_opt(char *errstr, - char lenchar = 0, *cp; - int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots; - char *comma = NULL; -- struct dhcp_netid *np = NULL; - u16 opt_len = 0; - int is6 = 0; - int option_ok = 0; -@@ -1052,14 +1147,9 @@ static int parse_dhcp_opt(char *errstr, - } - else - { -- new->netid = opt_malloc(sizeof (struct dhcp_netid)); - /* allow optional "net:" or "tag:" for consistency */ -- if (is_tag_prefix(arg)) -- new->netid->net = opt_string_alloc(arg+4); -- else -- new->netid->net = opt_string_alloc(set_prefix(arg)); -- new->netid->next = np; -- np = new->netid; -+ const char *name = (is_tag_prefix(arg)) ? arg+4 : set_prefix(arg); -+ new->netid = dhcp_netid_create(name, new->netid); - } - - arg = comma; -@@ -1069,7 +1159,7 @@ static int parse_dhcp_opt(char *errstr, - if (is6) - { - if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE)) -- ret_err(_("unsupported encapsulation for IPv6 option")); -+ goto_err(_("unsupported encapsulation for IPv6 option")); - - if (opt_len == 0 && - !(new->flags & DHOPT_RFC3925)) -@@ -1083,7 +1173,7 @@ static int parse_dhcp_opt(char *errstr, - - /* option may be missing with rfc3925 match */ - if (!option_ok) -- ret_err(_("bad dhcp-option")); -+ goto_err(_("bad dhcp-option")); - - if (comma) - { -@@ -1151,10 +1241,10 @@ static int parse_dhcp_opt(char *errstr, - is_string = is_dec = is_hex = 0; - - if (!is6 && (!is_addr || dots == 0)) -- ret_err(_("bad IP address")); -+ goto_err(_("bad IP address")); - - if (is6 && !is_addr6) -- ret_err(_("bad IPv6 address")); -+ goto_err(_("bad IPv6 address")); - } - /* or names */ - else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING)) -@@ -1247,7 +1337,7 @@ static int parse_dhcp_opt(char *errstr, - comma = split(cp); - slash = split_chr(cp, '/'); - if (!inet_pton(AF_INET, cp, &in)) -- ret_err(_("bad IPv4 address")); -+ goto_err(_("bad IPv4 address")); - if (!slash) - { - memcpy(op, &in, INADDRSZ); -@@ -1292,8 +1382,8 @@ static int parse_dhcp_opt(char *errstr, - op += IN6ADDRSZ; - continue; - } -- -- ret_err(_("bad IPv6 address")); -+ -+ goto_err(_("bad IPv6 address")); - } - new->len = op - new->val; - } -@@ -1320,7 +1410,7 @@ static int parse_dhcp_opt(char *errstr, - if (strcmp (arg, ".") != 0) - { - if (!(dom = canonicalise_opt(arg))) -- ret_err(_("bad domain in dhcp-option")); -+ goto_err(_("bad domain in dhcp-option")); - - domlen = strlen(dom) + 2; - } -@@ -1414,7 +1504,7 @@ static int parse_dhcp_opt(char *errstr, - { - char *dom = canonicalise_opt(arg); - if (!dom) -- ret_err(_("bad domain in dhcp-option")); -+ goto_err(_("bad domain in dhcp-option")); - - newp = opt_malloc(len + strlen(dom) + 2); - -@@ -1452,14 +1542,14 @@ static int parse_dhcp_opt(char *errstr, - ((new->len > 255) || - (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) || - (new->len > 250 && (new->flags & DHOPT_RFC3925)))) -- ret_err(_("dhcp-option too long")); -+ goto_err(_("dhcp-option too long")); - - if (flags == DHOPT_MATCH) - { - if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) || - !new->netid || - new->netid->next) -- ret_err(_("illegal dhcp-match")); -+ goto_err(_("illegal dhcp-match")); - - if (is6) - { -@@ -1484,6 +1574,9 @@ static int parse_dhcp_opt(char *errstr, - } - - return 1; -+on_error: -+ dhcp_opt_free(new); -+ return 0; - } - - #endif -@@ -1498,6 +1591,16 @@ void reset_option_bool(unsigned int opt) - option_var(opt) &= ~(option_val(opt)); - } - -+static void server_list_free(struct server *list) -+{ -+ while (list) -+ { -+ struct server *tmp = list; -+ list = list->next; -+ free(tmp); -+ } -+} -+ - static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only) - { - int i; -@@ -1679,13 +1782,13 @@ static int one_opt(int option, char *arg - /* has subnet+len */ - err = parse_mysockaddr(arg, &new->addr); - if (err) -- ret_err(err); -+ ret_err_free(err, new); - if (!atoi_check(end, &new->mask)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - new->addr_used = 1; - } - else if (!atoi_check(arg, &new->mask)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - - daemon->add_subnet4 = new; - -@@ -1697,15 +1800,15 @@ static int one_opt(int option, char *arg - /* has subnet+len */ - err = parse_mysockaddr(comma, &new->addr); - if (err) -- ret_err(err); -+ ret_err_free(err, new); - if (!atoi_check(end, &new->mask)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - new->addr_used = 1; - } - else - { - if (!atoi_check(comma, &new->mask)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - } - - daemon->add_subnet6 = new; -@@ -1912,7 +2015,10 @@ static int one_opt(int option, char *arg - else if (strcmp(fam, "6") == 0) - new->addr.sa.sa_family = AF_INET6; - else -- ret_err(gen_err); -+ { -+ free(new->name); -+ ret_err_free(gen_err, new); -+ } - } - } - new->next = daemon->authinterface; -@@ -2077,7 +2183,7 @@ static int one_opt(int option, char *arg - - arg = split(netpart); - if (!atoi_check(netpart, &msize)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - else if (inet_pton(AF_INET, comma, &new->start)) - { - int mask = (1 << (32 - msize)) - 1; -@@ -2090,18 +2196,18 @@ static int one_opt(int option, char *arg - { - if (!(new->prefix = canonicalise_opt(arg)) || - strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN) -- ret_err(_("bad prefix")); -+ ret_err_free(_("bad prefix"), new); - } - else if (strcmp(arg, "local") != 0 || - (msize != 8 && msize != 16 && msize != 24)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - else - { - /* generate the equivalent of - local=/xxx.yyy.zzz.in-addr.arpa/ */ - struct server *serv = add_rev4(new->start, msize); - if (!serv) -- ret_err(_("bad prefix")); -+ ret_err_free(_("bad prefix"), new); - - serv->flags |= SERV_NO_ADDR; - -@@ -2130,17 +2236,17 @@ static int one_opt(int option, char *arg - setaddr6part(&new->end6, addrpart | mask); - - if (msize < 64) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - else if (arg) - { - if (option != 's') - { - if (!(new->prefix = canonicalise_opt(arg)) || - strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN) -- ret_err(_("bad prefix")); -+ ret_err_free(_("bad prefix"), new); - } - else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - else - { - /* generate the equivalent of -@@ -2159,7 +2265,7 @@ static int one_opt(int option, char *arg - } - } - else -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - } - else - { -@@ -2173,7 +2279,7 @@ static int one_opt(int option, char *arg - if (!arg) - new->end.s_addr = new->start.s_addr; - else if (!inet_pton(AF_INET, arg, &new->end)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - } - else if (inet_pton(AF_INET6, comma, &new->start6)) - { -@@ -2181,16 +2287,16 @@ static int one_opt(int option, char *arg - if (!arg) - memcpy(&new->end6, &new->start6, IN6ADDRSZ); - else if (!inet_pton(AF_INET6, arg, &new->end6)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - } - else -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - - if (option != 's' && prefstr) - { - if (!(new->prefix = canonicalise_opt(prefstr)) || - strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN) -- ret_err(_("bad prefix")); -+ ret_err_free(_("bad prefix"), new); - } - } - -@@ -2352,7 +2458,7 @@ static int one_opt(int option, char *arg - #endif - } - else -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - - new->used = 0; - if (option == 'a') -@@ -2423,7 +2529,10 @@ static int one_opt(int option, char *arg - { - newlist->flags |= SERV_LITERAL_ADDRESS; - if (!(newlist->flags & SERV_TYPE)) -- ret_err(gen_err); -+ { -+ server_list_free(newlist); -+ ret_err(gen_err); -+ } - } - else if (option == LOPT_NO_REBIND) - newlist->flags |= SERV_NO_REBIND; -@@ -2440,7 +2549,10 @@ static int one_opt(int option, char *arg - { - char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags); - if (err) -- ret_err(err); -+ { -+ server_list_free(newlist); -+ ret_err(err); -+ } - } - - serv = newlist; -@@ -2776,21 +2888,19 @@ static int one_opt(int option, char *arg - { - if (is_tag_prefix(arg)) - { -- struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid)); -- tt->net = opt_string_alloc(arg+4); -- tt->next = new->filter; - /* ignore empty tag */ -- if (tt->net) -- new->filter = tt; -+ if (arg[4]) -+ new->filter = dhcp_netid_create(arg+4, new->filter); - } - else - { - if (new->netid.net) -- ret_err(_("only one tag allowed")); -- else if (strstr(arg, "set:") == arg) -- new->netid.net = opt_string_alloc(arg+4); -+ { -+ dhcp_context_free(new); -+ ret_err(_("only one tag allowed")); -+ } - else -- new->netid.net = opt_string_alloc(arg); -+ new->netid.net = opt_string_alloc(set_prefix(arg)); - } - arg = comma; - } -@@ -2806,7 +2916,10 @@ static int one_opt(int option, char *arg - break; - - if (k < 2) -- ret_err(_("bad dhcp-range")); -+ { -+ dhcp_context_free(new); -+ ret_err(_("bad dhcp-range")); -+ } - - if (inet_pton(AF_INET, a[0], &new->start)) - { -@@ -2818,7 +2931,10 @@ static int one_opt(int option, char *arg - else if (strcmp(a[1], "proxy") == 0) - new->flags |= CONTEXT_PROXY; - else if (!inet_pton(AF_INET, a[1], &new->end)) -- ret_err(_("bad dhcp-range")); -+ { -+ dhcp_context_free(new); -+ ret_err(_("bad dhcp-range")); -+ } - - if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr)) - { -@@ -2833,7 +2949,10 @@ static int one_opt(int option, char *arg - new->flags |= CONTEXT_NETMASK; - leasepos = 3; - if (!is_same_net(new->start, new->end, new->netmask)) -- ret_err(_("inconsistent DHCP range")); -+ { -+ dhcp_context_free(new); -+ ret_err(_("inconsistent DHCP range")); -+ } - - - if (k >= 4 && strchr(a[3], '.') && -@@ -2847,6 +2966,8 @@ static int one_opt(int option, char *arg - #ifdef HAVE_DHCP6 - else if (inet_pton(AF_INET6, a[0], &new->start6)) - { -+ const char *err = NULL; -+ - new->flags |= CONTEXT_V6; - new->prefix = 64; /* default */ - new->end6 = new->start6; -@@ -2892,19 +3013,24 @@ static int one_opt(int option, char *arg - } - } - -- if (new->prefix != 64) -+ if (new->prefix > 64) - { - if (new->flags & CONTEXT_RA) -- ret_err(_("prefix length must be exactly 64 for RA subnets")); -+ err=(_("prefix length must be exactly 64 for RA subnets")); - else if (new->flags & CONTEXT_TEMPLATE) -- ret_err(_("prefix length must be exactly 64 for subnet constructors")); -+ err=(_("prefix length must be exactly 64 for subnet constructors")); - } -- -- if (new->prefix < 64) -- ret_err(_("prefix length must be at least 64")); -+ else if (new->prefix < 64) -+ err=(_("prefix length must be at least 64")); - -- if (!is_same_net6(&new->start6, &new->end6, new->prefix)) -- ret_err(_("inconsistent DHCPv6 range")); -+ if (!err && !is_same_net6(&new->start6, &new->end6, new->prefix)) -+ err=(_("inconsistent DHCPv6 range")); -+ -+ if (err) -+ { -+ dhcp_context_free(new); -+ ret_err(err); -+ } - - /* dhcp-range=:: enables DHCP stateless on any interface */ - if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE)) -@@ -2915,7 +3041,10 @@ static int one_opt(int option, char *arg - struct in6_addr zero; - memset(&zero, 0, sizeof(zero)); - if (!is_same_net6(&zero, &new->start6, new->prefix)) -- ret_err(_("prefix must be zero with \"constructor:\" argument")); -+ { -+ dhcp_context_free(new); -+ ret_err(_("prefix must be zero with \"constructor:\" argument")); -+ } - } - - if (addr6part(&new->start6) > addr6part(&new->end6)) -@@ -2927,12 +3056,18 @@ static int one_opt(int option, char *arg - } - #endif - else -- ret_err(_("bad dhcp-range")); -+ { -+ dhcp_context_free(new); -+ ret_err(_("bad dhcp-range")); -+ } - - if (leasepos < k) - { - if (leasepos != k-1) -- ret_err(_("bad dhcp-range")); -+ { -+ dhcp_context_free(new); -+ ret_err(_("bad dhcp-range")); -+ } - - if (strcmp(a[leasepos], "infinite") == 0) - new->lease_time = 0xffffffff; -@@ -2971,7 +3106,7 @@ static int one_opt(int option, char *arg - break; - - if (*cp || (leasepos+1 < k)) -- ret_err(_("bad dhcp-range")); -+ ret_err_free(_("bad dhcp-range"), new); - - new->lease_time = atoi(a[leasepos]) * fac; - /* Leases of a minute or less confuse -@@ -2998,6 +3133,7 @@ static int one_opt(int option, char *arg - new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0; - new->hwaddr = NULL; - new->netid = NULL; -+ new->clid = NULL; - - if ((a[0] = arg)) - for (k = 1; k < 7; k++) -@@ -3028,7 +3164,10 @@ static int one_opt(int option, char *arg - } - - if (len == -1) -- ret_err(_("bad hex constant")); -+ { -+ dhcp_config_free(new); -+ ret_err(_("bad hex constant")); -+ } - else if ((new->clid = opt_malloc(len))) - { - new->flags |= CONFIG_CLID; -@@ -3040,17 +3179,17 @@ static int one_opt(int option, char *arg - /* dhcp-host has strange backwards-compat needs. */ - else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg) - { -- struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid)); - struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list)); -- newtag->net = opt_malloc(strlen(arg + 4) + 1); - newlist->next = new->netid; - new->netid = newlist; -- newlist->list = newtag; -- strcpy(newtag->net, arg+4); -- unhide_metas(newtag->net); -+ newlist->list = dhcp_netid_create(arg+4, NULL); - } - else if (strstr(arg, "tag:") == arg) -- ret_err(_("cannot match tags in --dhcp-host")); -+ { -+ -+ dhcp_config_free(new); -+ ret_err(_("cannot match tags in --dhcp-host")); -+ } - #ifdef HAVE_DHCP6 - else if (arg[0] == '[' && arg[strlen(arg)-1] == ']') - { -@@ -3058,7 +3197,10 @@ static int one_opt(int option, char *arg - arg++; - - if (!inet_pton(AF_INET6, arg, &new->addr6)) -- ret_err(_("bad IPv6 address")); -+ { -+ dhcp_config_free(new); -+ ret_err(_("bad IPv6 address")); -+ } - - for (i= 0; i < 8; i++) - if (new->addr6.s6_addr[i] != 0) -@@ -3076,10 +3218,13 @@ static int one_opt(int option, char *arg - struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config)); - if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX, - &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1) -- ret_err(_("bad hex constant")); -+ { -+ free(newhw); -+ dhcp_config_free(new); -+ ret_err(_("bad hex constant")); -+ } - else - { -- - newhw->next = new->hwaddr; - new->hwaddr = newhw; - } -@@ -3156,7 +3301,10 @@ static int one_opt(int option, char *arg - { - if (!(new->hostname = canonicalise_opt(a[j])) || - !legal_hostname(new->hostname)) -- ret_err(_("bad DHCP host name")); -+ { -+ dhcp_config_free(new); -+ ret_err(_("bad DHCP host name")); -+ } - - new->flags |= CONFIG_NAME; - new->domain = strip_hostname(new->hostname); -@@ -3209,10 +3357,7 @@ static int one_opt(int option, char *arg - } - else - { -- struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid)); -- newtag->net = opt_malloc(len - 3); -- strcpy(newtag->net, arg+4); -- unhide_metas(newtag->net); -+ struct dhcp_netid *newtag = dhcp_netid_create(arg+4, NULL); - - if (strstr(arg, "set:") == arg) - { -@@ -3229,7 +3374,7 @@ static int one_opt(int option, char *arg - else - { - new->set = NULL; -- free(newtag); -+ dhcp_netid_free(newtag); - break; - } - } -@@ -3238,7 +3383,11 @@ static int one_opt(int option, char *arg - } - - if (!new->set) -- ret_err(_("bad tag-if")); -+ { -+ dhcp_netid_free(new->tag); -+ dhcp_netid_list_free(new->set); -+ ret_err_free(_("bad tag-if"), new); -+ } - - break; - } -@@ -3281,19 +3430,12 @@ static int one_opt(int option, char *arg - - case 'M': /* --dhcp-boot */ - { -- struct dhcp_netid *id = NULL; -- while (is_tag_prefix(arg)) -- { -- struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid)); -- newid->next = id; -- id = newid; -- comma = split(arg); -- newid->net = opt_string_alloc(arg+4); -- arg = comma; -- }; -+ struct dhcp_netid *id = dhcp_tags(&arg); - -- if (!arg) -- ret_err(gen_err); -+ if (!id) -+ { -+ ret_err(gen_err); -+ } - else - { - char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL; -@@ -3339,19 +3481,12 @@ static int one_opt(int option, char *arg - - case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */ - { -- struct dhcp_netid *id = NULL; -- while (is_tag_prefix(arg)) -- { -- struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid)); -- newid->next = id; -- id = newid; -- comma = split(arg); -- newid->net = opt_string_alloc(arg+4); -- arg = comma; -- }; -+ struct dhcp_netid *id = dhcp_tags(&arg); - -- if (!arg) -- ret_err(gen_err); -+ if (!id) -+ { -+ ret_err(gen_err); -+ } - else - { - struct delay_config *new; -@@ -3376,19 +3511,13 @@ static int one_opt(int option, char *arg - - new->netid = NULL; - new->opt = 10; /* PXE_MENU_PROMPT */ -- -- while (is_tag_prefix(arg)) -- { -- struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid)); -- comma = split(arg); -- nn->next = new->netid; -- new->netid = nn; -- nn->net = opt_string_alloc(arg+4); -- arg = comma; -- } -+ new->netid = dhcp_tags(&arg); - -- if (!arg) -- ret_err(gen_err); -+ if (!new->netid) -+ { -+ dhcp_opt_free(new); -+ ret_err(gen_err); -+ } - else - { - comma = split(arg); -@@ -3424,17 +3553,8 @@ static int one_opt(int option, char *arg - new->netid = NULL; - new->sname = NULL; - new->server.s_addr = 0; -+ new->netid = dhcp_tags(&arg); - -- while (is_tag_prefix(arg)) -- { -- struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid)); -- comma = split(arg); -- nn->next = new->netid; -- new->netid = nn; -- nn->net = opt_string_alloc(arg+4); -- arg = comma; -- } -- - if (arg && (comma = split(arg))) - { - for (i = 0; CSA[i]; i++) -@@ -3511,7 +3631,10 @@ static int one_opt(int option, char *arg - unhide_metas(comma); - new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type); - if (new->hwaddr_len == -1) -- ret_err(gen_err); -+ { -+ free(new->netid.net); -+ ret_err_free(gen_err, new); -+ } - else - { - new->next = daemon->dhcp_macs; -@@ -3528,7 +3651,7 @@ static int one_opt(int option, char *arg - - if (!(comma = split(arg)) || - !atoi_check16(comma, &new->class)) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - - new->tag.net = opt_string_alloc(set_prefix(arg)); - new->next = daemon->prefix_classes; -@@ -3550,7 +3673,7 @@ static int one_opt(int option, char *arg - struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor)); - - if (!(comma = split(arg))) -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - - new->netid.net = opt_string_alloc(set_prefix(arg)); - /* check for hex string - must digits may include : must not have nothing else, -@@ -3560,7 +3683,10 @@ static int one_opt(int option, char *arg - if ((comma = split(arg))) - { - if (option != 'U' || strstr(arg, "enterprise:") != arg) -- ret_err(gen_err); -+ { -+ free(new->netid.net); -+ ret_err_free(gen_err, new); -+ } - else - new->enterprise = atoi(arg+11); - } -@@ -3662,14 +3788,8 @@ static int one_opt(int option, char *arg - } - - while (arg) { -- struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid)); - comma = split(arg); -- member->next = list; -- list = member; -- if (is_tag_prefix(arg)) -- member->net = opt_string_alloc(arg+4); -- else -- member->net = opt_string_alloc(arg); -+ list = dhcp_netid_create(is_tag_prefix(arg) ? arg+4 :arg, list); - arg = comma; - } - -@@ -3683,7 +3803,7 @@ static int one_opt(int option, char *arg - struct addr_list *new = opt_malloc(sizeof(struct addr_list)); - comma = split(arg); - if (!(inet_pton(AF_INET, arg, &new->addr) > 0)) -- ret_err(_("bad dhcp-proxy address")); -+ ret_err_free(_("bad dhcp-proxy address"), new); - new->next = daemon->override_relays; - daemon->override_relays = new; - arg = comma; -@@ -3709,7 +3829,10 @@ static int one_opt(int option, char *arg - } - #endif - else -- ret_err(_("Bad dhcp-relay")); -+ { -+ free(new->interface); -+ ret_err_free(_("Bad dhcp-relay"), new); -+ } - - break; - } -@@ -3749,8 +3872,11 @@ static int one_opt(int option, char *arg - arg = split(comma); - if (!atoi_check(comma, &new->interval) || - (arg && !atoi_check(arg, &new->lifetime))) -+ { - err: -- ret_err(_("bad RA-params")); -+ free(new->name); -+ ret_err_free(_("bad RA-params"), new); -+ } - - new->next = daemon->ra_interfaces; - daemon->ra_interfaces = new; -@@ -3799,7 +3925,7 @@ err: - (!(inet_pton(AF_INET, dash, &new->end) > 0) || - !is_same_net(new->in, new->end, new->mask) || - ntohl(new->in.s_addr) > ntohl(new->end.s_addr))) -- ret_err(_("invalid alias range")); -+ ret_err_free(_("invalid alias range"), new); - - break; - } -@@ -3832,7 +3958,7 @@ err: - else if (strcmp(arg, "6") == 0) - new->family = AF_INET6; - else -- ret_err(gen_err); -+ ret_err_free(gen_err, new); - } - new->intr = opt_string_alloc(comma); - break; -@@ -3864,11 +3990,19 @@ err: - alias = canonicalise_opt(arg); - - if (!alias || !target) -- ret_err(_("bad CNAME")); -+ { -+ free(target); -+ free(alias); -+ ret_err(_("bad CNAME")); -+ } - - for (new = daemon->cnames; new; new = new->next) - if (hostname_isequal(new->alias, alias)) -- ret_err(_("duplicate CNAME")); -+ { -+ free(target); -+ free(alias); -+ ret_err(_("duplicate CNAME")); -+ } - new = opt_malloc(sizeof(struct cname)); - new->next = daemon->cnames; - daemon->cnames = new; -@@ -3891,7 +4025,11 @@ err: - - if (!(dom = canonicalise_opt(arg)) || - (comma && !(target = canonicalise_opt(comma)))) -- ret_err(_("bad PTR record")); -+ { -+ free(dom); -+ free(target); -+ ret_err(_("bad PTR record")); -+ } - else - { - new = opt_malloc(sizeof(struct ptr_record)); -@@ -3909,7 +4047,7 @@ err: - int k = 0; - struct naptr *new; - int order, pref; -- char *name, *replace = NULL; -+ char *name=NULL, *replace = NULL; - - if ((a[0] = arg)) - for (k = 1; k < 7; k++) -@@ -3922,7 +4060,11 @@ err: - !atoi_check16(a[1], &order) || - !atoi_check16(a[2], &pref) || - (k == 7 && !(replace = canonicalise_opt(a[6])))) -- ret_err(_("bad NAPTR record")); -+ { -+ free(name); -+ free(replace); -+ ret_err(_("bad NAPTR record")); -+ } - else - { - new = opt_malloc(sizeof(struct naptr)); -@@ -3944,22 +4086,26 @@ err: - struct txt_record *new; - size_t len = 0; - char *data; -- int val; -+ int class; - - comma = split(arg); - data = split(comma); - - new = opt_malloc(sizeof(struct txt_record)); -- new->next = daemon->rr; -- daemon->rr = new; -+ new->name = NULL; - -- if (!atoi_check(comma, &val) || -+ if (!atoi_check(comma, &class) || - !(new->name = canonicalise_opt(arg)) || - (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U)) -- ret_err(_("bad RR record")); -- -- new->class = val; -+ { -+ free(new->name); -+ ret_err_free(_("bad RR record"), new); -+ } -+ - new->len = 0; -+ new->class = class; -+ new->next = daemon->rr; -+ daemon->rr = new; - - if (data) - { -@@ -4011,14 +4157,14 @@ err: - comma = split(arg); - - new = opt_malloc(sizeof(struct txt_record)); -- new->next = daemon->txt; -- daemon->txt = new; - new->class = C_IN; - new->stat = 0; - - if (!(new->name = canonicalise_opt(arg))) -- ret_err(_("bad TXT record")); -+ ret_err_free(_("bad TXT record"), new); - -+ new->next = daemon->txt; -+ daemon->txt = new; - len = comma ? strlen(comma) : 0; - len += (len/255) + 1; /* room for extra counts */ - new->txt = p = opt_malloc(len); -@@ -4065,24 +4211,32 @@ err: - arg = comma; - comma = split(arg); - if (!(target = canonicalise_opt(arg))) -- ret_err(_("bad SRV target")); -+ ret_err_free(_("bad SRV target"), name); - - if (comma) - { - arg = comma; - comma = split(arg); - if (!atoi_check16(arg, &port)) -- ret_err(_("invalid port number")); -+ { -+ free(name); -+ ret_err_free(_("invalid port number"), target); -+ } - - if (comma) - { - arg = comma; - comma = split(arg); - if (!atoi_check16(arg, &priority)) -- ret_err(_("invalid priority")); -- -+ { -+ free(name); -+ ret_err_free(_("invalid priority"), target); -+ } - if (comma && !atoi_check16(comma, &weight)) -- ret_err(_("invalid weight")); -+ { -+ free(name); -+ ret_err_free(_("invalid weight"), target); -+ } - } - } - } -@@ -4101,13 +4255,15 @@ err: - - case LOPT_HOST_REC: /* --host-record */ - { -- struct host_record *new = opt_malloc(sizeof(struct host_record)); -- memset(new, 0, sizeof(struct host_record)); -- new->ttl = -1; -+ struct host_record *new; - - if (!arg || !(comma = split(arg))) - ret_err(_("Bad host-record")); - -+ new = opt_malloc(sizeof(struct host_record)); -+ memset(new, 0, sizeof(struct host_record)); -+ new->ttl = -1; -+ - while (arg) - { - struct all_addr addr; -@@ -4126,10 +4282,19 @@ err: - { - int nomem; - char *canon = canonicalise(arg, &nomem); -- struct name_list *nl = opt_malloc(sizeof(struct name_list)); -+ struct name_list *nl; - if (!canon) -- ret_err(_("Bad name in host-record")); -+ { -+ struct name_list *tmp = new->names, *next; -+ for (tmp = new->names; tmp; tmp = next) -+ { -+ next = tmp->next; -+ free(tmp); -+ } -+ ret_err_free(_("Bad name in host-record"), new); -+ } - -+ nl = opt_malloc(sizeof(struct name_list)); - nl->name = canon; - /* keep order, so that PTR record goes to first name */ - nl->next = NULL; -@@ -4179,6 +4344,7 @@ err: - int len; - - new->class = C_IN; -+ new->name = NULL; - - if ((comma = split(arg)) && (algo = split(comma))) - { -@@ -4203,7 +4369,7 @@ err: - !atoi_check8(algo, &new->algo) || - !atoi_check8(digest, &new->digest_type) || - !(new->name = canonicalise_opt(arg))) -- ret_err(_("bad trust anchor")); -+ ret_err_free(_("bad trust anchor"), new); - - /* Upper bound on length */ - len = (2*strlen(keyhex))+1; -@@ -4217,7 +4383,10 @@ err: - else - cp++; - if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len, NULL, NULL)) == -1) -- ret_err(_("bad HEX in trust anchor")); -+ { -+ free(new->name); -+ ret_err_free(_("bad HEX in trust anchor"), new); -+ } - - new->next = daemon->ds; - daemon->ds = new; -@@ -4686,8 +4855,8 @@ void read_opts(int argc, char **argv, ch - size_t argbuf_size = MAXDNAME; - char *argbuf = opt_malloc(argbuf_size); - char *buff = opt_malloc(MAXDNAME); -- int option, conffile_opt = '7', testmode = 0; -- char *arg, *conffile = CONFFILE; -+ int option, testmode = 0; -+ char *arg, *conffile = NULL; - - opterr = 0; - -@@ -4796,7 +4965,8 @@ void read_opts(int argc, char **argv, ch - } - else if (option == 'C') - { -- conffile_opt = 0; /* file must exist */ -+ if (conffile) -+ free(conffile); - conffile = opt_string_alloc(arg); - } - else -@@ -4814,10 +4984,11 @@ void read_opts(int argc, char **argv, ch - - if (conffile) - { -- one_file(conffile, conffile_opt); -- if (conffile_opt == 0) -- free(conffile); -+ one_file(conffile, 0); -+ free(conffile); - } -+ else -+ one_file(CONFFILE, '7'); - - /* port might not be known when the address is parsed - fill in here */ - if (daemon->servers) diff --git a/package/network/services/dnsmasq/patches/0012-option-fix-non-DHCPv6-build-error.patch b/package/network/services/dnsmasq/patches/0012-option-fix-non-DHCPv6-build-error.patch deleted file mode 100644 index 983cb1402e..0000000000 --- a/package/network/services/dnsmasq/patches/0012-option-fix-non-DHCPv6-build-error.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 061eb8599636bb360e0b7fa5986935b86db39497 Mon Sep 17 00:00:00 2001 -From: Kevin Darbyshire-Bryant -Date: Mon, 10 Dec 2018 10:07:33 +0000 -Subject: [PATCH] option: fix non DHCPv6 build error - -option.c: In function 'dhcp_context_free': -option.c:1042:15: error: 'struct dhcp_context' has no member named 'template_interface' - free(ctx->template_interface); - ^~ - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/option.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/src/option.c -+++ b/src/option.c -@@ -1039,7 +1039,9 @@ static void dhcp_context_free(struct dhc - { - dhcp_netid_free(ctx->filter); - free(ctx->netid.net); -+#ifdef HAVE_DHCP6 - free(ctx->template_interface); -+#endif - free(ctx); - } - } diff --git a/package/network/services/dnsmasq/patches/0013-ipset-fix-ternary-order-swap.patch b/package/network/services/dnsmasq/patches/0013-ipset-fix-ternary-order-swap.patch deleted file mode 100644 index e93e6240a8..0000000000 --- a/package/network/services/dnsmasq/patches/0013-ipset-fix-ternary-order-swap.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 46de5d4954b470db155098001cffc357b51e50f4 Mon Sep 17 00:00:00 2001 -From: Kevin Darbyshire-Bryant -Date: Wed, 12 Dec 2018 11:35:12 +0000 -Subject: [PATCH] ipset fix ternary order swap - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/ipset.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/src/ipset.c -+++ b/src/ipset.c -@@ -120,7 +120,7 @@ static int new_add_to_ipset(const char * - struct my_nfgenmsg *nfg; - struct my_nlattr *nested[2]; - uint8_t proto; -- int addrsz = (af == AF_INET6) ? INADDRSZ : IN6ADDRSZ; -+ int addrsz = (af == AF_INET6) ? IN6ADDRSZ : INADDRSZ; - - if (strlen(setname) >= IPSET_MAXNAMELEN) - { diff --git a/package/network/services/dnsmasq/patches/0014-option-dhcp-boot-dhcp-reply-delay-tag-fixes.patch b/package/network/services/dnsmasq/patches/0014-option-dhcp-boot-dhcp-reply-delay-tag-fixes.patch deleted file mode 100644 index 7712a32827..0000000000 --- a/package/network/services/dnsmasq/patches/0014-option-dhcp-boot-dhcp-reply-delay-tag-fixes.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 668b45c29c38d440c8fce4bc994c56910adc3919 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= -Date: Fri, 14 Dec 2018 17:03:08 +0100 -Subject: [PATCH] Fix required tags in few places - -Some locations were incorrectly changed to require always tags, else -dnsmasq will not start. Fix dhcp-boot, dhcp-reply-delay and pxe-prompt. ---- - src/option.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/src/option.c -+++ b/src/option.c -@@ -3434,7 +3434,7 @@ static int one_opt(int option, char *arg - { - struct dhcp_netid *id = dhcp_tags(&arg); - -- if (!id) -+ if (!arg) - { - ret_err(gen_err); - } -@@ -3485,7 +3485,7 @@ static int one_opt(int option, char *arg - { - struct dhcp_netid *id = dhcp_tags(&arg); - -- if (!id) -+ if (!arg) - { - ret_err(gen_err); - } -@@ -3515,7 +3515,7 @@ static int one_opt(int option, char *arg - new->opt = 10; /* PXE_MENU_PROMPT */ - new->netid = dhcp_tags(&arg); - -- if (!new->netid) -+ if (!arg) - { - dhcp_opt_free(new); - ret_err(gen_err); diff --git a/package/network/services/dnsmasq/patches/0015-fix-build-with-libnettle-3.5.patch b/package/network/services/dnsmasq/patches/0015-fix-build-with-libnettle-3.5.patch deleted file mode 100644 index 901585aa82..0000000000 --- a/package/network/services/dnsmasq/patches/0015-fix-build-with-libnettle-3.5.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/src/crypto.c b/src/crypto.c -index ebb871e..94d0332 100644 ---- a/src/crypto.c -+++ b/src/crypto.c -@@ -275,6 +275,10 @@ static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len - static struct ecc_point *key_256 = NULL, *key_384 = NULL; - static mpz_t x, y; - static struct dsa_signature *sig_struct; -+#if NETTLE_VERSION_MAJOR == 3 && NETTLE_VERSION_MINOR < 4 -+#define nettle_get_secp_256r1() (&nettle_secp_256r1) -+#define nettle_get_secp_384r1() (&nettle_secp_384r1) -+#endif - - if (!sig_struct) - { -@@ -294,7 +298,7 @@ static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len - if (!(key_256 = whine_malloc(sizeof(struct ecc_point)))) - return 0; - -- nettle_ecc_point_init(key_256, &nettle_secp_256r1); -+ nettle_ecc_point_init(key_256, nettle_get_secp_256r1()); - } - - key = key_256; -@@ -307,7 +311,7 @@ static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len - if (!(key_384 = whine_malloc(sizeof(struct ecc_point)))) - return 0; - -- nettle_ecc_point_init(key_384, &nettle_secp_384r1); -+ nettle_ecc_point_init(key_384, nettle_get_secp_256r1()); - } - - key = key_384; diff --git a/package/network/services/dnsmasq/patches/100-remove-old-runtime-kernel-support.patch b/package/network/services/dnsmasq/patches/100-remove-old-runtime-kernel-support.patch new file mode 100644 index 0000000000..8a4e58cee7 --- /dev/null +++ b/package/network/services/dnsmasq/patches/100-remove-old-runtime-kernel-support.patch @@ -0,0 +1,178 @@ +From 7df4c681678612d196b4e1eec24963d181fdb28a Mon Sep 17 00:00:00 2001 +From: Kevin Darbyshire-Bryant +Date: Sun, 5 Apr 2020 17:18:23 +0100 +Subject: [PATCH] drop runtime old kernel support + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/dnsmasq.c | 4 ---- + src/dnsmasq.h | 5 +--- + src/ipset.c | 64 ++++----------------------------------------------- + src/netlink.c | 3 +-- + src/util.c | 19 --------------- + 5 files changed, 6 insertions(+), 89 deletions(-) + +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -94,10 +94,6 @@ int main (int argc, char **argv) + + read_opts(argc, argv, compile_opts); + +-#ifdef HAVE_LINUX_NETWORK +- daemon->kernel_version = kernel_version(); +-#endif +- + if (daemon->edns_pktsz < PACKETSZ) + daemon->edns_pktsz = PACKETSZ; + +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1110,7 +1110,7 @@ extern struct daemon { + int inotifyfd; + #endif + #if defined(HAVE_LINUX_NETWORK) +- int netlinkfd, kernel_version; ++ int netlinkfd; + #elif defined(HAVE_BSD_NETWORK) + int dhcp_raw_fd, dhcp_icmp_fd, routefd; + #endif +@@ -1290,9 +1290,6 @@ int read_write(int fd, unsigned char *pa + void close_fds(long max_fd, int spare1, int spare2, int spare3); + int wildcard_match(const char* wildcard, const char* match); + int wildcard_matchn(const char* wildcard, const char* match, int num); +-#ifdef HAVE_LINUX_NETWORK +-int kernel_version(void); +-#endif + + /* log.c */ + void die(char *message, char *arg1, int exit_code) ATTRIBUTE_NORETURN; +--- a/src/ipset.c ++++ b/src/ipset.c +@@ -70,7 +70,7 @@ struct my_nfgenmsg { + + #define NL_ALIGN(len) (((len)+3) & ~(3)) + static const struct sockaddr_nl snl = { .nl_family = AF_NETLINK }; +-static int ipset_sock, old_kernel; ++static int ipset_sock; + static char *buffer; + + static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data) +@@ -85,12 +85,7 @@ static inline void add_attr(struct nlmsg + + void ipset_init(void) + { +- old_kernel = (daemon->kernel_version < KERNEL_VERSION(2,6,32)); +- +- if (old_kernel && (ipset_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1) +- return; +- +- if (!old_kernel && ++ if ( + (buffer = safe_malloc(BUFF_SZ)) && + (ipset_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER)) != -1 && + (bind(ipset_sock, (struct sockaddr *)&snl, sizeof(snl)) != -1)) +@@ -147,65 +142,14 @@ static int new_add_to_ipset(const char * + return errno == 0 ? 0 : -1; + } + +- +-static int old_add_to_ipset(const char *setname, const union all_addr *ipaddr, int remove) +-{ +- socklen_t size; +- struct ip_set_req_adt_get { +- unsigned op; +- unsigned version; +- union { +- char name[IPSET_MAXNAMELEN]; +- uint16_t index; +- } set; +- char typename[IPSET_MAXNAMELEN]; +- } req_adt_get; +- struct ip_set_req_adt { +- unsigned op; +- uint16_t index; +- uint32_t ip; +- } req_adt; +- +- if (strlen(setname) >= sizeof(req_adt_get.set.name)) +- { +- errno = ENAMETOOLONG; +- return -1; +- } +- +- req_adt_get.op = 0x10; +- req_adt_get.version = 3; +- strcpy(req_adt_get.set.name, setname); +- size = sizeof(req_adt_get); +- if (getsockopt(ipset_sock, SOL_IP, 83, &req_adt_get, &size) < 0) +- return -1; +- req_adt.op = remove ? 0x102 : 0x101; +- req_adt.index = req_adt_get.set.index; +- req_adt.ip = ntohl(ipaddr->addr4.s_addr); +- if (setsockopt(ipset_sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0) +- return -1; +- +- return 0; +-} +- +- +- + int add_to_ipset(const char *setname, const union all_addr *ipaddr, int flags, int remove) + { + int ret = 0, af = AF_INET; + + if (flags & F_IPV6) +- { + af = AF_INET6; +- /* old method only supports IPv4 */ +- if (old_kernel) +- { +- errno = EAFNOSUPPORT ; +- ret = -1; +- } +- } +- +- if (ret != -1) +- ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove); ++ ++ ret = new_add_to_ipset(setname, ipaddr, af, remove); + + if (ret == -1) + my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno)); +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -82,8 +82,7 @@ void netlink_init(void) + } + + if (daemon->netlinkfd == -1 || +- (daemon->kernel_version >= KERNEL_VERSION(2,6,30) && +- setsockopt(daemon->netlinkfd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(opt)) == -1) || ++ (setsockopt(daemon->netlinkfd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(opt)) == -1) || + getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == -1) + die(_("cannot create netlink socket: %s"), NULL, EC_MISC); + +--- a/src/util.c ++++ b/src/util.c +@@ -786,22 +786,3 @@ int wildcard_matchn(const char* wildcard + + return (!num) || (*wildcard == *match); + } +- +-#ifdef HAVE_LINUX_NETWORK +-int kernel_version(void) +-{ +- struct utsname utsname; +- int version; +- char *split; +- +- if (uname(&utsname) < 0) +- die(_("failed to find kernel version: %s"), NULL, EC_MISC); +- +- split = strtok(utsname.release, "."); +- version = (split ? atoi(split) : 0); +- split = strtok(NULL, "."); +- version = version * 256 + (split ? atoi(split) : 0); +- split = strtok(NULL, "."); +- return version * 256 + (split ? atoi(split) : 0); +-} +-#endif diff --git a/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch b/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch deleted file mode 100644 index f2681e3993..0000000000 --- a/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch +++ /dev/null @@ -1,64 +0,0 @@ ---- a/src/ipset.c -+++ b/src/ipset.c -@@ -22,7 +22,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -72,7 +71,7 @@ struct my_nfgenmsg { - - #define NL_ALIGN(len) (((len)+3) & ~(3)) - static const struct sockaddr_nl snl = { .nl_family = AF_NETLINK }; --static int ipset_sock, old_kernel; -+static int ipset_sock; - static char *buffer; - - static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data) -@@ -87,25 +86,7 @@ static inline void add_attr(struct nlmsg - - void ipset_init(void) - { -- struct utsname utsname; -- int version; -- char *split; -- -- if (uname(&utsname) < 0) -- die(_("failed to find kernel version: %s"), NULL, EC_MISC); -- -- split = strtok(utsname.release, "."); -- version = (split ? atoi(split) : 0); -- split = strtok(NULL, "."); -- version = version * 256 + (split ? atoi(split) : 0); -- split = strtok(NULL, "."); -- version = version * 256 + (split ? atoi(split) : 0); -- old_kernel = (version < KERNEL_VERSION(2,6,32)); -- -- if (old_kernel && (ipset_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1) -- return; -- -- if (!old_kernel && -+ if ( - (buffer = safe_malloc(BUFF_SZ)) && - (ipset_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER)) != -1 && - (bind(ipset_sock, (struct sockaddr *)&snl, sizeof(snl)) != -1)) -@@ -211,16 +192,9 @@ int add_to_ipset(const char *setname, co - if (flags & F_IPV6) - { - af = AF_INET6; -- /* old method only supports IPv4 */ -- if (old_kernel) -- { -- errno = EAFNOSUPPORT ; -- ret = -1; -- } - } - -- if (ret != -1) -- ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove); -+ ret = new_add_to_ipset(setname, ipaddr, af, remove); - - if (ret == -1) - my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno)); diff --git a/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch b/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch deleted file mode 100644 index 2501079b3f..0000000000 --- a/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch +++ /dev/null @@ -1,18 +0,0 @@ -dnsmasq: fix warning with poll.h include on musl - -Warning is: - #warning redirecting incorrect #include to - -Signed-off-by: Kevin Darbyshire-Bryant - ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -95,7 +95,7 @@ typedef unsigned long long u64; - #if defined(HAVE_SOLARIS_NETWORK) - # include - #endif --#include -+#include - #include - #include - #include diff --git a/package/network/services/dnsmasq/patches/910-mini-ttl.patch b/package/network/services/dnsmasq/patches/910-mini-ttl.patch index 84fce3b8d2..74b5ca11b5 100644 --- a/package/network/services/dnsmasq/patches/910-mini-ttl.patch +++ b/package/network/services/dnsmasq/patches/910-mini-ttl.patch @@ -1,62 +1,71 @@ diff --git a/src/dnsmasq.h b/src/dnsmasq.h ---- a/src/dnsmasq.h 2018-10-19 02:21:55.000000000 +0800 -+++ b/src/dnsmasq.h 2020-01-13 10:38:16.940067371 +0800 -@@ -1017,7 +1017,7 @@ +--- a/src/dnsmasq.h 2020-03-16 04:31:43.337573724 +0800 ++++ b/src/dnsmasq.h 2020-03-16 04:32:07.138008046 +0800 +@@ -1029,7 +1029,7 @@ int max_logs; /* queue limit */ int cachesize, ftabsize; int port, query_port, min_port, max_port; - unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl; -+ unsigned long local_ttl, neg_ttl, min_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl; ++ unsigned long local_ttl, neg_ttl, max_ttl, min_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl; char *dns_client_id; struct hostsfile *addn_hosts; struct dhcp_context *dhcp, *dhcp6; diff --git a/src/option.c b/src/option.c ---- a/src/option.c 2018-10-19 02:21:55.000000000 +0800 -+++ b/src/option.c 2020-01-13 17:21:13.925164926 +0800 -@@ -106,6 +106,7 @@ +--- a/src/option.c 2020-03-16 04:33:35.999622026 +0800 ++++ b/src/option.c 2020-03-16 04:40:44.839289942 +0800 +@@ -105,6 +105,7 @@ + #define LOPT_TAG_IF 294 #define LOPT_PROXY 295 #define LOPT_GEN_NAMES 296 ++#define LOPT_MINTTL 361 #define LOPT_MAXTTL 297 -+#define LOPT_MINTTL 397 #define LOPT_NO_REBIND 298 #define LOPT_LOC_REBND 299 - #define LOPT_ADD_MAC 300 -@@ -282,6 +283,7 @@ +@@ -167,7 +168,7 @@ + #define LOPT_IGNORE_CLID 358 + #define LOPT_SINGLE_PORT 359 + #define LOPT_SCRIPT_TIME 360 +- ++ + #ifdef HAVE_GETOPT_LONG + static const struct option opts[] = + #else +@@ -284,6 +285,7 @@ + { "dhcp-name-match", 1, 0, LOPT_NAME_MATCH }, { "dhcp-broadcast", 2, 0, LOPT_BROADCAST }, { "neg-ttl", 1, 0, LOPT_NEGTTL }, - { "max-ttl", 1, 0, LOPT_MAXTTL }, + { "min-ttl", 1, 0, LOPT_MINTTL }, + { "max-ttl", 1, 0, LOPT_MAXTTL }, { "min-cache-ttl", 1, 0, LOPT_MINCTTL }, { "max-cache-ttl", 1, 0, LOPT_MAXCTTL }, - { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT }, -@@ -411,6 +413,7 @@ +@@ -410,6 +412,7 @@ + { 't', ARG_ONE, "", gettext_noop("Specify default target in an MX record."), NULL }, { 'T', ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL }, { LOPT_NEGTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL }, - { LOPT_MAXTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL }, + { LOPT_MINTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for minimum TTL to send to clients."), NULL }, + { LOPT_MAXTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL }, { LOPT_MAXCTTL, ARG_ONE, "", gettext_noop("Specify time-to-live ceiling for cache."), NULL }, { LOPT_MINCTTL, ARG_ONE, "", gettext_noop("Specify time-to-live floor for cache."), NULL }, - { 'u', ARG_ONE, "", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER }, -@@ -2747,6 +2750,7 @@ +@@ -2812,6 +2815,7 @@ + case 'T': /* --local-ttl */ case LOPT_NEGTTL: /* --neg-ttl */ - case LOPT_MAXTTL: /* --max-ttl */ + case LOPT_MINTTL: /* --min-ttl */ + case LOPT_MAXTTL: /* --max-ttl */ case LOPT_MINCTTL: /* --min-cache-ttl */ case LOPT_MAXCTTL: /* --max-cache-ttl */ - case LOPT_AUTHTTL: /* --auth-ttl */ -@@ -2759,6 +2763,8 @@ +@@ -2823,6 +2827,8 @@ + ret_err(gen_err); + else if (option == LOPT_NEGTTL) daemon->neg_ttl = (unsigned long)ttl; - else if (option == LOPT_MAXTTL) - daemon->max_ttl = (unsigned long)ttl; + else if (option == LOPT_MINTTL) + daemon->min_ttl = (unsigned long)ttl; + else if (option == LOPT_MAXTTL) + daemon->max_ttl = (unsigned long)ttl; else if (option == LOPT_MINCTTL) - { - if (ttl > TTL_FLOOR_LIMIT) diff --git a/src/rfc1035.c b/src/rfc1035.c ---- a/src/rfc1035.c 2018-10-19 02:21:55.000000000 +0800 -+++ b/src/rfc1035.c 2020-01-13 17:12:25.455445871 +0800 +--- a/src/rfc1035.c 2020-03-08 23:56:19.000000000 +0800 ++++ b/src/rfc1035.c 2020-03-16 04:41:50.888215364 +0800 @@ -664,11 +664,20 @@ GETSHORT(aqtype, p1); GETSHORT(aqclass, p1); @@ -81,7 +90,7 @@ diff --git a/src/rfc1035.c b/src/rfc1035.c GETSHORT(ardlen, p1); endrr = p1+ardlen; -@@ -755,11 +764,20 @@ +@@ -760,11 +769,20 @@ GETSHORT(aqtype, p1); GETSHORT(aqclass, p1); GETLONG(attl, p1); diff --git a/package/network/services/dnsmasq/patches/996-dnsmasq-filter-aaaa.patch b/package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa.patch similarity index 70% rename from package/network/services/dnsmasq/patches/996-dnsmasq-filter-aaaa.patch rename to package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa.patch index 4a6dd6cf3c..430f1cd0db 100644 --- a/package/network/services/dnsmasq/patches/996-dnsmasq-filter-aaaa.patch +++ b/package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa.patch @@ -13,13 +13,13 @@ diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 1896a64..e10d6c4 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h -@@ -259,7 +259,8 @@ struct event_desc { - #define OPT_TFTP_APREF_MAC 56 - #define OPT_RAPID_COMMIT 57 - #define OPT_UBUS 58 --#define OPT_LAST 59 -+#define OPT_FILTER_AAAA 59 -+#define OPT_LAST 60 +@@ -268,7 +268,8 @@ + #define OPT_IGNORE_CLID 59 + #define OPT_SINGLE_PORT 60 + #define OPT_LEASE_RENEW 61 +-#define OPT_LAST 62 ++#define OPT_FILTER_AAAA 62 ++#define OPT_LAST 63 #define OPTION_BITS (sizeof(unsigned int)*8) #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) @@ -27,26 +27,26 @@ diff --git a/src/option.c b/src/option.c index d8c57d6..1cc65bf 100644 --- a/src/option.c +++ b/src/option.c -@@ -166,6 +166,7 @@ struct myoption { - #define LOPT_UBUS 354 - #define LOPT_NAME_MATCH 355 - #define LOPT_CAA 356 -+#define LOPT_FILTER_AAAA 357 - +@@ -168,6 +168,7 @@ + #define LOPT_IGNORE_CLID 358 + #define LOPT_SINGLE_PORT 359 + #define LOPT_SCRIPT_TIME 360 ++#define LOPT_FILTER_AAAA 362 + #ifdef HAVE_GETOPT_LONG static const struct option opts[] = -@@ -337,6 +338,7 @@ static const struct myoption opts[] = - { "dhcp-rapid-commit", 0, 0, LOPT_RAPID_COMMIT }, +@@ -341,6 +342,7 @@ { "dumpfile", 1, 0, LOPT_DUMPFILE }, { "dumpmask", 1, 0, LOPT_DUMPMASK }, + { "dhcp-ignore-clid", 0, 0, LOPT_IGNORE_CLID }, + { "filter-aaaa", 0, 0, LOPT_FILTER_AAAA }, { NULL, 0, 0, 0 } }; -@@ -515,6 +517,7 @@ static struct { - { LOPT_RAPID_COMMIT, OPT_RAPID_COMMIT, NULL, gettext_noop("Enables DHCPv4 Rapid Commit option."), NULL }, +@@ -521,6 +523,7 @@ { LOPT_DUMPFILE, ARG_ONE, "", gettext_noop("Path to debug packet dump file"), NULL }, { LOPT_DUMPMASK, ARG_ONE, "", gettext_noop("Mask which packets to dump"), NULL }, + { LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL }, + { LOPT_FILTER_AAAA, OPT_FILTER_AAAA, NULL, gettext_noop("Filter all AAAA requests."), NULL }, { 0, 0, NULL, NULL, NULL } }; @@ -55,7 +55,7 @@ diff --git a/src/rfc1035.c b/src/rfc1035.c index 24d08c1..1594962 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c -@@ -1970,6 +1970,15 @@ size_t answer_request(struct dns_header +@@ -1959,6 +1959,15 @@ } } diff --git a/package/network/services/dropbear/Config.in b/package/network/services/dropbear/Config.in index 61a04ec876..3de4189e08 100644 --- a/package/network/services/dropbear/Config.in +++ b/package/network/services/dropbear/Config.in @@ -8,7 +8,7 @@ config DROPBEAR_CURVE25519 This enables the following key exchange algorithm: curve25519-sha256@libssh.org - Increases binary size by about 8 kB uncompressed (MIPS). + Increases binary size by about 4 kB (MIPS). config DROPBEAR_ECC bool "Elliptic curve cryptography (ECC)" @@ -49,6 +49,24 @@ config DROPBEAR_ECC_FULL Increases binary size by about 4 kB (MIPS). +config DROPBEAR_ED25519 + bool "Ed25519 support" + default n + help + This enables the following public key algorithm: + ssh-ed25519 + + Increases binary size by about 12 kB (MIPS). + +config DROPBEAR_CHACHA20POLY1305 + bool "Chacha20-Poly1305 support" + default y + help + This enables the following authenticated encryption cipher: + chacha20-poly1305@openssh.com + + Increases binary size by about 4 kB (MIPS). + config DROPBEAR_ZLIB bool "Enable compression" default n diff --git a/package/network/services/dropbear/Makefile b/package/network/services/dropbear/Makefile index 59b4f54954..8de0739d56 100644 --- a/package/network/services/dropbear/Makefile +++ b/package/network/services/dropbear/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dropbear PKG_VERSION:=2019.78 -PKG_RELEASE:=3 +PKG_RELEASE:=5 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:= \ @@ -29,6 +29,7 @@ PKG_FIXUP:=autoreconf PKG_CONFIG_DEPENDS:= \ CONFIG_TARGET_INIT_PATH CONFIG_DROPBEAR_ECC CONFIG_DROPBEAR_ECC_FULL \ CONFIG_DROPBEAR_CURVE25519 CONFIG_DROPBEAR_ZLIB \ + CONFIG_DROPBEAR_ED25519 CONFIG_DROPBEAR_CHACHA20POLY1305 \ CONFIG_DROPBEAR_UTMP CONFIG_DROPBEAR_PUTUTLINE \ CONFIG_DROPBEAR_DBCLIENT @@ -63,6 +64,7 @@ define Package/dropbear/description endef define Package/dropbear/conffiles +$(if $(CONFIG_DROPBEAR_ED25519),/etc/dropbear/dropbear_ed25519_host_key) $(if $(CONFIG_DROPBEAR_ECC),/etc/dropbear/dropbear_ecdsa_host_key) /etc/dropbear/dropbear_rsa_host_key /etc/config/dropbear @@ -110,6 +112,12 @@ define Build/Configure $(PKG_BUILD_DIR)/localoptions.h; \ done + echo '#define DROPBEAR_ED25519 $(if $(CONFIG_DROPBEAR_ED25519),1,0)' >> \ + $(PKG_BUILD_DIR)/localoptions.h + + echo '#define DROPBEAR_CHACHA20POLY1305 $(if $(CONFIG_DROPBEAR_CHACHA20POLY1305),1,0)' >> \ + $(PKG_BUILD_DIR)/localoptions.h + # remove protocol idented software version number $(ESED) 's,^(#define LOCAL_IDENT) .*$$$$,\1 "SSH-2.0-dropbear",g' \ $(PKG_BUILD_DIR)/sysoptions.h @@ -160,6 +168,7 @@ define Package/dropbear/install $(INSTALL_DIR) $(1)/etc/dropbear $(INSTALL_DIR) $(1)/lib/preinit $(INSTALL_DATA) ./files/dropbear.failsafe $(1)/lib/preinit/99_10_failsafe_dropbear + $(if $(CONFIG_DROPBEAR_ED25519),touch $(1)/etc/dropbear/dropbear_ed25519_host_key) $(if $(CONFIG_DROPBEAR_ECC),touch $(1)/etc/dropbear/dropbear_ecdsa_host_key) touch $(1)/etc/dropbear/dropbear_rsa_host_key endef diff --git a/package/network/services/dropbear/files/dropbear.init b/package/network/services/dropbear/files/dropbear.init index 173ab09285..daf111fadb 100755 --- a/package/network/services/dropbear/files/dropbear.init +++ b/package/network/services/dropbear/files/dropbear.init @@ -66,7 +66,7 @@ hk_generate_as_needed() kdir='/etc/dropbear' kgen='' - for ktype in ecdsa rsa; do + for ktype in ed25519 ecdsa rsa; do hk_verify "${kdir}/dropbear_${ktype}_host_key" && continue kgen="${kgen} ${ktype}" diff --git a/package/network/services/dropbear/patches/020-backport-ed25519-support.patch b/package/network/services/dropbear/patches/020-backport-ed25519-support.patch new file mode 100644 index 0000000000..00a3bbbee1 --- /dev/null +++ b/package/network/services/dropbear/patches/020-backport-ed25519-support.patch @@ -0,0 +1,2890 @@ +From 3d12521735e7ef7e48be217af0f27d68e23050a7 Mon Sep 17 00:00:00 2001 +From: Vladislav Grishenko +Date: Wed, 11 Mar 2020 21:09:45 +0500 +Subject: [PATCH] Add Ed25519 support (#91) + +* Add support for Ed25519 as a public key type + +Ed25519 is a elliptic curve signature scheme that offers +better security than ECDSA and DSA and good performance. It may be +used for both user and host keys. + +OpenSSH key import and fuzzer are not supported yet. + +Initially inspired by Peter Szabo. + +* Add curve25519 and ed25519 fuzzers + +* Add import and export of Ed25519 keys +--- + .travis.yml | 1 + + FUZZER-NOTES.md | 3 + + LICENSE | 71 ++-- + Makefile.in | 12 +- + README | 1 + + cli-kex.c | 2 +- + common-algo.c | 3 + + common-kex.c | 14 +- + curve25519-donna.c | 860 ----------------------------------------- + curve25519.c | 502 ++++++++++++++++++++++++ + curve25519.h | 37 ++ + default_options.h | 7 +- + dropbear.8 | 6 +- + dropbearkey.c | 25 ++ + ed25519.c | 184 +++++++++ + ed25519.h | 54 +++ + filelist.txt | 4 + + fuzz-common.c | 8 + + fuzz-hostkeys.c | 10 + + fuzzer-kexcurve25519.c | 72 ++++ + gened25519.c | 47 +++ + gened25519.h | 36 ++ + gensignkey.c | 10 + + keyimport.c | 158 +++++++- + signkey.c | 60 ++- + signkey.h | 7 + + ssh.h | 2 + + svr-kex.c | 8 +- + svr-runopts.c | 24 ++ + sysoptions.h | 7 +- + 30 files changed, 1289 insertions(+), 946 deletions(-) + delete mode 100644 curve25519-donna.c + create mode 100644 curve25519.c + create mode 100644 curve25519.h + create mode 100644 ed25519.c + create mode 100644 ed25519.h + create mode 100644 fuzzer-kexcurve25519.c + create mode 100644 gened25519.c + create mode 100644 gened25519.h + +diff --git a/.travis.yml b/.travis.yml +index 9bcbce4..99499c8 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -57,6 +57,7 @@ script: + - ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256 + - ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384 + - ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521 ++ - ~/inst/bin/dropbearkey -t ed25519 -f tested25519 + - test -z $DO_FUZZ || ./fuzzers_test.sh + + branches: +diff --git a/FUZZER-NOTES.md b/FUZZER-NOTES.md +index 7b88238..4967eba 100644 +--- a/FUZZER-NOTES.md ++++ b/FUZZER-NOTES.md +@@ -72,3 +72,6 @@ Current fuzzers are + + - [fuzzer-kexecdh](fuzzer-kexecdh.c) - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh. + This is testing libtommath ECC routines. ++ ++- [fuzzer-kexcurve25519](fuzzer-kexcurve25519.c) - test Curve25519 Elliptic Curve Diffie-Hellman key exchange ++ like fuzzer-kexecdh. This is testing `dropbear_curve25519_scalarmult()` and other libtommath routines. +diff --git a/LICENSE b/LICENSE +index c400d94..a4849ff 100644 +--- a/LICENSE ++++ b/LICENSE +@@ -90,52 +90,25 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + ===== + +-curve25519-donna: +- +-/* Copyright 2008, Google Inc. +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are +- * met: +- * +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above +- * copyright notice, this list of conditions and the following disclaimer +- * in the documentation and/or other materials provided with the +- * distribution. +- * * Neither the name of Google Inc. nor the names of its +- * contributors may be used to endorse or promote products derived from +- * this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * curve25519-donna: Curve25519 elliptic curve, public key function +- * +- * http://code.google.com/p/curve25519-donna/ +- * +- * Adam Langley +- * +- * Derived from public domain C code by Daniel J. Bernstein +- * +- * More information about curve25519 can be found here +- * http://cr.yp.to/ecdh.html +- * +- * djb's sample implementation of curve25519 is written in a special assembly +- * language called qhasm and uses the floating point registers. +- * +- * This is, almost, a clean room reimplementation from the curve25519 paper. It +- * uses many of the tricks described therein. Only the crecip function is taken +- * from the sample implementation. +- */ ++crypto25519.c: ++crypto26619.h: ++ ++Modified TweetNaCl version 20140427, a self-contained public-domain C library. ++https://tweetnacl.cr.yp.to/ ++ ++Contributors (alphabetical order) ++Daniel J. Bernstein, University of Illinois at Chicago and Technische ++Universiteit Eindhoven ++Bernard van Gastel, Radboud Universiteit Nijmegen ++Wesley Janssen, Radboud Universiteit Nijmegen ++Tanja Lange, Technische Universiteit Eindhoven ++Peter Schwabe, Radboud Universiteit Nijmegen ++Sjaak Smetsers, Radboud Universiteit Nijmegen ++ ++Acknowledgments ++This work was supported by the U.S. National Science Foundation under grant ++1018836. "Any opinions, findings, and conclusions or recommendations expressed ++in this material are those of the author(s) and do not necessarily reflect the ++views of the National Science Foundation." ++This work was supported by the Netherlands Organisation for Scientific ++Research (NWO) under grant 639.073.005 and Veni 2013 project 13114. +diff --git a/Makefile.in b/Makefile.in +index bc55b7d..aaf7b3b 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -36,8 +36,9 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \ + queue.o \ + atomicio.o compat.o fake-rfc2553.o \ + ltc_prng.o ecc.o ecdsa.o crypto_desc.o \ ++ curve25519.o ed25519.o \ + dbmalloc.o \ +- gensignkey.o gendss.o genrsa.o ++ gensignkey.o gendss.o genrsa.o gened25519.o + + SVROBJS=svr-kex.o svr-auth.o sshpty.o \ + svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \ +@@ -52,7 +53,7 @@ CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \ + CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \ + common-channel.o common-chansession.o termcodes.o loginrec.o \ + tcp-accept.o listener.o process-packet.o dh_groups.o \ +- common-runopts.o circbuffer.o curve25519-donna.o list.o netio.o ++ common-runopts.o circbuffer.o list.o netio.o + + KEYOBJS=dropbearkey.o + +@@ -264,7 +265,7 @@ tidy: + ## Fuzzing targets + + # list of fuzz targets +-FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths fuzzer-kexdh fuzzer-kexecdh ++FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 + + FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) + +@@ -303,6 +304,9 @@ fuzzer-kexdh: fuzzer-kexdh.o fuzz-harness.o + fuzzer-kexecdh: fuzzer-kexecdh.o fuzz-harness.o + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + ++fuzzer-kexcurve25519: fuzzer-kexcurve25519.o fuzz-harness.o ++ $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ ++ + fuzzer-%.options: Makefile + echo "[libfuzzer]" > $@ + echo "max_len = 50000" >> $@ +@@ -313,7 +317,9 @@ fuzz-hostkeys: + dropbearkey -t rsa -f keyr + dropbearkey -t dss -f keyd + dropbearkey -t ecdsa -size 256 -f keye ++ dropbearkey -t ed25519 -f keyed25519 + echo > hostkeys.c + /usr/bin/xxd -i -a keyr >> hostkeys.c + /usr/bin/xxd -i -a keye >> hostkeys.c + /usr/bin/xxd -i -a keyd >> hostkeys.c ++ /usr/bin/xxd -i -a keyed25519 >> hostkeys.c +diff --git a/README b/README +index b8a6fd2..d197ec7 100644 +--- a/README ++++ b/README +@@ -55,6 +55,7 @@ To run the server, you need to generate server keys, this is one-off: + ./dropbearkey -t rsa -f dropbear_rsa_host_key + ./dropbearkey -t dss -f dropbear_dss_host_key + ./dropbearkey -t ecdsa -f dropbear_ecdsa_host_key ++./dropbearkey -t ed25519 -f dropbear_ed25519_host_key + + or alternatively convert OpenSSH keys to Dropbear: + ./dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key dropbear_dss_host_key +diff --git a/cli-kex.c b/cli-kex.c +index b02cfc7..7cefb5f 100644 +--- a/cli-kex.c ++++ b/cli-kex.c +@@ -81,7 +81,7 @@ void send_msg_kexdh_init() { + } + cli_ses.curve25519_param = gen_kexcurve25519_param(); + } +- buf_putstring(ses.writepayload, (const char*)cli_ses.curve25519_param->pub, CURVE25519_LEN); ++ buf_putstring(ses.writepayload, cli_ses.curve25519_param->pub, CURVE25519_LEN); + break; + #endif + } +diff --git a/common-algo.c b/common-algo.c +index 2f896ab..558aad2 100644 +--- a/common-algo.c ++++ b/common-algo.c +@@ -222,6 +222,9 @@ algo_type ssh_nocompress[] = { + }; + + algo_type sshhostkey[] = { ++#if DROPBEAR_ED25519 ++ {"ssh-ed25519", DROPBEAR_SIGNKEY_ED25519, NULL, 1, NULL}, ++#endif + #if DROPBEAR_ECDSA + #if DROPBEAR_ECC_256 + {"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256, NULL, 1, NULL}, +diff --git a/common-kex.c b/common-kex.c +index d4933dd..16b7e27 100644 +--- a/common-kex.c ++++ b/common-kex.c +@@ -36,6 +36,7 @@ + #include "dbrandom.h" + #include "runopts.h" + #include "ecc.h" ++#include "curve25519.h" + #include "crypto_desc.h" + + static void kexinitialise(void); +@@ -703,23 +704,18 @@ void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them, + #endif /* DROPBEAR_ECDH */ + + #if DROPBEAR_CURVE25519 +-struct kex_curve25519_param *gen_kexcurve25519_param () { ++struct kex_curve25519_param *gen_kexcurve25519_param() { + /* Per http://cr.yp.to/ecdh.html */ + struct kex_curve25519_param *param = m_malloc(sizeof(*param)); + const unsigned char basepoint[32] = {9}; + + genrandom(param->priv, CURVE25519_LEN); +- param->priv[0] &= 248; +- param->priv[31] &= 127; +- param->priv[31] |= 64; +- +- curve25519_donna(param->pub, param->priv, basepoint); ++ dropbear_curve25519_scalarmult(param->pub, param->priv, basepoint); + + return param; + } + +-void free_kexcurve25519_param(struct kex_curve25519_param *param) +-{ ++void free_kexcurve25519_param(struct kex_curve25519_param *param) { + m_burn(param->priv, CURVE25519_LEN); + m_free(param); + } +@@ -736,7 +732,7 @@ void kexcurve25519_comb_key(const struct kex_curve25519_param *param, const buff + dropbear_exit("Bad curve25519"); + } + +- curve25519_donna(out, param->priv, buf_pub_them->data); ++ dropbear_curve25519_scalarmult(out, param->priv, buf_pub_them->data); + + if (constant_time_memcmp(zeroes, out, CURVE25519_LEN) == 0) { + dropbear_exit("Bad curve25519"); +diff --git a/curve25519-donna.c b/curve25519-donna.c +deleted file mode 100644 +index ef0b6d1..0000000 +--- a/curve25519-donna.c ++++ /dev/null +@@ -1,860 +0,0 @@ +-/* Copyright 2008, Google Inc. +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are +- * met: +- * +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above +- * copyright notice, this list of conditions and the following disclaimer +- * in the documentation and/or other materials provided with the +- * distribution. +- * * Neither the name of Google Inc. nor the names of its +- * contributors may be used to endorse or promote products derived from +- * this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * curve25519-donna: Curve25519 elliptic curve, public key function +- * +- * http://code.google.com/p/curve25519-donna/ +- * +- * Adam Langley +- * +- * Derived from public domain C code by Daniel J. Bernstein +- * +- * More information about curve25519 can be found here +- * http://cr.yp.to/ecdh.html +- * +- * djb's sample implementation of curve25519 is written in a special assembly +- * language called qhasm and uses the floating point registers. +- * +- * This is, almost, a clean room reimplementation from the curve25519 paper. It +- * uses many of the tricks described therein. Only the crecip function is taken +- * from the sample implementation. */ +- +-#include +-#include +- +-#ifdef _MSC_VER +-#define inline __inline +-#endif +- +-typedef uint8_t u8; +-typedef int32_t s32; +-typedef int64_t limb; +- +-/* Field element representation: +- * +- * Field elements are written as an array of signed, 64-bit limbs, least +- * significant first. The value of the field element is: +- * x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ... +- * +- * i.e. the limbs are 26, 25, 26, 25, ... bits wide. */ +- +-/* Sum two numbers: output += in */ +-static void fsum(limb *output, const limb *in) { +- unsigned i; +- for (i = 0; i < 10; i += 2) { +- output[0+i] = output[0+i] + in[0+i]; +- output[1+i] = output[1+i] + in[1+i]; +- } +-} +- +-/* Find the difference of two numbers: output = in - output +- * (note the order of the arguments!). */ +-static void fdifference(limb *output, const limb *in) { +- unsigned i; +- for (i = 0; i < 10; ++i) { +- output[i] = in[i] - output[i]; +- } +-} +- +-/* Multiply a number by a scalar: output = in * scalar */ +-static void fscalar_product(limb *output, const limb *in, const limb scalar) { +- unsigned i; +- for (i = 0; i < 10; ++i) { +- output[i] = in[i] * scalar; +- } +-} +- +-/* Multiply two numbers: output = in2 * in +- * +- * output must be distinct to both inputs. The inputs are reduced coefficient +- * form, the output is not. +- * +- * output[x] <= 14 * the largest product of the input limbs. */ +-static void fproduct(limb *output, const limb *in2, const limb *in) { +- output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]); +- output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + +- ((limb) ((s32) in2[1])) * ((s32) in[0]); +- output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) + +- ((limb) ((s32) in2[0])) * ((s32) in[2]) + +- ((limb) ((s32) in2[2])) * ((s32) in[0]); +- output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) + +- ((limb) ((s32) in2[2])) * ((s32) in[1]) + +- ((limb) ((s32) in2[0])) * ((s32) in[3]) + +- ((limb) ((s32) in2[3])) * ((s32) in[0]); +- output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) + +- 2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) + +- ((limb) ((s32) in2[3])) * ((s32) in[1])) + +- ((limb) ((s32) in2[0])) * ((s32) in[4]) + +- ((limb) ((s32) in2[4])) * ((s32) in[0]); +- output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) + +- ((limb) ((s32) in2[3])) * ((s32) in[2]) + +- ((limb) ((s32) in2[1])) * ((s32) in[4]) + +- ((limb) ((s32) in2[4])) * ((s32) in[1]) + +- ((limb) ((s32) in2[0])) * ((s32) in[5]) + +- ((limb) ((s32) in2[5])) * ((s32) in[0]); +- output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) + +- ((limb) ((s32) in2[1])) * ((s32) in[5]) + +- ((limb) ((s32) in2[5])) * ((s32) in[1])) + +- ((limb) ((s32) in2[2])) * ((s32) in[4]) + +- ((limb) ((s32) in2[4])) * ((s32) in[2]) + +- ((limb) ((s32) in2[0])) * ((s32) in[6]) + +- ((limb) ((s32) in2[6])) * ((s32) in[0]); +- output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) + +- ((limb) ((s32) in2[4])) * ((s32) in[3]) + +- ((limb) ((s32) in2[2])) * ((s32) in[5]) + +- ((limb) ((s32) in2[5])) * ((s32) in[2]) + +- ((limb) ((s32) in2[1])) * ((s32) in[6]) + +- ((limb) ((s32) in2[6])) * ((s32) in[1]) + +- ((limb) ((s32) in2[0])) * ((s32) in[7]) + +- ((limb) ((s32) in2[7])) * ((s32) in[0]); +- output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) + +- 2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) + +- ((limb) ((s32) in2[5])) * ((s32) in[3]) + +- ((limb) ((s32) in2[1])) * ((s32) in[7]) + +- ((limb) ((s32) in2[7])) * ((s32) in[1])) + +- ((limb) ((s32) in2[2])) * ((s32) in[6]) + +- ((limb) ((s32) in2[6])) * ((s32) in[2]) + +- ((limb) ((s32) in2[0])) * ((s32) in[8]) + +- ((limb) ((s32) in2[8])) * ((s32) in[0]); +- output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) + +- ((limb) ((s32) in2[5])) * ((s32) in[4]) + +- ((limb) ((s32) in2[3])) * ((s32) in[6]) + +- ((limb) ((s32) in2[6])) * ((s32) in[3]) + +- ((limb) ((s32) in2[2])) * ((s32) in[7]) + +- ((limb) ((s32) in2[7])) * ((s32) in[2]) + +- ((limb) ((s32) in2[1])) * ((s32) in[8]) + +- ((limb) ((s32) in2[8])) * ((s32) in[1]) + +- ((limb) ((s32) in2[0])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[0]); +- output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) + +- ((limb) ((s32) in2[3])) * ((s32) in[7]) + +- ((limb) ((s32) in2[7])) * ((s32) in[3]) + +- ((limb) ((s32) in2[1])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[1])) + +- ((limb) ((s32) in2[4])) * ((s32) in[6]) + +- ((limb) ((s32) in2[6])) * ((s32) in[4]) + +- ((limb) ((s32) in2[2])) * ((s32) in[8]) + +- ((limb) ((s32) in2[8])) * ((s32) in[2]); +- output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) + +- ((limb) ((s32) in2[6])) * ((s32) in[5]) + +- ((limb) ((s32) in2[4])) * ((s32) in[7]) + +- ((limb) ((s32) in2[7])) * ((s32) in[4]) + +- ((limb) ((s32) in2[3])) * ((s32) in[8]) + +- ((limb) ((s32) in2[8])) * ((s32) in[3]) + +- ((limb) ((s32) in2[2])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[2]); +- output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) + +- 2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) + +- ((limb) ((s32) in2[7])) * ((s32) in[5]) + +- ((limb) ((s32) in2[3])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[3])) + +- ((limb) ((s32) in2[4])) * ((s32) in[8]) + +- ((limb) ((s32) in2[8])) * ((s32) in[4]); +- output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) + +- ((limb) ((s32) in2[7])) * ((s32) in[6]) + +- ((limb) ((s32) in2[5])) * ((s32) in[8]) + +- ((limb) ((s32) in2[8])) * ((s32) in[5]) + +- ((limb) ((s32) in2[4])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[4]); +- output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) + +- ((limb) ((s32) in2[5])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[5])) + +- ((limb) ((s32) in2[6])) * ((s32) in[8]) + +- ((limb) ((s32) in2[8])) * ((s32) in[6]); +- output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) + +- ((limb) ((s32) in2[8])) * ((s32) in[7]) + +- ((limb) ((s32) in2[6])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[6]); +- output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) + +- 2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[7])); +- output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) + +- ((limb) ((s32) in2[9])) * ((s32) in[8]); +- output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]); +-} +- +-/* Reduce a long form to a short form by taking the input mod 2^255 - 19. +- * +- * On entry: |output[i]| < 14*2^54 +- * On exit: |output[0..8]| < 280*2^54 */ +-static void freduce_degree(limb *output) { +- /* Each of these shifts and adds ends up multiplying the value by 19. +- * +- * For output[0..8], the absolute entry value is < 14*2^54 and we add, at +- * most, 19*14*2^54 thus, on exit, |output[0..8]| < 280*2^54. */ +- output[8] += output[18] << 4; +- output[8] += output[18] << 1; +- output[8] += output[18]; +- output[7] += output[17] << 4; +- output[7] += output[17] << 1; +- output[7] += output[17]; +- output[6] += output[16] << 4; +- output[6] += output[16] << 1; +- output[6] += output[16]; +- output[5] += output[15] << 4; +- output[5] += output[15] << 1; +- output[5] += output[15]; +- output[4] += output[14] << 4; +- output[4] += output[14] << 1; +- output[4] += output[14]; +- output[3] += output[13] << 4; +- output[3] += output[13] << 1; +- output[3] += output[13]; +- output[2] += output[12] << 4; +- output[2] += output[12] << 1; +- output[2] += output[12]; +- output[1] += output[11] << 4; +- output[1] += output[11] << 1; +- output[1] += output[11]; +- output[0] += output[10] << 4; +- output[0] += output[10] << 1; +- output[0] += output[10]; +-} +- +-#if (-1 & 3) != 3 +-#error "This code only works on a two's complement system" +-#endif +- +-/* return v / 2^26, using only shifts and adds. +- * +- * On entry: v can take any value. */ +-static inline limb +-div_by_2_26(const limb v) +-{ +- /* High word of v; no shift needed. */ +- const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); +- /* Set to all 1s if v was negative; else set to 0s. */ +- const int32_t sign = ((int32_t) highword) >> 31; +- /* Set to 0x3ffffff if v was negative; else set to 0. */ +- const int32_t roundoff = ((uint32_t) sign) >> 6; +- /* Should return v / (1<<26) */ +- return (v + roundoff) >> 26; +-} +- +-/* return v / (2^25), using only shifts and adds. +- * +- * On entry: v can take any value. */ +-static inline limb +-div_by_2_25(const limb v) +-{ +- /* High word of v; no shift needed*/ +- const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); +- /* Set to all 1s if v was negative; else set to 0s. */ +- const int32_t sign = ((int32_t) highword) >> 31; +- /* Set to 0x1ffffff if v was negative; else set to 0. */ +- const int32_t roundoff = ((uint32_t) sign) >> 7; +- /* Should return v / (1<<25) */ +- return (v + roundoff) >> 25; +-} +- +-/* Reduce all coefficients of the short form input so that |x| < 2^26. +- * +- * On entry: |output[i]| < 280*2^54 */ +-static void freduce_coefficients(limb *output) { +- unsigned i; +- +- output[10] = 0; +- +- for (i = 0; i < 10; i += 2) { +- limb over = div_by_2_26(output[i]); +- /* The entry condition (that |output[i]| < 280*2^54) means that over is, at +- * most, 280*2^28 in the first iteration of this loop. This is added to the +- * next limb and we can approximate the resulting bound of that limb by +- * 281*2^54. */ +- output[i] -= over << 26; +- output[i+1] += over; +- +- /* For the first iteration, |output[i+1]| < 281*2^54, thus |over| < +- * 281*2^29. When this is added to the next limb, the resulting bound can +- * be approximated as 281*2^54. +- * +- * For subsequent iterations of the loop, 281*2^54 remains a conservative +- * bound and no overflow occurs. */ +- over = div_by_2_25(output[i+1]); +- output[i+1] -= over << 25; +- output[i+2] += over; +- } +- /* Now |output[10]| < 281*2^29 and all other coefficients are reduced. */ +- output[0] += output[10] << 4; +- output[0] += output[10] << 1; +- output[0] += output[10]; +- +- output[10] = 0; +- +- /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19*281*2^29 +- * So |over| will be no more than 2^16. */ +- { +- limb over = div_by_2_26(output[0]); +- output[0] -= over << 26; +- output[1] += over; +- } +- +- /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 2^16 < 2^26. The +- * bound on |output[1]| is sufficient to meet our needs. */ +-} +- +-/* A helpful wrapper around fproduct: output = in * in2. +- * +- * On entry: |in[i]| < 2^27 and |in2[i]| < 2^27. +- * +- * output must be distinct to both inputs. The output is reduced degree +- * (indeed, one need only provide storage for 10 limbs) and |output[i]| < 2^26. */ +-static void +-fmul(limb *output, const limb *in, const limb *in2) { +- limb t[19]; +- fproduct(t, in, in2); +- /* |t[i]| < 14*2^54 */ +- freduce_degree(t); +- freduce_coefficients(t); +- /* |t[i]| < 2^26 */ +- memcpy(output, t, sizeof(limb) * 10); +-} +- +-/* Square a number: output = in**2 +- * +- * output must be distinct from the input. The inputs are reduced coefficient +- * form, the output is not. +- * +- * output[x] <= 14 * the largest product of the input limbs. */ +-static void fsquare_inner(limb *output, const limb *in) { +- output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); +- output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); +- output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + +- ((limb) ((s32) in[0])) * ((s32) in[2])); +- output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + +- ((limb) ((s32) in[0])) * ((s32) in[3])); +- output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + +- 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + +- 2 * ((limb) ((s32) in[0])) * ((s32) in[4]); +- output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + +- ((limb) ((s32) in[1])) * ((s32) in[4]) + +- ((limb) ((s32) in[0])) * ((s32) in[5])); +- output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + +- ((limb) ((s32) in[2])) * ((s32) in[4]) + +- ((limb) ((s32) in[0])) * ((s32) in[6]) + +- 2 * ((limb) ((s32) in[1])) * ((s32) in[5])); +- output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + +- ((limb) ((s32) in[2])) * ((s32) in[5]) + +- ((limb) ((s32) in[1])) * ((s32) in[6]) + +- ((limb) ((s32) in[0])) * ((s32) in[7])); +- output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) + +- 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) + +- ((limb) ((s32) in[0])) * ((s32) in[8]) + +- 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) + +- ((limb) ((s32) in[3])) * ((s32) in[5]))); +- output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) + +- ((limb) ((s32) in[3])) * ((s32) in[6]) + +- ((limb) ((s32) in[2])) * ((s32) in[7]) + +- ((limb) ((s32) in[1])) * ((s32) in[8]) + +- ((limb) ((s32) in[0])) * ((s32) in[9])); +- output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) + +- ((limb) ((s32) in[4])) * ((s32) in[6]) + +- ((limb) ((s32) in[2])) * ((s32) in[8]) + +- 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) + +- ((limb) ((s32) in[1])) * ((s32) in[9]))); +- output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) + +- ((limb) ((s32) in[4])) * ((s32) in[7]) + +- ((limb) ((s32) in[3])) * ((s32) in[8]) + +- ((limb) ((s32) in[2])) * ((s32) in[9])); +- output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) + +- 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) + +- 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) + +- ((limb) ((s32) in[3])) * ((s32) in[9]))); +- output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) + +- ((limb) ((s32) in[5])) * ((s32) in[8]) + +- ((limb) ((s32) in[4])) * ((s32) in[9])); +- output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) + +- ((limb) ((s32) in[6])) * ((s32) in[8]) + +- 2 * ((limb) ((s32) in[5])) * ((s32) in[9])); +- output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) + +- ((limb) ((s32) in[6])) * ((s32) in[9])); +- output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) + +- 4 * ((limb) ((s32) in[7])) * ((s32) in[9]); +- output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]); +- output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); +-} +- +-/* fsquare sets output = in^2. +- * +- * On entry: The |in| argument is in reduced coefficients form and |in[i]| < +- * 2^27. +- * +- * On exit: The |output| argument is in reduced coefficients form (indeed, one +- * need only provide storage for 10 limbs) and |out[i]| < 2^26. */ +-static void +-fsquare(limb *output, const limb *in) { +- limb t[19]; +- fsquare_inner(t, in); +- /* |t[i]| < 14*2^54 because the largest product of two limbs will be < +- * 2^(27+27) and fsquare_inner adds together, at most, 14 of those +- * products. */ +- freduce_degree(t); +- freduce_coefficients(t); +- /* |t[i]| < 2^26 */ +- memcpy(output, t, sizeof(limb) * 10); +-} +- +-/* Take a little-endian, 32-byte number and expand it into polynomial form */ +-static void +-fexpand(limb *output, const u8 *input) { +-#define F(n,start,shift,mask) \ +- output[n] = ((((limb) input[start + 0]) | \ +- ((limb) input[start + 1]) << 8 | \ +- ((limb) input[start + 2]) << 16 | \ +- ((limb) input[start + 3]) << 24) >> shift) & mask; +- F(0, 0, 0, 0x3ffffff); +- F(1, 3, 2, 0x1ffffff); +- F(2, 6, 3, 0x3ffffff); +- F(3, 9, 5, 0x1ffffff); +- F(4, 12, 6, 0x3ffffff); +- F(5, 16, 0, 0x1ffffff); +- F(6, 19, 1, 0x3ffffff); +- F(7, 22, 3, 0x1ffffff); +- F(8, 25, 4, 0x3ffffff); +- F(9, 28, 6, 0x1ffffff); +-#undef F +-} +- +-#if (-32 >> 1) != -16 +-#error "This code only works when >> does sign-extension on negative numbers" +-#endif +- +-/* s32_eq returns 0xffffffff iff a == b and zero otherwise. */ +-static s32 s32_eq(s32 a, s32 b) { +- a = ~(a ^ b); +- a &= a << 16; +- a &= a << 8; +- a &= a << 4; +- a &= a << 2; +- a &= a << 1; +- return a >> 31; +-} +- +-/* s32_gte returns 0xffffffff if a >= b and zero otherwise, where a and b are +- * both non-negative. */ +-static s32 s32_gte(s32 a, s32 b) { +- a -= b; +- /* a >= 0 iff a >= b. */ +- return ~(a >> 31); +-} +- +-/* Take a fully reduced polynomial form number and contract it into a +- * little-endian, 32-byte array. +- * +- * On entry: |input_limbs[i]| < 2^26 */ +-static void +-fcontract(u8 *output, limb *input_limbs) { +- int i; +- int j; +- s32 input[10]; +- s32 mask; +- +- /* |input_limbs[i]| < 2^26, so it's valid to convert to an s32. */ +- for (i = 0; i < 10; i++) { +- input[i] = input_limbs[i]; +- } +- +- for (j = 0; j < 2; ++j) { +- for (i = 0; i < 9; ++i) { +- if ((i & 1) == 1) { +- /* This calculation is a time-invariant way to make input[i] +- * non-negative by borrowing from the next-larger limb. */ +- const s32 mask = input[i] >> 31; +- const s32 carry = -((input[i] & mask) >> 25); +- input[i] = input[i] + (carry << 25); +- input[i+1] = input[i+1] - carry; +- } else { +- const s32 mask = input[i] >> 31; +- const s32 carry = -((input[i] & mask) >> 26); +- input[i] = input[i] + (carry << 26); +- input[i+1] = input[i+1] - carry; +- } +- } +- +- /* There's no greater limb for input[9] to borrow from, but we can multiply +- * by 19 and borrow from input[0], which is valid mod 2^255-19. */ +- { +- const s32 mask = input[9] >> 31; +- const s32 carry = -((input[9] & mask) >> 25); +- input[9] = input[9] + (carry << 25); +- input[0] = input[0] - (carry * 19); +- } +- +- /* After the first iteration, input[1..9] are non-negative and fit within +- * 25 or 26 bits, depending on position. However, input[0] may be +- * negative. */ +- } +- +- /* The first borrow-propagation pass above ended with every limb +- except (possibly) input[0] non-negative. +- +- If input[0] was negative after the first pass, then it was because of a +- carry from input[9]. On entry, input[9] < 2^26 so the carry was, at most, +- one, since (2**26-1) >> 25 = 1. Thus input[0] >= -19. +- +- In the second pass, each limb is decreased by at most one. Thus the second +- borrow-propagation pass could only have wrapped around to decrease +- input[0] again if the first pass left input[0] negative *and* input[1] +- through input[9] were all zero. In that case, input[1] is now 2^25 - 1, +- and this last borrow-propagation step will leave input[1] non-negative. */ +- { +- const s32 mask = input[0] >> 31; +- const s32 carry = -((input[0] & mask) >> 26); +- input[0] = input[0] + (carry << 26); +- input[1] = input[1] - carry; +- } +- +- /* All input[i] are now non-negative. However, there might be values between +- * 2^25 and 2^26 in a limb which is, nominally, 25 bits wide. */ +- for (j = 0; j < 2; j++) { +- for (i = 0; i < 9; i++) { +- if ((i & 1) == 1) { +- const s32 carry = input[i] >> 25; +- input[i] &= 0x1ffffff; +- input[i+1] += carry; +- } else { +- const s32 carry = input[i] >> 26; +- input[i] &= 0x3ffffff; +- input[i+1] += carry; +- } +- } +- +- { +- const s32 carry = input[9] >> 25; +- input[9] &= 0x1ffffff; +- input[0] += 19*carry; +- } +- } +- +- /* If the first carry-chain pass, just above, ended up with a carry from +- * input[9], and that caused input[0] to be out-of-bounds, then input[0] was +- * < 2^26 + 2*19, because the carry was, at most, two. +- * +- * If the second pass carried from input[9] again then input[0] is < 2*19 and +- * the input[9] -> input[0] carry didn't push input[0] out of bounds. */ +- +- /* It still remains the case that input might be between 2^255-19 and 2^255. +- * In this case, input[1..9] must take their maximum value and input[0] must +- * be >= (2^255-19) & 0x3ffffff, which is 0x3ffffed. */ +- mask = s32_gte(input[0], 0x3ffffed); +- for (i = 1; i < 10; i++) { +- if ((i & 1) == 1) { +- mask &= s32_eq(input[i], 0x1ffffff); +- } else { +- mask &= s32_eq(input[i], 0x3ffffff); +- } +- } +- +- /* mask is either 0xffffffff (if input >= 2^255-19) and zero otherwise. Thus +- * this conditionally subtracts 2^255-19. */ +- input[0] -= mask & 0x3ffffed; +- +- for (i = 1; i < 10; i++) { +- if ((i & 1) == 1) { +- input[i] -= mask & 0x1ffffff; +- } else { +- input[i] -= mask & 0x3ffffff; +- } +- } +- +- input[1] <<= 2; +- input[2] <<= 3; +- input[3] <<= 5; +- input[4] <<= 6; +- input[6] <<= 1; +- input[7] <<= 3; +- input[8] <<= 4; +- input[9] <<= 6; +-#define F(i, s) \ +- output[s+0] |= input[i] & 0xff; \ +- output[s+1] = (input[i] >> 8) & 0xff; \ +- output[s+2] = (input[i] >> 16) & 0xff; \ +- output[s+3] = (input[i] >> 24) & 0xff; +- output[0] = 0; +- output[16] = 0; +- F(0,0); +- F(1,3); +- F(2,6); +- F(3,9); +- F(4,12); +- F(5,16); +- F(6,19); +- F(7,22); +- F(8,25); +- F(9,28); +-#undef F +-} +- +-/* Input: Q, Q', Q-Q' +- * Output: 2Q, Q+Q' +- * +- * x2 z3: long form +- * x3 z3: long form +- * x z: short form, destroyed +- * xprime zprime: short form, destroyed +- * qmqp: short form, preserved +- * +- * On entry and exit, the absolute value of the limbs of all inputs and outputs +- * are < 2^26. */ +-static void fmonty(limb *x2, limb *z2, /* output 2Q */ +- limb *x3, limb *z3, /* output Q + Q' */ +- limb *x, limb *z, /* input Q */ +- limb *xprime, limb *zprime, /* input Q' */ +- const limb *qmqp /* input Q - Q' */) { +- limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], +- zzprime[19], zzzprime[19], xxxprime[19]; +- +- memcpy(origx, x, 10 * sizeof(limb)); +- fsum(x, z); +- /* |x[i]| < 2^27 */ +- fdifference(z, origx); /* does x - z */ +- /* |z[i]| < 2^27 */ +- +- memcpy(origxprime, xprime, sizeof(limb) * 10); +- fsum(xprime, zprime); +- /* |xprime[i]| < 2^27 */ +- fdifference(zprime, origxprime); +- /* |zprime[i]| < 2^27 */ +- fproduct(xxprime, xprime, z); +- /* |xxprime[i]| < 14*2^54: the largest product of two limbs will be < +- * 2^(27+27) and fproduct adds together, at most, 14 of those products. +- * (Approximating that to 2^58 doesn't work out.) */ +- fproduct(zzprime, x, zprime); +- /* |zzprime[i]| < 14*2^54 */ +- freduce_degree(xxprime); +- freduce_coefficients(xxprime); +- /* |xxprime[i]| < 2^26 */ +- freduce_degree(zzprime); +- freduce_coefficients(zzprime); +- /* |zzprime[i]| < 2^26 */ +- memcpy(origxprime, xxprime, sizeof(limb) * 10); +- fsum(xxprime, zzprime); +- /* |xxprime[i]| < 2^27 */ +- fdifference(zzprime, origxprime); +- /* |zzprime[i]| < 2^27 */ +- fsquare(xxxprime, xxprime); +- /* |xxxprime[i]| < 2^26 */ +- fsquare(zzzprime, zzprime); +- /* |zzzprime[i]| < 2^26 */ +- fproduct(zzprime, zzzprime, qmqp); +- /* |zzprime[i]| < 14*2^52 */ +- freduce_degree(zzprime); +- freduce_coefficients(zzprime); +- /* |zzprime[i]| < 2^26 */ +- memcpy(x3, xxxprime, sizeof(limb) * 10); +- memcpy(z3, zzprime, sizeof(limb) * 10); +- +- fsquare(xx, x); +- /* |xx[i]| < 2^26 */ +- fsquare(zz, z); +- /* |zz[i]| < 2^26 */ +- fproduct(x2, xx, zz); +- /* |x2[i]| < 14*2^52 */ +- freduce_degree(x2); +- freduce_coefficients(x2); +- /* |x2[i]| < 2^26 */ +- fdifference(zz, xx); /* does zz = xx - zz */ +- /* |zz[i]| < 2^27 */ +- memset(zzz + 10, 0, sizeof(limb) * 9); +- fscalar_product(zzz, zz, 121665); +- /* |zzz[i]| < 2^(27+17) */ +- /* No need to call freduce_degree here: +- fscalar_product doesn't increase the degree of its input. */ +- freduce_coefficients(zzz); +- /* |zzz[i]| < 2^26 */ +- fsum(zzz, xx); +- /* |zzz[i]| < 2^27 */ +- fproduct(z2, zz, zzz); +- /* |z2[i]| < 14*2^(26+27) */ +- freduce_degree(z2); +- freduce_coefficients(z2); +- /* |z2|i| < 2^26 */ +-} +- +-/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave +- * them unchanged if 'iswap' is 0. Runs in data-invariant time to avoid +- * side-channel attacks. +- * +- * NOTE that this function requires that 'iswap' be 1 or 0; other values give +- * wrong results. Also, the two limb arrays must be in reduced-coefficient, +- * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped, +- * and all all values in a[0..9],b[0..9] must have magnitude less than +- * INT32_MAX. */ +-static void +-swap_conditional(limb a[19], limb b[19], limb iswap) { +- unsigned i; +- const s32 swap = (s32) -iswap; +- +- for (i = 0; i < 10; ++i) { +- const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) ); +- a[i] = ((s32)a[i]) ^ x; +- b[i] = ((s32)b[i]) ^ x; +- } +-} +- +-/* Calculates nQ where Q is the x-coordinate of a point on the curve +- * +- * resultx/resultz: the x coordinate of the resulting curve point (short form) +- * n: a little endian, 32-byte number +- * q: a point of the curve (short form) */ +-static void +-cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { +- limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0}; +- limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; +- limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1}; +- limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; +- +- unsigned i, j; +- +- memcpy(nqpqx, q, sizeof(limb) * 10); +- +- for (i = 0; i < 32; ++i) { +- u8 byte = n[31 - i]; +- for (j = 0; j < 8; ++j) { +- const limb bit = byte >> 7; +- +- swap_conditional(nqx, nqpqx, bit); +- swap_conditional(nqz, nqpqz, bit); +- fmonty(nqx2, nqz2, +- nqpqx2, nqpqz2, +- nqx, nqz, +- nqpqx, nqpqz, +- q); +- swap_conditional(nqx2, nqpqx2, bit); +- swap_conditional(nqz2, nqpqz2, bit); +- +- t = nqx; +- nqx = nqx2; +- nqx2 = t; +- t = nqz; +- nqz = nqz2; +- nqz2 = t; +- t = nqpqx; +- nqpqx = nqpqx2; +- nqpqx2 = t; +- t = nqpqz; +- nqpqz = nqpqz2; +- nqpqz2 = t; +- +- byte <<= 1; +- } +- } +- +- memcpy(resultx, nqx, sizeof(limb) * 10); +- memcpy(resultz, nqz, sizeof(limb) * 10); +-} +- +-/* ----------------------------------------------------------------------------- +- * Shamelessly copied from djb's code +- * ----------------------------------------------------------------------------- */ +-static void +-crecip(limb *out, const limb *z) { +- limb z2[10]; +- limb z9[10]; +- limb z11[10]; +- limb z2_5_0[10]; +- limb z2_10_0[10]; +- limb z2_20_0[10]; +- limb z2_50_0[10]; +- limb z2_100_0[10]; +- limb t0[10]; +- limb t1[10]; +- int i; +- +- /* 2 */ fsquare(z2,z); +- /* 4 */ fsquare(t1,z2); +- /* 8 */ fsquare(t0,t1); +- /* 9 */ fmul(z9,t0,z); +- /* 11 */ fmul(z11,z9,z2); +- /* 22 */ fsquare(t0,z11); +- /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9); +- +- /* 2^6 - 2^1 */ fsquare(t0,z2_5_0); +- /* 2^7 - 2^2 */ fsquare(t1,t0); +- /* 2^8 - 2^3 */ fsquare(t0,t1); +- /* 2^9 - 2^4 */ fsquare(t1,t0); +- /* 2^10 - 2^5 */ fsquare(t0,t1); +- /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0); +- +- /* 2^11 - 2^1 */ fsquare(t0,z2_10_0); +- /* 2^12 - 2^2 */ fsquare(t1,t0); +- /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } +- /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0); +- +- /* 2^21 - 2^1 */ fsquare(t0,z2_20_0); +- /* 2^22 - 2^2 */ fsquare(t1,t0); +- /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } +- /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0); +- +- /* 2^41 - 2^1 */ fsquare(t1,t0); +- /* 2^42 - 2^2 */ fsquare(t0,t1); +- /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } +- /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0); +- +- /* 2^51 - 2^1 */ fsquare(t0,z2_50_0); +- /* 2^52 - 2^2 */ fsquare(t1,t0); +- /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } +- /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0); +- +- /* 2^101 - 2^1 */ fsquare(t1,z2_100_0); +- /* 2^102 - 2^2 */ fsquare(t0,t1); +- /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } +- /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0); +- +- /* 2^201 - 2^1 */ fsquare(t0,t1); +- /* 2^202 - 2^2 */ fsquare(t1,t0); +- /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } +- /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0); +- +- /* 2^251 - 2^1 */ fsquare(t1,t0); +- /* 2^252 - 2^2 */ fsquare(t0,t1); +- /* 2^253 - 2^3 */ fsquare(t1,t0); +- /* 2^254 - 2^4 */ fsquare(t0,t1); +- /* 2^255 - 2^5 */ fsquare(t1,t0); +- /* 2^255 - 21 */ fmul(out,t1,z11); +-} +- +-int +-curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { +- limb bp[10], x[10], z[11], zmone[10]; +- uint8_t e[32]; +- int i; +- +- for (i = 0; i < 32; ++i) e[i] = secret[i]; +- e[0] &= 248; +- e[31] &= 127; +- e[31] |= 64; +- +- fexpand(bp, basepoint); +- cmult(x, z, e, bp); +- crecip(zmone, z); +- fmul(z, x, zmone); +- fcontract(mypublic, z); +- return 0; +-} +diff --git a/curve25519.c b/curve25519.c +new file mode 100644 +index 0000000..4b83776 +--- /dev/null ++++ b/curve25519.c +@@ -0,0 +1,502 @@ ++/* ++ * Dropbear - a SSH2 server ++ * ++ * Copyright (c) 2002,2003 Matt Johnston ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. */ ++ ++#include "includes.h" ++#include "dbrandom.h" ++#include "curve25519.h" ++ ++#if DROPBEAR_CURVE25519 || DROPBEAR_ED25519 ++ ++/* Modified TweetNaCl version 20140427, a self-contained public-domain C library. ++ * https://tweetnacl.cr.yp.to/ */ ++ ++#define FOR(i,n) for (i = 0;i < n;++i) ++#define sv static void ++ ++typedef unsigned char u8; ++typedef unsigned long u32; ++typedef unsigned long long u64; ++typedef long long i64; ++typedef i64 gf[16]; ++ ++#if DROPBEAR_CURVE25519 ++static const gf ++ _121665 = {0xDB41,1}; ++#endif /* DROPBEAR_CURVE25519 */ ++#if DROPBEAR_ED25519 ++static const gf ++ gf0, ++ gf1 = {1}, ++ D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, ++ X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, ++ Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}; ++#if DROPBEAR_SIGNKEY_VERIFY ++static const gf ++ D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, ++ I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; ++#endif /* DROPBEAR_SIGNKEY_VERIFY */ ++#endif /* DROPBEAR_ED25519 */ ++ ++#if DROPBEAR_ED25519 ++#if DROPBEAR_SIGNKEY_VERIFY ++static int vn(const u8 *x,const u8 *y,u32 n) ++{ ++ u32 i,d = 0; ++ FOR(i,n) d |= x[i]^y[i]; ++ return (1 & ((d - 1) >> 8)) - 1; ++} ++ ++static int crypto_verify_32(const u8 *x,const u8 *y) ++{ ++ return vn(x,y,32); ++} ++#endif /* DROPBEAR_SIGNKEY_VERIFY */ ++ ++sv set25519(gf r, const gf a) ++{ ++ int i; ++ FOR(i,16) r[i]=a[i]; ++} ++#endif /* DROPBEAR_ED25519 */ ++ ++sv car25519(gf o) ++{ ++ int i; ++ i64 c; ++ FOR(i,16) { ++ o[i]+=(1LL<<16); ++ c=o[i]>>16; ++ o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); ++ o[i]-=c<<16; ++ } ++} ++ ++sv sel25519(gf p,gf q,int b) ++{ ++ i64 t,i,c=~(b-1); ++ FOR(i,16) { ++ t= c&(p[i]^q[i]); ++ p[i]^=t; ++ q[i]^=t; ++ } ++} ++ ++sv pack25519(u8 *o,const gf n) ++{ ++ int i,j,b; ++ gf m,t; ++ FOR(i,16) t[i]=n[i]; ++ car25519(t); ++ car25519(t); ++ car25519(t); ++ FOR(j,2) { ++ m[0]=t[0]-0xffed; ++ for(i=1;i<15;i++) { ++ m[i]=t[i]-0xffff-((m[i-1]>>16)&1); ++ m[i-1]&=0xffff; ++ } ++ m[15]=t[15]-0x7fff-((m[14]>>16)&1); ++ b=(m[15]>>16)&1; ++ m[14]&=0xffff; ++ sel25519(t,m,1-b); ++ } ++ FOR(i,16) { ++ o[2*i]=t[i]&0xff; ++ o[2*i+1]=t[i]>>8; ++ } ++} ++ ++#if DROPBEAR_ED25519 ++#if DROPBEAR_SIGNKEY_VERIFY ++static int neq25519(const gf a, const gf b) ++{ ++ u8 c[32],d[32]; ++ pack25519(c,a); ++ pack25519(d,b); ++ return crypto_verify_32(c,d); ++} ++#endif /* DROPBEAR_SIGNKEY_VERIFY */ ++ ++static u8 par25519(const gf a) ++{ ++ u8 d[32]; ++ pack25519(d,a); ++ return d[0]&1; ++} ++#endif /* DROPBEAR_ED25519 */ ++ ++sv unpack25519(gf o, const u8 *n) ++{ ++ int i; ++ FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8); ++ o[15]&=0x7fff; ++} ++ ++sv A(gf o,const gf a,const gf b) ++{ ++ int i; ++ FOR(i,16) o[i]=a[i]+b[i]; ++} ++ ++sv Z(gf o,const gf a,const gf b) ++{ ++ int i; ++ FOR(i,16) o[i]=a[i]-b[i]; ++} ++ ++sv M(gf o,const gf a,const gf b) ++{ ++ i64 i,j,t[31]; ++ FOR(i,31) t[i]=0; ++ FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j]; ++ FOR(i,15) t[i]+=38*t[i+16]; ++ FOR(i,16) o[i]=t[i]; ++ car25519(o); ++ car25519(o); ++} ++ ++sv S(gf o,const gf a) ++{ ++ M(o,a,a); ++} ++ ++sv inv25519(gf o,const gf i) ++{ ++ gf c; ++ int a; ++ FOR(a,16) c[a]=i[a]; ++ for(a=253;a>=0;a--) { ++ S(c,c); ++ if(a!=2&&a!=4) M(c,c,i); ++ } ++ FOR(a,16) o[a]=c[a]; ++} ++ ++#if DROPBEAR_ED25519 && DROPBEAR_SIGNKEY_VERIFY ++sv pow2523(gf o,const gf i) ++{ ++ gf c; ++ int a; ++ FOR(a,16) c[a]=i[a]; ++ for(a=250;a>=0;a--) { ++ S(c,c); ++ if(a!=1) M(c,c,i); ++ } ++ FOR(a,16) o[a]=c[a]; ++} ++#endif /* DROPBEAR_ED25519 && DROPBEAR_SIGNKEY_VERIFY */ ++ ++#if DROPBEAR_CURVE25519 ++int dropbear_curve25519_scalarmult(u8 *q,const u8 *n,const u8 *p) ++{ ++ u8 z[32]; ++ i64 x[80],r,i; ++ gf a,b,c,d,e,f; ++ FOR(i,31) z[i]=n[i]; ++ z[31]=(n[31]&127)|64; ++ z[0]&=248; ++ unpack25519(x,p); ++ FOR(i,16) { ++ b[i]=x[i]; ++ d[i]=a[i]=c[i]=0; ++ } ++ a[0]=d[0]=1; ++ for(i=254;i>=0;--i) { ++ r=(z[i>>3]>>(i&7))&1; ++ sel25519(a,b,r); ++ sel25519(c,d,r); ++ A(e,a,c); ++ Z(a,a,c); ++ A(c,b,d); ++ Z(b,b,d); ++ S(d,e); ++ S(f,a); ++ M(a,c,a); ++ M(c,b,e); ++ A(e,a,c); ++ Z(a,a,c); ++ S(b,a); ++ Z(c,d,f); ++ M(a,c,_121665); ++ A(a,a,d); ++ M(c,c,a); ++ M(a,d,f); ++ M(d,b,x); ++ S(b,e); ++ sel25519(a,b,r); ++ sel25519(c,d,r); ++ } ++ FOR(i,16) { ++ x[i+16]=a[i]; ++ x[i+32]=c[i]; ++ x[i+48]=b[i]; ++ x[i+64]=d[i]; ++ } ++ inv25519(x+32,x+32); ++ M(x+16,x+16,x+32); ++ pack25519(q,x+16); ++ return 0; ++} ++#endif /* DROPBEAR_CURVE25519 */ ++ ++#if DROPBEAR_ED25519 ++static int crypto_hash(u8 *out,const u8 *m,u64 n) ++{ ++ hash_state hs; ++ ++ sha512_init(&hs); ++ sha512_process(&hs, m, n); ++ return sha512_done(&hs, out); ++} ++ ++sv add(gf p[4],gf q[4]) ++{ ++ gf a,b,c,d,t,e,f,g,h; ++ ++ Z(a, p[1], p[0]); ++ Z(t, q[1], q[0]); ++ M(a, a, t); ++ A(b, p[0], p[1]); ++ A(t, q[0], q[1]); ++ M(b, b, t); ++ M(c, p[3], q[3]); ++ M(c, c, D2); ++ M(d, p[2], q[2]); ++ A(d, d, d); ++ Z(e, b, a); ++ Z(f, d, c); ++ A(g, d, c); ++ A(h, b, a); ++ ++ M(p[0], e, f); ++ M(p[1], h, g); ++ M(p[2], g, f); ++ M(p[3], e, h); ++} ++ ++sv cswap(gf p[4],gf q[4],u8 b) ++{ ++ int i; ++ FOR(i,4) ++ sel25519(p[i],q[i],b); ++} ++ ++sv pack(u8 *r,gf p[4]) ++{ ++ gf tx, ty, zi; ++ inv25519(zi, p[2]); ++ M(tx, p[0], zi); ++ M(ty, p[1], zi); ++ pack25519(r, ty); ++ r[31] ^= par25519(tx) << 7; ++} ++ ++sv scalarmult(gf p[4],gf q[4],const u8 *s) ++{ ++ int i; ++ set25519(p[0],gf0); ++ set25519(p[1],gf1); ++ set25519(p[2],gf1); ++ set25519(p[3],gf0); ++ for (i = 255;i >= 0;--i) { ++ u8 b = (s[i/8]>>(i&7))&1; ++ cswap(p,q,b); ++ add(q,p); ++ add(p,p); ++ cswap(p,q,b); ++ } ++} ++ ++sv scalarbase(gf p[4],const u8 *s) ++{ ++ gf q[4]; ++ set25519(q[0],X); ++ set25519(q[1],Y); ++ set25519(q[2],gf1); ++ M(q[3],X,Y); ++ scalarmult(p,q,s); ++} ++ ++int dropbear_ed25519_make_key(u8 *pk,u8 *sk) ++{ ++ u8 d[64]; ++ gf p[4]; ++ ++ genrandom(sk, 32); ++ ++ crypto_hash(d, sk, 32); ++ d[0] &= 248; ++ d[31] &= 127; ++ d[31] |= 64; ++ ++ scalarbase(p,d); ++ pack(pk,p); ++ ++ return 0; ++} ++ ++static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; ++ ++sv modL(u8 *r,i64 x[64]) ++{ ++ i64 carry,i,j; ++ for (i = 63;i >= 32;--i) { ++ carry = 0; ++ for (j = i - 32;j < i - 12;++j) { ++ x[j] += carry - 16 * x[i] * L[j - (i - 32)]; ++ carry = (x[j] + 128) >> 8; ++ x[j] -= carry << 8; ++ } ++ x[j] += carry; ++ x[i] = 0; ++ } ++ carry = 0; ++ FOR(j,32) { ++ x[j] += carry - (x[31] >> 4) * L[j]; ++ carry = x[j] >> 8; ++ x[j] &= 255; ++ } ++ FOR(j,32) x[j] -= carry * L[j]; ++ FOR(i,32) { ++ x[i+1] += x[i] >> 8; ++ r[i] = x[i] & 255; ++ } ++} ++ ++sv reduce(u8 *r) ++{ ++ i64 x[64],i; ++ FOR(i,64) x[i] = (u64) r[i]; ++ FOR(i,64) r[i] = 0; ++ modL(r,x); ++} ++ ++int dropbear_ed25519_sign(const u8 *m,u32 mlen,u8 *s,u32 *slen,const u8 *sk, const u8 *pk) ++{ ++ hash_state hs; ++ u8 d[64],h[64],r[64]; ++ i64 x[64]; ++ gf p[4]; ++ u32 i,j; ++ ++ crypto_hash(d, sk, 32); ++ d[0] &= 248; ++ d[31] &= 127; ++ d[31] |= 64; ++ ++ *slen = 64; ++ ++ sha512_init(&hs); ++ sha512_process(&hs,d + 32,32); ++ sha512_process(&hs,m,mlen); ++ sha512_done(&hs,r); ++ reduce(r); ++ scalarbase(p,r); ++ pack(s,p); ++ ++ sha512_init(&hs); ++ sha512_process(&hs,s,32); ++ sha512_process(&hs,pk,32); ++ sha512_process(&hs,m,mlen); ++ sha512_done(&hs,h); ++ reduce(h); ++ ++ FOR(i,64) x[i] = 0; ++ FOR(i,32) x[i] = (u64) r[i]; ++ FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; ++ modL(s + 32,x); ++ ++ return 0; ++} ++ ++#if DROPBEAR_SIGNKEY_VERIFY ++static int unpackneg(gf r[4],const u8 p[32]) ++{ ++ gf t, chk, num, den, den2, den4, den6; ++ set25519(r[2],gf1); ++ unpack25519(r[1],p); ++ S(num,r[1]); ++ M(den,num,D); ++ Z(num,num,r[2]); ++ A(den,r[2],den); ++ ++ S(den2,den); ++ S(den4,den2); ++ M(den6,den4,den2); ++ M(t,den6,num); ++ M(t,t,den); ++ ++ pow2523(t,t); ++ M(t,t,num); ++ M(t,t,den); ++ M(t,t,den); ++ M(r[0],t,den); ++ ++ S(chk,r[0]); ++ M(chk,chk,den); ++ if (neq25519(chk, num)) M(r[0],r[0],I); ++ ++ S(chk,r[0]); ++ M(chk,chk,den); ++ if (neq25519(chk, num)) return -1; ++ ++ if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]); ++ ++ M(r[3],r[0],r[1]); ++ return 0; ++} ++ ++int dropbear_ed25519_verify(const u8 *m,u32 mlen,const u8 *s,u32 slen,const u8 *pk) ++{ ++ hash_state hs; ++ u8 t[32],h[64]; ++ gf p[4],q[4]; ++ ++ if (slen < 64) return -1; ++ ++ if (unpackneg(q,pk)) return -1; ++ ++ sha512_init(&hs); ++ sha512_process(&hs,s,32); ++ sha512_process(&hs,pk,32); ++ sha512_process(&hs,m,mlen); ++ sha512_done(&hs,h); ++ ++ reduce(h); ++ scalarmult(p,q,h); ++ ++ scalarbase(q,s + 32); ++ add(p,q); ++ pack(t,p); ++ ++ if (crypto_verify_32(s, t)) ++ return -1; ++ ++ return 0; ++} ++#endif /* DROPBEAR_SIGNKEY_VERIFY */ ++ ++#endif /* DROPBEAR_ED25519 */ ++ ++#endif /* DROPBEAR_CURVE25519 || DROPBEAR_ED25519 */ +diff --git a/curve25519.h b/curve25519.h +new file mode 100644 +index 0000000..7f75aed +--- /dev/null ++++ b/curve25519.h +@@ -0,0 +1,37 @@ ++/* ++ * Dropbear - a SSH2 server ++ * ++ * Copyright (c) 2002,2003 Matt Johnston ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. */ ++ ++#ifndef DROPBEAR_CURVE25519_H ++#define DROPBEAR_CURVE25519_H ++ ++int dropbear_curve25519_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p); ++int dropbear_ed25519_make_key(unsigned char *pk, unsigned char *sk); ++int dropbear_ed25519_sign(const unsigned char *m, unsigned long mlen, ++ unsigned char *s, unsigned long *slen, ++ const unsigned char *sk, const unsigned char *pk); ++int dropbear_ed25519_verify(const unsigned char *m, unsigned long mlen, ++ const unsigned char *s, unsigned long slen, ++ const unsigned char *pk); ++ ++#endif /* DROPBEAR_CURVE25519_H */ +diff --git a/default_options.h b/default_options.h +index 9000fcc..5b232dd 100644 +--- a/default_options.h ++++ b/default_options.h +@@ -22,6 +22,7 @@ IMPORTANT: Some options will require "make clean" after changes */ + #define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key" + #define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_host_key" + #define ECDSA_PRIV_FILENAME "/etc/dropbear/dropbear_ecdsa_host_key" ++#define ED25519_PRIV_FILENAME "/etc/dropbear/dropbear_ed25519_host_key" + + /* Set NON_INETD_MODE if you require daemon functionality (ie Dropbear listens + * on chosen ports and keeps accepting connections. This is the default. +@@ -116,11 +117,15 @@ IMPORTANT: Some options will require "make clean" after changes */ + * code (either ECDSA or ECDH) increases binary size - around 30kB + * on x86-64 */ + #define DROPBEAR_ECDSA 1 ++/* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases ++ binary size - around 7,5kB on x86-64 */ ++#define DROPBEAR_ED25519 1 + + /* RSA must be >=1024 */ + #define DROPBEAR_DEFAULT_RSA_SIZE 2048 + /* DSS is always 1024 */ + /* ECDSA defaults to largest size configured, usually 521 */ ++/* Ed25519 is always 256 */ + + /* Add runtime flag "-R" to generate hostkeys as-needed when the first + connection using that key type occurs. +@@ -143,7 +148,7 @@ IMPORTANT: Some options will require "make clean" after changes */ + * group14 is supported by most implementations. + * group16 provides a greater strength level but is slower and increases binary size + * curve25519 and ecdh algorithms are faster than non-elliptic curve methods +- * curve25519 increases binary size by ~8kB on x86-64 ++ * curve25519 increases binary size by ~2,5kB on x86-64 + * including either ECDH or ECDSA increases binary size by ~30kB on x86-64 + + * Small systems should generally include either curve25519 or ecdh for performance. +diff --git a/dropbear.8 b/dropbear.8 +index 71c955a..345954f 100644 +--- a/dropbear.8 ++++ b/dropbear.8 +@@ -107,7 +107,7 @@ Print the version + Authorized Keys + + ~/.ssh/authorized_keys can be set up to allow remote login with a RSA, +-ECDSA, or DSS ++ECDSA, Ed25519 or DSS + key. Each line is of the form + .TP + [restrictions] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIgAsp... [comment] +@@ -146,8 +146,8 @@ key authentication. + Host Key Files + + Host key files are read at startup from a standard location, by default +-/etc/dropbear/dropbear_dss_host_key, /etc/dropbear/dropbear_rsa_host_key, and +-/etc/dropbear/dropbear_ecdsa_host_key ++/etc/dropbear/dropbear_dss_host_key, /etc/dropbear/dropbear_rsa_host_key, ++/etc/dropbear/dropbear_ecdsa_host_key and /etc/dropbear/dropbear_ed25519_host_key + + If the -r command line option is specified the default files are not loaded. + Host key files are of the form generated by dropbearkey. +diff --git a/dropbearkey.c b/dropbearkey.c +index dd0e697..f881855 100644 +--- a/dropbearkey.c ++++ b/dropbearkey.c +@@ -43,6 +43,10 @@ + * mp_int y + * mp_int x + * ++ * Ed25519: ++ * string "ssh-ed25519" ++ * string k (32 bytes) + A (32 bytes) ++ * + */ + #include "includes.h" + #include "signkey.h" +@@ -51,6 +55,7 @@ + + #include "genrsa.h" + #include "gendss.h" ++#include "gened25519.h" + #include "ecdsa.h" + #include "crypto_desc.h" + #include "dbrandom.h" +@@ -75,6 +80,9 @@ static void printhelp(char * progname) { + #endif + #if DROPBEAR_ECDSA + " ecdsa\n" ++#endif ++#if DROPBEAR_ED25519 ++ " ed25519\n" + #endif + "-f filename Use filename for the secret key.\n" + " ~/.ssh/id_dropbear is recommended for client keys.\n" +@@ -94,6 +102,9 @@ static void printhelp(char * progname) { + "521 " + #endif + "\n" ++#endif ++#if DROPBEAR_ED25519 ++ " Ed25519 has a fixed size of 256 bits\n" + #endif + "-y Just print the publickey and fingerprint for the\n private key in .\n" + #if DEBUG_TRACE +@@ -106,6 +117,14 @@ static void printhelp(char * progname) { + static void check_signkey_bits(enum signkey_type type, int bits) + { + switch (type) { ++#if DROPBEAR_ED25519 ++ case DROPBEAR_SIGNKEY_ED25519: ++ if (bits != 256) { ++ dropbear_exit("Ed25519 keys have a fixed size of 256 bits\n"); ++ exit(EXIT_FAILURE); ++ } ++ break; ++#endif + #if DROPBEAR_RSA + case DROPBEAR_SIGNKEY_RSA: + if (bits < 512 || bits > 4096 || (bits % 8 != 0)) { +@@ -224,6 +243,12 @@ int main(int argc, char ** argv) { + keytype = DROPBEAR_SIGNKEY_ECDSA_KEYGEN; + } + #endif ++#if DROPBEAR_ED25519 ++ if (strcmp(typetext, "ed25519") == 0) ++ { ++ keytype = DROPBEAR_SIGNKEY_ED25519; ++ } ++#endif + + if (keytype == DROPBEAR_SIGNKEY_NONE) { + fprintf(stderr, "Unknown key type '%s'\n", typetext); +diff --git a/ed25519.c b/ed25519.c +new file mode 100644 +index 0000000..3fb544c +--- /dev/null ++++ b/ed25519.c +@@ -0,0 +1,184 @@ ++/* ++ * Dropbear - a SSH2 server ++ * ++ * Copyright (c) 2002,2003 Matt Johnston ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. */ ++ ++/* Perform Ed25519 operations on data, including reading keys, signing and ++ * verification. */ ++ ++#include "includes.h" ++#include "dbutil.h" ++#include "buffer.h" ++#include "ssh.h" ++#include "curve25519.h" ++#include "ed25519.h" ++ ++#if DROPBEAR_ED25519 ++ ++/* Load a public ed25519 key from a buffer, initialising the values. ++ * The key will have the same format as buf_put_ed25519_key. ++ * These should be freed with ed25519_key_free. ++ * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ ++int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key) { ++ ++ unsigned int len; ++ ++ TRACE(("enter buf_get_ed25519_pub_key")) ++ dropbear_assert(key != NULL); ++ ++ buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */ ++ ++ len = buf_getint(buf); ++ if (len != CURVE25519_LEN || buf->len - buf->pos < len) { ++ TRACE(("leave buf_get_ed25519_pub_key: failure")) ++ return DROPBEAR_FAILURE; ++ } ++ ++ m_burn(key->priv, CURVE25519_LEN); ++ memcpy(key->pub, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN); ++ buf_incrpos(buf, CURVE25519_LEN); ++ ++ TRACE(("leave buf_get_ed25519_pub_key: success")) ++ return DROPBEAR_SUCCESS; ++} ++ ++/* Same as buf_get_ed25519_pub_key, but reads private key at the end. ++ * Loads a public and private ed25519 key from a buffer ++ * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ ++int buf_get_ed25519_priv_key(buffer *buf, dropbear_ed25519_key *key) { ++ ++ unsigned int len; ++ ++ TRACE(("enter buf_get_ed25519_priv_key")) ++ dropbear_assert(key != NULL); ++ ++ buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */ ++ ++ len = buf_getint(buf); ++ if (len != CURVE25519_LEN*2 || buf->len - buf->pos < len) { ++ TRACE(("leave buf_get_ed25519_priv_key: failure")) ++ return DROPBEAR_FAILURE; ++ } ++ ++ memcpy(key->priv, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN); ++ buf_incrpos(buf, CURVE25519_LEN); ++ memcpy(key->pub, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN); ++ buf_incrpos(buf, CURVE25519_LEN); ++ ++ TRACE(("leave buf_get_ed25519_pub_key: success")) ++ return DROPBEAR_SUCCESS; ++} ++ ++/* Clear and free the memory used by a public or private key */ ++void ed25519_key_free(dropbear_ed25519_key *key) { ++ ++ TRACE2(("enter ed25519_key_free")) ++ ++ if (key == NULL) { ++ TRACE2(("leave ed25519_key_free: key == NULL")) ++ return; ++ } ++ m_burn(key->priv, CURVE25519_LEN); ++ m_free(key); ++ ++ TRACE2(("leave rsa_key_free")) ++} ++ ++/* Put the public ed25519 key into the buffer in the required format */ ++void buf_put_ed25519_pub_key(buffer *buf, const dropbear_ed25519_key *key) { ++ ++ TRACE(("enter buf_put_ed25519_pub_key")) ++ dropbear_assert(key != NULL); ++ ++ buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN); ++ buf_putstring(buf, key->pub, CURVE25519_LEN); ++ ++ TRACE(("leave buf_put_ed25519_pub_key")) ++} ++ ++/* Put the public and private ed25519 key into the buffer in the required format */ ++void buf_put_ed25519_priv_key(buffer *buf, const dropbear_ed25519_key *key) { ++ ++ TRACE(("enter buf_put_ed25519_priv_key")) ++ dropbear_assert(key != NULL); ++ ++ buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN); ++ buf_putint(buf, CURVE25519_LEN*2); ++ buf_putbytes(buf, key->priv, CURVE25519_LEN); ++ buf_putbytes(buf, key->pub, CURVE25519_LEN); ++ ++ TRACE(("leave buf_put_ed25519_priv_key")) ++} ++ ++/* Sign the data presented with key, writing the signature contents ++ * to the buffer */ ++void buf_put_ed25519_sign(buffer* buf, const dropbear_ed25519_key *key, const buffer *data_buf) { ++ ++ unsigned char s[64]; ++ unsigned long slen = sizeof(s); ++ ++ TRACE(("enter buf_put_ed25519_sign")) ++ dropbear_assert(key != NULL); ++ ++ if (dropbear_ed25519_sign(data_buf->data, data_buf->len, ++ s, &slen, key->priv, key->pub) == 0) { ++ buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN); ++ buf_putstring(buf, s, slen); ++ } ++ ++ TRACE(("leave buf_put_ed25519_sign")) ++} ++ ++#if DROPBEAR_SIGNKEY_VERIFY ++/* Verify a signature in buf, made on data by the key given. ++ * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ ++int buf_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf) { ++ ++ int ret = DROPBEAR_FAILURE; ++ unsigned char *s; ++ unsigned long slen; ++ ++ TRACE(("enter buf_ed25519_verify")) ++ dropbear_assert(key != NULL); ++ ++ slen = buf_getint(buf); ++ if (slen != 64 || buf->len - buf->pos < slen) { ++ TRACE(("bad size")) ++ goto out; ++ } ++ s = buf_getptr(buf, slen); ++ ++ if (dropbear_ed25519_verify(data_buf->data, data_buf->len, ++ s, slen, key->pub) == 0) { ++ /* signature is valid */ ++ TRACE(("success!")) ++ ret = DROPBEAR_SUCCESS; ++ } ++ ++out: ++ TRACE(("leave buf_ed25519_verify: ret %d", ret)) ++ return ret; ++} ++ ++#endif /* DROPBEAR_SIGNKEY_VERIFY */ ++ ++#endif /* DROPBEAR_ED25519 */ +diff --git a/ed25519.h b/ed25519.h +new file mode 100644 +index 0000000..16c0d7b +--- /dev/null ++++ b/ed25519.h +@@ -0,0 +1,54 @@ ++/* ++ * Dropbear - a SSH2 server ++ * ++ * Copyright (c) 2002,2003 Matt Johnston ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. */ ++ ++#ifndef DROPBEAR_ED25519_H_ ++#define DROPBEAR_ED25519_H_ ++ ++#include "includes.h" ++#include "buffer.h" ++ ++#if DROPBEAR_ED25519 ++ ++#define CURVE25519_LEN 32 ++ ++typedef struct { ++ ++ unsigned char priv[CURVE25519_LEN]; ++ unsigned char pub[CURVE25519_LEN]; ++ ++} dropbear_ed25519_key; ++ ++void buf_put_ed25519_sign(buffer* buf, const dropbear_ed25519_key *key, const buffer *data_buf); ++#if DROPBEAR_SIGNKEY_VERIFY ++int buf_ed25519_verify(buffer * buf, const dropbear_ed25519_key *key, const buffer *data_buf); ++#endif ++int buf_get_ed25519_pub_key(buffer* buf, dropbear_ed25519_key *key); ++int buf_get_ed25519_priv_key(buffer* buf, dropbear_ed25519_key *key); ++void buf_put_ed25519_pub_key(buffer* buf, const dropbear_ed25519_key *key); ++void buf_put_ed25519_priv_key(buffer* buf, const dropbear_ed25519_key *key); ++void ed25519_key_free(dropbear_ed25519_key *key); ++ ++#endif /* DROPBEAR_ED25519 */ ++ ++#endif /* DROPBEAR_ED25519_H_ */ +diff --git a/filelist.txt b/filelist.txt +index 8281c14..3b9bb67 100644 +--- a/filelist.txt ++++ b/filelist.txt +@@ -99,6 +99,10 @@ rsa.c RSA asymmetric crypto routines + + dss.c DSS asymmetric crypto routines + ++ed25519.c Ed25519 asymmetric crypto routines ++ ++gened25519.c Ed25519 key generation ++ + gendss.c DSS key generation + + genrsa.c RSA key generation +diff --git a/fuzz-common.c b/fuzz-common.c +index 5c90c45..b1b00f6 100644 +--- a/fuzz-common.c ++++ b/fuzz-common.c +@@ -112,6 +112,14 @@ static void load_fixed_hostkeys(void) { + dropbear_exit("failed fixed ecdsa hostkey"); + } + ++ buf_setlen(b, 0); ++ buf_putbytes(b, keyed25519, keyed25519_len); ++ buf_setpos(b, 0); ++ type = DROPBEAR_SIGNKEY_ED25519; ++ if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { ++ dropbear_exit("failed fixed ed25519 hostkey"); ++ } ++ + buf_free(b); + } + +diff --git a/fuzz-hostkeys.c b/fuzz-hostkeys.c +index dc1615d..3fff5cb 100644 +--- a/fuzz-hostkeys.c ++++ b/fuzz-hostkeys.c +@@ -127,3 +127,13 @@ unsigned char keyd[] = { + 0xf9, 0x39 + }; + unsigned int keyd_len = 458; ++unsigned char keyed25519[] = { ++ 0x00, 0x00, 0x00, 0x0b, 0x73, 0x73, 0x68, 0x2d, 0x65, 0x64, 0x32, 0x35, ++ 0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb3, 0x79, 0x06, 0xe5, ++ 0x9b, 0xe7, 0xe4, 0x6e, 0xec, 0xfe, 0xa5, 0x39, 0x21, 0x7c, 0xf6, 0x66, ++ 0x8c, 0x0b, 0x6a, 0x01, 0x09, 0x05, 0xc7, 0x4f, 0x64, 0xa8, 0x24, 0xd2, ++ 0x8d, 0xbd, 0xdd, 0xc6, 0x3c, 0x99, 0x1b, 0x2d, 0x3e, 0x33, 0x90, 0x19, ++ 0xa4, 0xd5, 0xe9, 0x23, 0xfe, 0x8e, 0xd6, 0xd4, 0xf9, 0xb1, 0x11, 0x69, ++ 0x7c, 0x57, 0x52, 0x0e, 0x41, 0xdb, 0x1b, 0x12, 0x87, 0xfa, 0xc9 ++}; ++unsigned int keyed25519_len = 83; +diff --git a/fuzzer-kexcurve25519.c b/fuzzer-kexcurve25519.c +new file mode 100644 +index 0000000..f2eab14 +--- /dev/null ++++ b/fuzzer-kexcurve25519.c +@@ -0,0 +1,72 @@ ++#include "fuzz.h" ++#include "session.h" ++#include "fuzz-wrapfd.h" ++#include "debug.h" ++#include "runopts.h" ++#include "algo.h" ++#include "bignum.h" ++ ++int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { ++ static int once = 0; ++ static struct key_context* keep_newkeys = NULL; ++ /* number of generated parameters is limited by the timeout for the first run. ++ TODO move this to the libfuzzer initialiser function instead if the timeout ++ doesn't apply there */ ++ #define NUM_PARAMS 20 ++ static struct kex_curve25519_param *curve25519_params[NUM_PARAMS]; ++ ++ if (!once) { ++ fuzz_common_setup(); ++ fuzz_svr_setup(); ++ ++ keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); ++ keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "curve25519-sha256"); ++ keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ED25519; ++ ses.newkeys = keep_newkeys; ++ ++ /* Pre-generate parameters */ ++ int i; ++ for (i = 0; i < NUM_PARAMS; i++) { ++ curve25519_params[i] = gen_kexcurve25519_param(); ++ } ++ ++ once = 1; ++ } ++ ++ if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { ++ return 0; ++ } ++ ++ m_malloc_set_epoch(1); ++ ++ if (setjmp(fuzz.jmp) == 0) { ++ /* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply() ++ with DROPBEAR_KEX_CURVE25519 */ ++ ses.newkeys = keep_newkeys; ++ ++ /* Choose from the collection of curve25519 params */ ++ unsigned int e = buf_getint(fuzz.input); ++ struct kex_curve25519_param *curve25519_param = curve25519_params[e % NUM_PARAMS]; ++ ++ buffer * ecdh_qs = buf_getstringbuf(fuzz.input); ++ ++ ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS); ++ kexcurve25519_comb_key(curve25519_param, ecdh_qs, svr_opts.hostkey); ++ ++ mp_clear(ses.dh_K); ++ m_free(ses.dh_K); ++ buf_free(ecdh_qs); ++ ++ buf_free(ses.hash); ++ buf_free(ses.session_id); ++ /* kexhashbuf is freed in kexdh_comb_key */ ++ ++ m_malloc_free_epoch(1, 0); ++ } else { ++ m_malloc_free_epoch(1, 1); ++ TRACE(("dropbear_exit longjmped")) ++ /* dropbear_exit jumped here */ ++ } ++ ++ return 0; ++} +diff --git a/gened25519.c b/gened25519.c +new file mode 100644 +index 0000000..a027914 +--- /dev/null ++++ b/gened25519.c +@@ -0,0 +1,47 @@ ++/* ++ * Dropbear - a SSH2 server ++ * ++ * Copyright (c) 2002,2003 Matt Johnston ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. */ ++ ++#include "includes.h" ++#include "dbutil.h" ++#include "dbrandom.h" ++#include "curve25519.h" ++#include "gened25519.h" ++ ++#if DROPBEAR_ED25519 ++ ++dropbear_ed25519_key * gen_ed25519_priv_key(unsigned int size) { ++ ++ dropbear_ed25519_key *key; ++ ++ if (size != 256) { ++ dropbear_exit("Ed25519 keys have a fixed size of 256 bits"); ++ } ++ ++ key = m_malloc(sizeof(*key)); ++ dropbear_ed25519_make_key(key->pub, key->priv); ++ ++ return key; ++} ++ ++#endif /* DROPBEAR_ED25519 */ +diff --git a/gened25519.h b/gened25519.h +new file mode 100644 +index 0000000..8058310 +--- /dev/null ++++ b/gened25519.h +@@ -0,0 +1,36 @@ ++/* ++ * Dropbear - a SSH2 server ++ * ++ * Copyright (c) 2002,2003 Matt Johnston ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. */ ++ ++#ifndef DROPBEAR_GENED25519_H_ ++#define DROPBEAR_GENED25519_H_ ++ ++#include "ed25519.h" ++ ++#if DROPBEAR_ED25519 ++ ++dropbear_ed25519_key * gen_ed25519_priv_key(unsigned int size); ++ ++#endif /* DROPBEAR_ED25519 */ ++ ++#endif /* DROPBEAR_GENED25519_H_ */ +diff --git a/gensignkey.c b/gensignkey.c +index 34b6f5a..674d81f 100644 +--- a/gensignkey.c ++++ b/gensignkey.c +@@ -4,6 +4,7 @@ + #include "ecdsa.h" + #include "genrsa.h" + #include "gendss.h" ++#include "gened25519.h" + #include "signkey.h" + #include "dbrandom.h" + +@@ -68,6 +69,10 @@ static int get_default_bits(enum signkey_type keytype) + return 384; + case DROPBEAR_SIGNKEY_ECDSA_NISTP256: + return 256; ++#endif ++#if DROPBEAR_ED25519 ++ case DROPBEAR_SIGNKEY_ED25519: ++ return 256; + #endif + default: + return 0; +@@ -118,6 +123,11 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename, + *signkey_key_ptr(key, keytype) = ecckey; + } + break; ++#endif ++#if DROPBEAR_ED25519 ++ case DROPBEAR_SIGNKEY_ED25519: ++ key->ed25519key = gen_ed25519_priv_key(bits); ++ break; + #endif + default: + dropbear_exit("Internal error"); +diff --git a/keyimport.c b/keyimport.c +index 7304e58..ad0c530 100644 +--- a/keyimport.c ++++ b/keyimport.c +@@ -35,6 +35,15 @@ + #include "buffer.h" + #include "dbutil.h" + #include "ecc.h" ++#include "ssh.h" ++ ++static const unsigned char OSSH_PKEY_BLOB[] = ++ "openssh-key-v1\0" /* AUTH_MAGIC */ ++ "\0\0\0\4none" /* cipher name*/ ++ "\0\0\0\4none" /* kdf name */ ++ "\0\0\0\0" /* kdf */ ++ "\0\0\0\1"; /* key num */ ++#define OSSH_PKEY_BLOBLEN (sizeof(OSSH_PKEY_BLOB) - 1) + + #if DROPBEAR_ECDSA + static const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}; +@@ -352,7 +361,7 @@ struct mpint_pos { void *start; int bytes; }; + * Code to read and write OpenSSH private keys. + */ + +-enum { OSSH_DSA, OSSH_RSA, OSSH_EC }; ++enum { OSSH_DSA, OSSH_RSA, OSSH_EC, OSSH_PKEY }; + struct openssh_key { + int type; + int encrypted; +@@ -364,11 +373,12 @@ struct openssh_key { + static struct openssh_key *load_openssh_key(const char *filename) + { + struct openssh_key *ret; ++ buffer *buf = NULL; + FILE *fp = NULL; + char buffer[256]; + char *errmsg = NULL, *p = NULL; + int headers_done; +- unsigned long len, outlen; ++ unsigned long len; + + ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key)); + ret->keyblob = NULL; +@@ -397,12 +407,15 @@ static struct openssh_key *load_openssh_key(const char *filename) + ret->type = OSSH_DSA; + else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n")) + ret->type = OSSH_EC; ++ else if (!strcmp(buffer, "-----BEGIN OPENSSH PRIVATE KEY-----\n")) ++ ret->type = OSSH_PKEY; + else { + errmsg = "Unrecognised key type"; + goto error; + } + + headers_done = 0; ++ buf = buf_new(0); + while (1) { + if (!fgets(buffer, sizeof(buffer), fp)) { + errmsg = "Unexpected end of file"; +@@ -448,20 +461,31 @@ static struct openssh_key *load_openssh_key(const char *filename) + } else { + headers_done = 1; + len = strlen(buffer); +- outlen = len*4/3; +- if (ret->keyblob_len + outlen > ret->keyblob_size) { +- ret->keyblob_size = ret->keyblob_len + outlen + 256; +- ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, +- ret->keyblob_size); +- } +- outlen = ret->keyblob_size - ret->keyblob_len; +- if (base64_decode((const unsigned char *)buffer, len, +- ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){ +- errmsg = "Error decoding base64"; +- goto error; +- } +- ret->keyblob_len += outlen; ++ buf = buf_resize(buf, buf->size + len); ++ buf_putbytes(buf, buffer, len); ++ } ++ } ++ ++ if (buf && buf->len) { ++ ret->keyblob_size = ret->keyblob_len + buf->len*4/3 + 256; ++ ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, ret->keyblob_size); ++ len = ret->keyblob_size; ++ if (base64_decode((const unsigned char *)buf->data, buf->len, ++ ret->keyblob, &len) != CRYPT_OK){ ++ errmsg = "Error decoding base64"; ++ goto error; ++ } ++ ret->keyblob_len = len; ++ } ++ ++ if (ret->type == OSSH_PKEY) { ++ if (ret->keyblob_len < OSSH_PKEY_BLOBLEN || ++ memcmp(ret->keyblob, OSSH_PKEY_BLOB, OSSH_PKEY_BLOBLEN)) { ++ errmsg = "Error decoding OpenSSH key"; ++ goto error; + } ++ ret->keyblob_len -= OSSH_PKEY_BLOBLEN; ++ memmove(ret->keyblob, ret->keyblob + OSSH_PKEY_BLOBLEN, ret->keyblob_len); + } + + if (ret->keyblob_len == 0 || !ret->keyblob) { +@@ -474,10 +498,18 @@ static struct openssh_key *load_openssh_key(const char *filename) + goto error; + } + ++ if (buf) { ++ buf_burn(buf); ++ buf_free(buf); ++ } + m_burn(buffer, sizeof(buffer)); + return ret; + + error: ++ if (buf) { ++ buf_burn(buf); ++ buf_free(buf); ++ } + m_burn(buffer, sizeof(buffer)); + if (ret) { + if (ret->keyblob) { +@@ -569,6 +601,57 @@ static sign_key *openssh_read(const char *filename, const char * UNUSED(passphra + #endif + } + ++ /* ++ * Now we have a decrypted key blob, which contains OpenSSH ++ * encoded private key. We must now untangle the OpenSSH format. ++ */ ++ if (key->type == OSSH_PKEY) { ++ blobbuf = buf_new(key->keyblob_len); ++ buf_putbytes(blobbuf, key->keyblob, key->keyblob_len); ++ buf_setpos(blobbuf, 0); ++ ++ /* limit length of private key blob */ ++ len = buf_getint(blobbuf); ++ buf_setlen(blobbuf, blobbuf->pos + len); ++ ++ type = DROPBEAR_SIGNKEY_ANY; ++ if (buf_get_pub_key(blobbuf, retkey, &type) ++ != DROPBEAR_SUCCESS) { ++ errmsg = "Error parsing OpenSSH key"; ++ goto ossh_error; ++ } ++ ++ /* restore full length */ ++ buf_setlen(blobbuf, key->keyblob_len); ++ ++ if (type != DROPBEAR_SIGNKEY_NONE) { ++ retkey->type = type; ++ /* limit length of private key blob */ ++ len = buf_getint(blobbuf); ++ buf_setlen(blobbuf, blobbuf->pos + len); ++#if DROPBEAR_ED25519 ++ if (type == DROPBEAR_SIGNKEY_ED25519) { ++ buf_incrpos(blobbuf, 8); ++ buf_eatstring(blobbuf); ++ buf_eatstring(blobbuf); ++ buf_incrpos(blobbuf, -SSH_SIGNKEY_ED25519_LEN-4); ++ if (buf_get_ed25519_priv_key(blobbuf, retkey->ed25519key) ++ == DROPBEAR_SUCCESS) { ++ errmsg = NULL; ++ retval = retkey; ++ goto error; ++ } ++ } ++#endif ++ } ++ ++ errmsg = "Unsupported OpenSSH key type"; ++ ossh_error: ++ sign_key_free(retkey); ++ retkey = NULL; ++ goto error; ++ } ++ + /* + * Now we have a decrypted key blob, which contains an ASN.1 + * encoded private key. We must now untangle the ASN.1. +@@ -1129,6 +1212,51 @@ static int openssh_write(const char *filename, sign_key *key, + } + #endif + ++#if DROPBEAR_ED25519 ++ if (key->type == DROPBEAR_SIGNKEY_ED25519) { ++ buffer *buf = buf_new(300); ++ keyblob = buf_new(100); ++ extrablob = buf_new(200); ++ ++ /* private key blob w/o header */ ++ buf_put_priv_key(keyblob, key, key->type); ++ buf_setpos(keyblob, 0); ++ buf_incrpos(keyblob, buf_getint(keyblob)); ++ len = buf_getint(keyblob); ++ ++ /* header */ ++ buf_putbytes(buf, OSSH_PKEY_BLOB, OSSH_PKEY_BLOBLEN); ++ ++ /* public key */ ++ buf_put_pub_key(buf, key, key->type); ++ ++ /* private key */ ++ buf_incrwritepos(extrablob, 4); ++ buf_put_pub_key(extrablob, key, key->type); ++ buf_putstring(extrablob, buf_getptr(keyblob, len), len); ++ /* comment */ ++ buf_putstring(extrablob, "", 0); ++ /* padding to cipher block length */ ++ len = (extrablob->len+8) & ~7; ++ for (i = 1; len - extrablob->len > 0; i++) ++ buf_putbyte(extrablob, i); ++ buf_setpos(extrablob, 0); ++ buf_putbytes(extrablob, "\0\0\0\0\0\0\0\0", 8); ++ buf_putbufstring(buf, extrablob); ++ ++ outlen = len = pos = buf->len; ++ outblob = (unsigned char*)m_malloc(outlen); ++ memcpy(outblob, buf->data, buf->len); ++ ++ buf_burn(buf); ++ buf_free(buf); ++ buf = NULL; ++ ++ header = "-----BEGIN OPENSSH PRIVATE KEY-----\n"; ++ footer = "-----END OPENSSH PRIVATE KEY-----\n"; ++ } ++#endif ++ + /* + * Padding on OpenSSH keys is deterministic. The number of + * padding bytes is always more than zero, and always at most +diff --git a/signkey.c b/signkey.c +index 88f06c7..a0af44a 100644 +--- a/signkey.c ++++ b/signkey.c +@@ -39,8 +39,11 @@ static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = { + #if DROPBEAR_ECDSA + "ecdsa-sha2-nistp256", + "ecdsa-sha2-nistp384", +- "ecdsa-sha2-nistp521" ++ "ecdsa-sha2-nistp521", + #endif /* DROPBEAR_ECDSA */ ++#if DROPBEAR_ED25519 ++ "ssh-ed25519", ++#endif /* DROPBEAR_ED25519 */ + }; + + /* malloc a new sign_key and set the dss and rsa keys to NULL */ +@@ -107,6 +110,10 @@ Be sure to check both (ret != NULL) and (*ret != NULL) */ + void ** + signkey_key_ptr(sign_key *key, enum signkey_type type) { + switch (type) { ++#if DROPBEAR_ED25519 ++ case DROPBEAR_SIGNKEY_ED25519: ++ return (void**)&key->ed25519key; ++#endif + #if DROPBEAR_ECDSA + #if DROPBEAR_ECC_256 + case DROPBEAR_SIGNKEY_ECDSA_NISTP256: +@@ -200,6 +207,17 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) { + } + } + #endif ++#if DROPBEAR_ED25519 ++ if (keytype == DROPBEAR_SIGNKEY_ED25519) { ++ ed25519_key_free(key->ed25519key); ++ key->ed25519key = m_malloc(sizeof(*key->ed25519key)); ++ ret = buf_get_ed25519_pub_key(buf, key->ed25519key); ++ if (ret == DROPBEAR_FAILURE) { ++ m_free(key->ed25519key); ++ key->ed25519key = NULL; ++ } ++ } ++#endif + + TRACE2(("leave buf_get_pub_key")) + +@@ -270,6 +288,17 @@ int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) { + } + } + #endif ++#if DROPBEAR_ED25519 ++ if (keytype == DROPBEAR_SIGNKEY_ED25519) { ++ ed25519_key_free(key->ed25519key); ++ key->ed25519key = m_malloc(sizeof(*key->ed25519key)); ++ ret = buf_get_ed25519_priv_key(buf, key->ed25519key); ++ if (ret == DROPBEAR_FAILURE) { ++ m_free(key->ed25519key); ++ key->ed25519key = NULL; ++ } ++ } ++#endif + + TRACE2(("leave buf_get_priv_key")) + +@@ -302,6 +331,11 @@ void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) { + buf_put_ecdsa_pub_key(pubkeys, *eck); + } + } ++#endif ++#if DROPBEAR_ED25519 ++ if (type == DROPBEAR_SIGNKEY_ED25519) { ++ buf_put_ed25519_pub_key(pubkeys, key->ed25519key); ++ } + #endif + if (pubkeys->len == 0) { + dropbear_exit("Bad key types in buf_put_pub_key"); +@@ -341,6 +375,13 @@ void buf_put_priv_key(buffer* buf, sign_key *key, enum signkey_type type) { + return; + } + } ++#endif ++#if DROPBEAR_ED25519 ++ if (type == DROPBEAR_SIGNKEY_ED25519) { ++ buf_put_ed25519_priv_key(buf, key->ed25519key); ++ TRACE(("leave buf_put_priv_key: ed25519 done")) ++ return; ++ } + #endif + dropbear_exit("Bad key types in put pub key"); + } +@@ -379,6 +420,10 @@ void sign_key_free(sign_key *key) { + key->ecckey521 = NULL; + } + #endif ++#endif ++#if DROPBEAR_ED25519 ++ ed25519_key_free(key->ed25519key); ++ key->ed25519key = NULL; + #endif + + m_free(key->filename); +@@ -503,6 +548,11 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type type, + buf_put_ecdsa_sign(sigblob, *eck, data_buf); + } + } ++#endif ++#if DROPBEAR_ED25519 ++ if (type == DROPBEAR_SIGNKEY_ED25519) { ++ buf_put_ed25519_sign(sigblob, key->ed25519key, data_buf); ++ } + #endif + if (sigblob->len == 0) { + dropbear_exit("Non-matching signing type"); +@@ -555,6 +605,14 @@ int buf_verify(buffer * buf, sign_key *key, const buffer *data_buf) { + } + } + #endif ++#if DROPBEAR_ED25519 ++ if (type == DROPBEAR_SIGNKEY_ED25519) { ++ if (key->ed25519key == NULL) { ++ dropbear_exit("No Ed25519 key to verify signature"); ++ } ++ return buf_ed25519_verify(buf, key->ed25519key, data_buf); ++ } ++#endif + + dropbear_exit("Non-matching signing type"); + return DROPBEAR_FAILURE; +diff --git a/signkey.h b/signkey.h +index 59df3ee..fa39a02 100644 +--- a/signkey.h ++++ b/signkey.h +@@ -28,6 +28,7 @@ + #include "buffer.h" + #include "dss.h" + #include "rsa.h" ++#include "ed25519.h" + + enum signkey_type { + #if DROPBEAR_RSA +@@ -41,6 +42,9 @@ enum signkey_type { + DROPBEAR_SIGNKEY_ECDSA_NISTP384, + DROPBEAR_SIGNKEY_ECDSA_NISTP521, + #endif /* DROPBEAR_ECDSA */ ++#if DROPBEAR_ED25519 ++ DROPBEAR_SIGNKEY_ED25519, ++#endif + DROPBEAR_SIGNKEY_NUM_NAMED, + DROPBEAR_SIGNKEY_ECDSA_KEYGEN = 70, /* just "ecdsa" for keygen */ + DROPBEAR_SIGNKEY_ANY = 80, +@@ -78,6 +82,9 @@ struct SIGN_key { + ecc_key * ecckey521; + #endif + #endif ++#if DROPBEAR_ED25519 ++ dropbear_ed25519_key * ed25519key; ++#endif + }; + + typedef struct SIGN_key sign_key; +diff --git a/ssh.h b/ssh.h +index f40b65a..db723b8 100644 +--- a/ssh.h ++++ b/ssh.h +@@ -105,6 +105,8 @@ + #define SSH_SIGNKEY_DSS_LEN 7 + #define SSH_SIGNKEY_RSA "ssh-rsa" + #define SSH_SIGNKEY_RSA_LEN 7 ++#define SSH_SIGNKEY_ED25519 "ssh-ed25519" ++#define SSH_SIGNKEY_ED25519_LEN 11 + + /* Agent commands. These aren't part of the spec, and are defined + * only on the openssh implementation. */ +diff --git a/svr-kex.c b/svr-kex.c +index 406ad97..af16d2f 100644 +--- a/svr-kex.c ++++ b/svr-kex.c +@@ -122,6 +122,11 @@ static void svr_ensure_hostkey() { + case DROPBEAR_SIGNKEY_ECDSA_NISTP521: + fn = ECDSA_PRIV_FILENAME; + break; ++#endif ++#if DROPBEAR_ED25519 ++ case DROPBEAR_SIGNKEY_ED25519: ++ fn = ED25519_PRIV_FILENAME; ++ break; + #endif + default: + dropbear_assert(0); +@@ -219,7 +224,8 @@ static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) { + { + struct kex_curve25519_param *param = gen_kexcurve25519_param(); + kexcurve25519_comb_key(param, ecdh_qs, svr_opts.hostkey); +- buf_putstring(ses.writepayload, (const char*)param->pub, CURVE25519_LEN); ++ ++ buf_putstring(ses.writepayload, param->pub, CURVE25519_LEN); + free_kexcurve25519_param(param); + } + break; +diff --git a/svr-runopts.c b/svr-runopts.c +index d7a0d5a..d430825 100644 +--- a/svr-runopts.c ++++ b/svr-runopts.c +@@ -57,6 +57,9 @@ static void printhelp(const char * progname) { + #if DROPBEAR_ECDSA + " ecdsa %s\n" + #endif ++#if DROPBEAR_ED25519 ++ " ed25519 %s\n" ++#endif + #if DROPBEAR_DELAY_HOSTKEY + "-R Create hostkeys as required\n" + #endif +@@ -116,6 +119,9 @@ static void printhelp(const char * progname) { + #endif + #if DROPBEAR_ECDSA + ECDSA_PRIV_FILENAME, ++#endif ++#if DROPBEAR_ED25519 ++ ED25519_PRIV_FILENAME, + #endif + MAX_AUTH_TRIES, + DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE, +@@ -538,6 +544,13 @@ static void loadhostkey(const char *keyfile, int fatal_duplicate) { + } + #endif + #endif /* DROPBEAR_ECDSA */ ++ ++#if DROPBEAR_ED25519 ++ if (type == DROPBEAR_SIGNKEY_ED25519) { ++ loadhostkey_helper("ed25519", (void**)&read_key->ed25519key, (void**)&svr_opts.hostkey->ed25519key, fatal_duplicate); ++ } ++#endif ++ + sign_key_free(read_key); + TRACE(("leave loadhostkey")) + } +@@ -578,6 +591,9 @@ void load_all_hostkeys() { + + #if DROPBEAR_ECDSA + loadhostkey(ECDSA_PRIV_FILENAME, 0); ++#endif ++#if DROPBEAR_ED25519 ++ loadhostkey(ED25519_PRIV_FILENAME, 0); + #endif + } + +@@ -642,6 +658,14 @@ void load_all_hostkeys() { + #endif + #endif /* DROPBEAR_ECDSA */ + ++#if DROPBEAR_ED25519 ++ if (!svr_opts.delay_hostkey && !svr_opts.hostkey->ed25519key) { ++ disablekey(DROPBEAR_SIGNKEY_ED25519); ++ } else { ++ any_keys = 1; ++ } ++#endif ++ + if (!any_keys) { + dropbear_exit("No hostkeys available. 'dropbear -R' may be useful or run dropbearkey."); + } +diff --git a/sysoptions.h b/sysoptions.h +index cfd5469..2c27caf 100644 +--- a/sysoptions.h ++++ b/sysoptions.h +@@ -145,7 +145,8 @@ If you test it please contact the Dropbear author */ + #define DROPBEAR_SHA384 (DROPBEAR_ECC_384) + /* LTC SHA384 depends on SHA512 */ + #define DROPBEAR_SHA512 ((DROPBEAR_SHA2_512_HMAC) || (DROPBEAR_ECC_521) \ +- || (DROPBEAR_SHA384) || (DROPBEAR_DH_GROUP16)) ++ || (DROPBEAR_SHA384) || (DROPBEAR_DH_GROUP16) \ ++ || (DROPBEAR_ED25519)) + #define DROPBEAR_MD5 (DROPBEAR_MD5_HMAC) + + #define DROPBEAR_DH_GROUP14 ((DROPBEAR_DH_GROUP14_SHA256) || (DROPBEAR_DH_GROUP14_SHA1)) +@@ -186,7 +187,7 @@ If you test it please contact the Dropbear author */ + /* For a 4096 bit DSS key, empirically determined */ + #define MAX_PRIVKEY_SIZE 1700 + +-#define MAX_HOSTKEYS 3 ++#define MAX_HOSTKEYS 4 + + /* The maximum size of the bignum portion of the kexhash buffer */ + /* Sect. 8 of the transport rfc 4253, K_S + e + f + K */ +@@ -252,7 +253,7 @@ If you test it please contact the Dropbear author */ + #error "At least one encryption algorithm must be enabled. AES128 is recommended." + #endif + +-#if !(DROPBEAR_RSA || DROPBEAR_DSS || DROPBEAR_ECDSA) ++#if !(DROPBEAR_RSA || DROPBEAR_DSS || DROPBEAR_ECDSA || DROPBEAR_ED25519) + #error "At least one hostkey or public-key algorithm must be enabled; RSA is recommended." + #endif + +-- +2.17.1 + diff --git a/package/network/services/dropbear/patches/021-backport-chacha20-poly1305-support.patch b/package/network/services/dropbear/patches/021-backport-chacha20-poly1305-support.patch new file mode 100644 index 0000000000..2120b4593e --- /dev/null +++ b/package/network/services/dropbear/patches/021-backport-chacha20-poly1305-support.patch @@ -0,0 +1,693 @@ +From 3cdf9ec918b37c17e12b33e4c244944d1ee836ca Mon Sep 17 00:00:00 2001 +From: Vladislav Grishenko +Date: Mon, 6 Apr 2020 23:28:09 +0500 +Subject: [PATCH] Add Chacha20-Poly1305 authenticated encryption + +* Add general AEAD approach. +* Add chacha20-poly1305@openssh.com algo using LibTomCrypt chacha and + poly1305 routines. + +Chacha20-Poly1305 is generally faster than AES256 on CPU w/o dedicated +AES instructions, having the same key size. +Compiling in will add ~5,5kB to binary size on x86-64. +--- + Makefile.in | 2 +- + algo.h | 8 ++ + chachapoly.c | 148 ++++++++++++++++++++ + chachapoly.h | 44 ++++++ + common-algo.c | 11 +- + common-kex.c | 44 ++++-- + default_options.h | 6 + + libtomcrypt/src/headers/tomcrypt_dropbear.h | 4 + + packet.c | 145 +++++++++++++------ + session.h | 4 + + sysoptions.h | 8 +- + 11 files changed, 368 insertions(+), 56 deletions(-) + create mode 100644 chachapoly.c + create mode 100644 chachapoly.h + +diff --git a/Makefile.in b/Makefile.in +index aaf7b3b..3437cb2 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -53,7 +53,7 @@ CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \ + CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \ + common-channel.o common-chansession.o termcodes.o loginrec.o \ + tcp-accept.o listener.o process-packet.o dh_groups.o \ +- common-runopts.o circbuffer.o list.o netio.o ++ common-runopts.o circbuffer.o list.o netio.o chachapoly.o + + KEYOBJS=dropbearkey.o + +diff --git a/algo.h b/algo.h +index b12fb94..efd0d73 100644 +--- a/algo.h ++++ b/algo.h +@@ -72,6 +72,14 @@ struct dropbear_cipher_mode { + unsigned long len, void *cipher_state); + int (*decrypt)(const unsigned char *ct, unsigned char *pt, + unsigned long len, void *cipher_state); ++ int (*aead_crypt)(unsigned int seq, ++ const unsigned char *in, unsigned char *out, ++ unsigned long len, unsigned long taglen, ++ void *cipher_state, int direction); ++ int (*aead_getlength)(unsigned int seq, ++ const unsigned char *in, unsigned int *outlen, ++ unsigned long len, void *cipher_state); ++ const struct dropbear_hash *aead_mac; + }; + + struct dropbear_hash { +diff --git a/chachapoly.c b/chachapoly.c +new file mode 100644 +index 0000000..8fb06c5 +--- /dev/null ++++ b/chachapoly.c +@@ -0,0 +1,148 @@ ++/* ++ * Dropbear SSH ++ * ++ * Copyright (c) 2002,2003 Matt Johnston ++ * Copyright (c) 2020 by Vladislav Grishenko ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. */ ++ ++#include "includes.h" ++#include "algo.h" ++#include "dbutil.h" ++#include "chachapoly.h" ++ ++#if DROPBEAR_CHACHA20POLY1305 ++ ++#define CHACHA20_KEY_LEN 32 ++#define CHACHA20_BLOCKSIZE 8 ++#define POLY1305_KEY_LEN 32 ++#define POLY1305_TAG_LEN 16 ++ ++static const struct ltc_cipher_descriptor dummy = {.name = NULL}; ++ ++static const struct dropbear_hash dropbear_chachapoly_mac = ++ {NULL, POLY1305_KEY_LEN, POLY1305_TAG_LEN}; ++ ++const struct dropbear_cipher dropbear_chachapoly = ++ {&dummy, CHACHA20_KEY_LEN*2, CHACHA20_BLOCKSIZE}; ++ ++static int dropbear_chachapoly_start(int UNUSED(cipher), const unsigned char* UNUSED(IV), ++ const unsigned char *key, int keylen, ++ int UNUSED(num_rounds), dropbear_chachapoly_state *state) { ++ int err; ++ ++ TRACE2(("enter dropbear_chachapoly_start")) ++ ++ if (keylen != CHACHA20_KEY_LEN*2) { ++ return CRYPT_ERROR; ++ } ++ ++ if ((err = chacha_setup(&state->chacha, key, ++ CHACHA20_KEY_LEN, 20)) != CRYPT_OK) { ++ return err; ++ } ++ ++ if ((err = chacha_setup(&state->header, key + CHACHA20_KEY_LEN, ++ CHACHA20_KEY_LEN, 20) != CRYPT_OK)) { ++ return err; ++ } ++ ++ TRACE2(("leave dropbear_chachapoly_start")) ++ return CRYPT_OK; ++} ++ ++static int dropbear_chachapoly_crypt(unsigned int seq, ++ const unsigned char *in, unsigned char *out, ++ unsigned long len, unsigned long taglen, ++ dropbear_chachapoly_state *state, int direction) { ++ poly1305_state poly; ++ unsigned char seqbuf[8], key[POLY1305_KEY_LEN], tag[POLY1305_TAG_LEN]; ++ int err; ++ ++ TRACE2(("enter dropbear_chachapoly_crypt")) ++ ++ if (len < 4 || taglen != POLY1305_TAG_LEN) { ++ return CRYPT_ERROR; ++ } ++ ++ STORE64H((uint64_t)seq, seqbuf); ++ chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 0); ++ if ((err = chacha_keystream(&state->chacha, key, sizeof(key))) != CRYPT_OK) { ++ return err; ++ } ++ ++ poly1305_init(&poly, key, sizeof(key)); ++ if (direction == LTC_DECRYPT) { ++ poly1305_process(&poly, in, len); ++ poly1305_done(&poly, tag, &taglen); ++ if (constant_time_memcmp(in + len, tag, taglen) != 0) { ++ return CRYPT_ERROR; ++ } ++ } ++ ++ chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0); ++ if ((err = chacha_crypt(&state->header, in, 4, out)) != CRYPT_OK) { ++ return err; ++ } ++ ++ chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 1); ++ if ((err = chacha_crypt(&state->chacha, in + 4, len - 4, out + 4)) != CRYPT_OK) { ++ return err; ++ } ++ ++ if (direction == LTC_ENCRYPT) { ++ poly1305_process(&poly, out, len); ++ poly1305_done(&poly, out + len, &taglen); ++ } ++ ++ TRACE2(("leave dropbear_chachapoly_crypt")) ++ return CRYPT_OK; ++} ++ ++static int dropbear_chachapoly_getlength(unsigned int seq, ++ const unsigned char *in, unsigned int *outlen, ++ unsigned long len, dropbear_chachapoly_state *state) { ++ unsigned char seqbuf[8], buf[4]; ++ int err; ++ ++ TRACE2(("enter dropbear_chachapoly_getlength")) ++ ++ if (len < sizeof(buf)) { ++ return CRYPT_ERROR; ++ } ++ ++ STORE64H((uint64_t)seq, seqbuf); ++ chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0); ++ if ((err = chacha_crypt(&state->header, in, sizeof(buf), buf)) != CRYPT_OK) { ++ return err; ++ } ++ ++ LOAD32H(*outlen, buf); ++ ++ TRACE2(("leave dropbear_chachapoly_getlength")) ++ return CRYPT_OK; ++} ++ ++const struct dropbear_cipher_mode dropbear_mode_chachapoly = ++ {(void *)dropbear_chachapoly_start, NULL, NULL, ++ (void *)dropbear_chachapoly_crypt, ++ (void *)dropbear_chachapoly_getlength, &dropbear_chachapoly_mac}; ++ ++#endif /* DROPBEAR_CHACHA20POLY1305 */ +diff --git a/chachapoly.h b/chachapoly.h +new file mode 100644 +index 0000000..5a7c5b2 +--- /dev/null ++++ b/chachapoly.h +@@ -0,0 +1,44 @@ ++/* ++ * Dropbear SSH ++ * ++ * Copyright (c) 2002,2003 Matt Johnston ++ * Copyright (c) 2020 by Vladislav Grishenko ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. */ ++ ++#ifndef DROPBEAR_DROPBEAR_CHACHAPOLY_H_ ++#define DROPBEAR_DROPBEAR_CHACHAPOLY_H_ ++ ++#include "includes.h" ++#include "algo.h" ++ ++#if DROPBEAR_CHACHA20POLY1305 ++ ++typedef struct { ++ chacha_state chacha; ++ chacha_state header; ++} dropbear_chachapoly_state; ++ ++extern const struct dropbear_cipher dropbear_chachapoly; ++extern const struct dropbear_cipher_mode dropbear_mode_chachapoly; ++ ++#endif /* DROPBEAR_CHACHA20POLY1305 */ ++ ++#endif /* DROPBEAR_DROPBEAR_CHACHAPOLY_H_ */ +diff --git a/common-algo.c b/common-algo.c +index 558aad2..1436456 100644 +--- a/common-algo.c ++++ b/common-algo.c +@@ -30,6 +30,7 @@ + #include "dh_groups.h" + #include "ltc_prng.h" + #include "ecc.h" ++#include "chachapoly.h" + + /* This file (algo.c) organises the ciphers which can be used, and is used to + * decide which ciphers/hashes/compression/signing to use during key exchange*/ +@@ -86,11 +87,11 @@ const struct dropbear_cipher dropbear_nocipher = + * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */ + #if DROPBEAR_ENABLE_CBC_MODE + const struct dropbear_cipher_mode dropbear_mode_cbc = +- {(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt}; ++ {(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt, NULL, NULL, NULL}; + #endif /* DROPBEAR_ENABLE_CBC_MODE */ + + const struct dropbear_cipher_mode dropbear_mode_none = +- {void_start, void_cipher, void_cipher}; ++ {void_start, void_cipher, void_cipher, NULL, NULL, NULL}; + + #if DROPBEAR_ENABLE_CTR_MODE + /* a wrapper to make ctr_start and cbc_start look the same */ +@@ -101,7 +102,7 @@ static int dropbear_big_endian_ctr_start(int cipher, + return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr); + } + const struct dropbear_cipher_mode dropbear_mode_ctr = +- {(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt}; ++ {(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt, NULL, NULL, NULL}; + #endif /* DROPBEAR_ENABLE_CTR_MODE */ + + /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc. +@@ -137,6 +138,10 @@ const struct dropbear_hash dropbear_nohash = + * that is also supported by the server will get used. */ + + algo_type sshciphers[] = { ++#if DROPBEAR_CHACHA20POLY1305 ++ {"chacha20-poly1305@openssh.com", 0, &dropbear_chachapoly, 1, &dropbear_mode_chachapoly}, ++#endif ++ + #if DROPBEAR_ENABLE_CTR_MODE + #if DROPBEAR_AES128 + {"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr}, +diff --git a/common-kex.c b/common-kex.c +index 16b7e27..5e2923f 100644 +--- a/common-kex.c ++++ b/common-kex.c +@@ -329,9 +329,12 @@ static void gen_new_keys() { + hashkeys(S2C_key, sizeof(S2C_key), &hs, 'D'); + + if (ses.newkeys->recv.algo_crypt->cipherdesc != NULL) { +- int recv_cipher = find_cipher(ses.newkeys->recv.algo_crypt->cipherdesc->name); +- if (recv_cipher < 0) +- dropbear_exit("Crypto error"); ++ int recv_cipher = -1; ++ if (ses.newkeys->recv.algo_crypt->cipherdesc->name != NULL) { ++ recv_cipher = find_cipher(ses.newkeys->recv.algo_crypt->cipherdesc->name); ++ if (recv_cipher < 0) ++ dropbear_exit("Crypto error"); ++ } + if (ses.newkeys->recv.crypt_mode->start(recv_cipher, + recv_IV, recv_key, + ses.newkeys->recv.algo_crypt->keysize, 0, +@@ -341,9 +344,12 @@ static void gen_new_keys() { + } + + if (ses.newkeys->trans.algo_crypt->cipherdesc != NULL) { +- int trans_cipher = find_cipher(ses.newkeys->trans.algo_crypt->cipherdesc->name); +- if (trans_cipher < 0) +- dropbear_exit("Crypto error"); ++ int trans_cipher = -1; ++ if (ses.newkeys->trans.algo_crypt->cipherdesc->name != NULL) { ++ trans_cipher = find_cipher(ses.newkeys->trans.algo_crypt->cipherdesc->name); ++ if (trans_cipher < 0) ++ dropbear_exit("Crypto error"); ++ } + if (ses.newkeys->trans.crypt_mode->start(trans_cipher, + trans_IV, trans_key, + ses.newkeys->trans.algo_crypt->keysize, 0, +@@ -868,19 +874,29 @@ static void read_kex_algos() { + + /* mac_algorithms_client_to_server */ + c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL); ++#if DROPBEAR_AEAD_MODE ++ if (((struct dropbear_cipher_mode*)c2s_cipher_algo->mode)->aead_crypt != NULL) { ++ c2s_hash_algo = NULL; ++ } else ++#endif + if (c2s_hash_algo == NULL) { + erralgo = "mac c->s"; + goto error; + } +- TRACE(("hash c2s is %s", c2s_hash_algo->name)) ++ TRACE(("hash c2s is %s", c2s_hash_algo ? c2s_hash_algo->name : "")) + + /* mac_algorithms_server_to_client */ + s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL); ++#if DROPBEAR_AEAD_MODE ++ if (((struct dropbear_cipher_mode*)s2c_cipher_algo->mode)->aead_crypt != NULL) { ++ s2c_hash_algo = NULL; ++ } else ++#endif + if (s2c_hash_algo == NULL) { + erralgo = "mac s->c"; + goto error; + } +- TRACE(("hash s2c is %s", s2c_hash_algo->name)) ++ TRACE(("hash s2c is %s", s2c_hash_algo ? s2c_hash_algo->name : "")) + + /* compression_algorithms_client_to_server */ + c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL); +@@ -925,8 +941,14 @@ static void read_kex_algos() { + ses.newkeys->trans.crypt_mode = + (struct dropbear_cipher_mode*)c2s_cipher_algo->mode; + ses.newkeys->recv.algo_mac = ++#if DROPBEAR_AEAD_MODE ++ s2c_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac : ++#endif + (struct dropbear_hash*)s2c_hash_algo->data; + ses.newkeys->trans.algo_mac = ++#if DROPBEAR_AEAD_MODE ++ c2s_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac : ++#endif + (struct dropbear_hash*)c2s_hash_algo->data; + ses.newkeys->recv.algo_comp = s2c_comp_algo->val; + ses.newkeys->trans.algo_comp = c2s_comp_algo->val; +@@ -941,8 +963,14 @@ static void read_kex_algos() { + ses.newkeys->trans.crypt_mode = + (struct dropbear_cipher_mode*)s2c_cipher_algo->mode; + ses.newkeys->recv.algo_mac = ++#if DROPBEAR_AEAD_MODE ++ c2s_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac : ++#endif + (struct dropbear_hash*)c2s_hash_algo->data; + ses.newkeys->trans.algo_mac = ++#if DROPBEAR_AEAD_MODE ++ s2c_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac : ++#endif + (struct dropbear_hash*)s2c_hash_algo->data; + ses.newkeys->recv.algo_comp = c2s_comp_algo->val; + ses.newkeys->trans.algo_comp = s2c_comp_algo->val; +diff --git a/default_options.h b/default_options.h +index bafbb07..1a2ab10 100644 +--- a/default_options.h ++++ b/default_options.h +@@ -99,6 +99,12 @@ IMPORTANT: Some options will require "make clean" after changes */ + * and forwards compatibility */ + #define DROPBEAR_ENABLE_CTR_MODE 1 + ++/* Enable Chacha20-Poly1305 authenticated encryption mode. This is ++ * generally faster than AES256 on CPU w/o dedicated AES instructions, ++ * having the same key size. ++ * Compiling in will add ~5,5kB to binary size on x86-64 */ ++#define DROPBEAR_CHACHA20POLY1305 1 ++ + /* Message integrity. sha2-256 is recommended as a default, + sha1 for compatibility */ + #define DROPBEAR_SHA1_HMAC 1 +diff --git a/libtomcrypt/src/headers/tomcrypt_dropbear.h b/libtomcrypt/src/headers/tomcrypt_dropbear.h +index b0ce45b..59960e5 100644 +--- a/libtomcrypt/src/headers/tomcrypt_dropbear.h ++++ b/libtomcrypt/src/headers/tomcrypt_dropbear.h +@@ -35,6 +35,10 @@ + #define LTC_CTR_MODE + #endif + ++#if DROPBEAR_CHACHA20POLY1305 ++#define LTC_CHACHA ++#define LTC_POLY1305 ++#endif + + #if DROPBEAR_SHA512 + #define LTC_SHA512 +diff --git a/packet.c b/packet.c +index 9fda0d6..0454726 100644 +--- a/packet.c ++++ b/packet.c +@@ -215,7 +215,7 @@ static int read_packet_init() { + + unsigned int maxlen; + int slen; +- unsigned int len; ++ unsigned int len, plen; + unsigned int blocksize; + unsigned int macsize; + +@@ -254,21 +254,35 @@ static int read_packet_init() { + /* now we have the first block, need to get packet length, so we decrypt + * the first block (only need first 4 bytes) */ + buf_setpos(ses.readbuf, 0); +- if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), +- buf_getwriteptr(ses.readbuf, blocksize), +- blocksize, +- &ses.keys->recv.cipher_state) != CRYPT_OK) { +- dropbear_exit("Error decrypting"); ++#if DROPBEAR_AEAD_MODE ++ if (ses.keys->recv.crypt_mode->aead_crypt) { ++ if (ses.keys->recv.crypt_mode->aead_getlength(ses.recvseq, ++ buf_getptr(ses.readbuf, blocksize), &plen, ++ blocksize, ++ &ses.keys->recv.cipher_state) != CRYPT_OK) { ++ dropbear_exit("Error decrypting"); ++ } ++ len = plen + 4 + macsize; ++ } else ++#endif ++ { ++ if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), ++ buf_getwriteptr(ses.readbuf, blocksize), ++ blocksize, ++ &ses.keys->recv.cipher_state) != CRYPT_OK) { ++ dropbear_exit("Error decrypting"); ++ } ++ plen = buf_getint(ses.readbuf) + 4; ++ len = plen + macsize; + } +- len = buf_getint(ses.readbuf) + 4 + macsize; + + TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize)) + + + /* check packet length */ + if ((len > RECV_MAX_PACKET_LEN) || +- (len < MIN_PACKET_LEN + macsize) || +- ((len - macsize) % blocksize != 0)) { ++ (plen < blocksize) || ++ (plen % blocksize != 0)) { + dropbear_exit("Integrity error (bad packet size %u)", len); + } + +@@ -294,23 +308,42 @@ void decrypt_packet() { + + ses.kexstate.datarecv += ses.readbuf->len; + +- /* we've already decrypted the first blocksize in read_packet_init */ +- buf_setpos(ses.readbuf, blocksize); +- +- /* decrypt it in-place */ +- len = ses.readbuf->len - macsize - ses.readbuf->pos; +- if (ses.keys->recv.crypt_mode->decrypt( +- buf_getptr(ses.readbuf, len), +- buf_getwriteptr(ses.readbuf, len), +- len, +- &ses.keys->recv.cipher_state) != CRYPT_OK) { +- dropbear_exit("Error decrypting"); +- } +- buf_incrpos(ses.readbuf, len); ++#if DROPBEAR_AEAD_MODE ++ if (ses.keys->recv.crypt_mode->aead_crypt) { ++ /* first blocksize is not decrypted yet */ ++ buf_setpos(ses.readbuf, 0); ++ ++ /* decrypt it in-place */ ++ len = ses.readbuf->len - macsize - ses.readbuf->pos; ++ if (ses.keys->recv.crypt_mode->aead_crypt(ses.recvseq, ++ buf_getptr(ses.readbuf, len + macsize), ++ buf_getwriteptr(ses.readbuf, len), ++ len, macsize, ++ &ses.keys->recv.cipher_state, LTC_DECRYPT) != CRYPT_OK) { ++ dropbear_exit("Error decrypting"); ++ } ++ buf_incrpos(ses.readbuf, len); ++ } else ++#endif ++ { ++ /* we've already decrypted the first blocksize in read_packet_init */ ++ buf_setpos(ses.readbuf, blocksize); ++ ++ /* decrypt it in-place */ ++ len = ses.readbuf->len - macsize - ses.readbuf->pos; ++ if (ses.keys->recv.crypt_mode->decrypt( ++ buf_getptr(ses.readbuf, len), ++ buf_getwriteptr(ses.readbuf, len), ++ len, ++ &ses.keys->recv.cipher_state) != CRYPT_OK) { ++ dropbear_exit("Error decrypting"); ++ } ++ buf_incrpos(ses.readbuf, len); + +- /* check the hmac */ +- if (checkmac() != DROPBEAR_SUCCESS) { +- dropbear_exit("Integrity error"); ++ /* check the hmac */ ++ if (checkmac() != DROPBEAR_SUCCESS) { ++ dropbear_exit("Integrity error"); ++ } + } + + /* get padding length */ +@@ -557,9 +590,16 @@ void encrypt_packet() { + buf_setpos(ses.writepayload, 0); + buf_setlen(ses.writepayload, 0); + +- /* length of padding - packet length must be a multiple of blocksize, +- * with a minimum of 4 bytes of padding */ +- padlen = blocksize - (writebuf->len) % blocksize; ++ /* length of padding - packet length excluding the packetlength uint32 ++ * field in aead mode must be a multiple of blocksize, with a minimum of ++ * 4 bytes of padding */ ++ len = writebuf->len; ++#if DROPBEAR_AEAD_MODE ++ if (ses.keys->trans.crypt_mode->aead_crypt) { ++ len -= 4; ++ } ++#endif ++ padlen = blocksize - len % blocksize; + if (padlen < 4) { + padlen += blocksize; + } +@@ -579,23 +619,42 @@ void encrypt_packet() { + buf_incrlen(writebuf, padlen); + genrandom(buf_getptr(writebuf, padlen), padlen); + +- make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes); ++#if DROPBEAR_AEAD_MODE ++ if (ses.keys->trans.crypt_mode->aead_crypt) { ++ /* do the actual encryption, in-place */ ++ buf_setpos(writebuf, 0); ++ /* encrypt it in-place*/ ++ len = writebuf->len; ++ buf_incrlen(writebuf, mac_size); ++ if (ses.keys->trans.crypt_mode->aead_crypt(ses.transseq, ++ buf_getptr(writebuf, len), ++ buf_getwriteptr(writebuf, len + mac_size), ++ len, mac_size, ++ &ses.keys->trans.cipher_state, LTC_ENCRYPT) != CRYPT_OK) { ++ dropbear_exit("Error encrypting"); ++ } ++ buf_incrpos(writebuf, len + mac_size); ++ } else ++#endif ++ { ++ make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes); ++ ++ /* do the actual encryption, in-place */ ++ buf_setpos(writebuf, 0); ++ /* encrypt it in-place*/ ++ len = writebuf->len; ++ if (ses.keys->trans.crypt_mode->encrypt( ++ buf_getptr(writebuf, len), ++ buf_getwriteptr(writebuf, len), ++ len, ++ &ses.keys->trans.cipher_state) != CRYPT_OK) { ++ dropbear_exit("Error encrypting"); ++ } ++ buf_incrpos(writebuf, len); + +- /* do the actual encryption, in-place */ +- buf_setpos(writebuf, 0); +- /* encrypt it in-place*/ +- len = writebuf->len; +- if (ses.keys->trans.crypt_mode->encrypt( +- buf_getptr(writebuf, len), +- buf_getwriteptr(writebuf, len), +- len, +- &ses.keys->trans.cipher_state) != CRYPT_OK) { +- dropbear_exit("Error encrypting"); ++ /* stick the MAC on it */ ++ buf_putbytes(writebuf, mac_bytes, mac_size); + } +- buf_incrpos(writebuf, len); +- +- /* stick the MAC on it */ +- buf_putbytes(writebuf, mac_bytes, mac_size); + + /* Update counts */ + ses.kexstate.datatrans += writebuf->len; +diff --git a/session.h b/session.h +index e436882..a8f8914 100644 +--- a/session.h ++++ b/session.h +@@ -41,6 +41,7 @@ + #include "chansession.h" + #include "dbutil.h" + #include "netio.h" ++#include "chachapoly.h" + + void common_session_init(int sock_in, int sock_out); + void session_loop(void(*loophandler)(void)) ATTRIB_NORETURN; +@@ -80,6 +81,9 @@ struct key_context_directional { + symmetric_CBC cbc; + #if DROPBEAR_ENABLE_CTR_MODE + symmetric_CTR ctr; ++#endif ++#if DROPBEAR_CHACHA20POLY1305 ++ dropbear_chachapoly_state chachapoly; + #endif + } cipher_state; + unsigned char mackey[MAX_MAC_LEN]; +diff --git a/sysoptions.h b/sysoptions.h +index 2c27caf..2432779 100644 +--- a/sysoptions.h ++++ b/sysoptions.h +@@ -92,7 +92,11 @@ + #define MD5_HASH_SIZE 16 + #define MAX_HASH_SIZE 64 /* sha512 */ + ++#if DROPBEAR_CHACHA20POLY1305 ++#define MAX_KEY_LEN 64 /* 2 x 256 bits for chacha20 */ ++#else + #define MAX_KEY_LEN 32 /* 256 bits for aes256 etc */ ++#endif + #define MAX_IV_LEN 20 /* must be same as max blocksize, */ + + #if DROPBEAR_SHA2_512_HMAC +@@ -207,6 +211,8 @@ If you test it please contact the Dropbear author */ + + #define DROPBEAR_TWOFISH ((DROPBEAR_TWOFISH256) || (DROPBEAR_TWOFISH128)) + ++#define DROPBEAR_AEAD_MODE ((DROPBEAR_CHACHA20POLY1305)) ++ + #define DROPBEAR_CLI_ANYTCPFWD ((DROPBEAR_CLI_REMOTETCPFWD) || (DROPBEAR_CLI_LOCALTCPFWD)) + + #define DROPBEAR_TCP_ACCEPT ((DROPBEAR_CLI_LOCALTCPFWD) || (DROPBEAR_SVR_REMOTETCPFWD)) +@@ -249,7 +255,7 @@ If you test it please contact the Dropbear author */ + #endif + + #if !(DROPBEAR_AES128 || DROPBEAR_3DES || DROPBEAR_AES256 || DROPBEAR_BLOWFISH \ +- || DROPBEAR_TWOFISH256 || DROPBEAR_TWOFISH128) ++ || DROPBEAR_TWOFISH256 || DROPBEAR_TWOFISH128 || DROPBEAR_CHACHA20POLY1305) + #error "At least one encryption algorithm must be enabled. AES128 is recommended." + #endif + +-- +2.17.1 + diff --git a/package/network/services/uhttpd/Makefile b/package/network/services/uhttpd/Makefile index 07baf478ad..a595a7738a 100644 --- a/package/network/services/uhttpd/Makefile +++ b/package/network/services/uhttpd/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/uhttpd.git -PKG_SOURCE_DATE:=2020-03-13 -PKG_SOURCE_VERSION:=5e9c23c6f40ff26209ef22cfeeda4904a5918f3d -PKG_MIRROR_HASH:=3ede9616c5a9fbbf9db68eeb083efc605246ec53b7f4404b8dc63b5190646949 +PKG_SOURCE_DATE:=2020-06-03 +PKG_SOURCE_VERSION:=939c281c70ef82929ffcb3cb383fd6fdc40f341b +PKG_MIRROR_HASH:=4cd16ef955fe32ddb579ec79f3d8f636e7100ccecd95be1991e7e4d317090a54 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=ISC diff --git a/package/ntlf9t/luci-app-clash/Makefile b/package/ntlf9t/luci-app-clash/Makefile index 14c5da4b72..f9dca789f0 100644 --- a/package/ntlf9t/luci-app-clash/Makefile +++ b/package/ntlf9t/luci-app-clash/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-clash -PKG_VERSION:=1.7.0 +PKG_VERSION:=1.7.1 PKG_MAINTAINER:=frainzy1477 @@ -101,7 +101,6 @@ define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/usr/lib/lua/luci $(INSTALL_DIR) $(1)/usr/share/ $(INSTALL_DIR) $(1)/usr/share/clash - $(INSTALL_DIR) $(1)/usr/share/clash/rules $(INSTALL_DIR) $(1)/usr/share/clash/rules/g_rules $(INSTALL_DIR) $(1)/usr/share/clash/dashboard @@ -137,8 +136,6 @@ define Package/$(PKG_NAME)/install $(INSTALL_BIN) ./root/usr/share/clash/logstatus_check $(1)/usr/share/clash/ $(INSTALL_BIN) ./root/usr/share/clash/clash.txt $(1)/usr/share/clash/ - - $(INSTALL_BIN) ./root/usr/share/clash/dashboard/index.html $(1)/usr/share/clash/dashboard/ $(INSTALL_BIN) ./root/usr/share/clash/dashboard/main.1560b07adc97ac0ac265.css $(1)/usr/share/clash/dashboard/ $(INSTALL_BIN) ./root/usr/share/clash/dashboard/img/ffac0fa1d89f15922b4594863b8b32e9.png $(1)/usr/share/clash/dashboard/img/ diff --git a/package/ntlf9t/luci-app-clash/luasrc/controller/clash.lua b/package/ntlf9t/luci-app-clash/luasrc/controller/clash.lua index 0d1b042521..2d3726bf0d 100644 --- a/package/ntlf9t/luci-app-clash/luasrc/controller/clash.lua +++ b/package/ntlf9t/luci-app-clash/luasrc/controller/clash.lua @@ -13,7 +13,7 @@ function index() local page = entry({"admin", "services", "clash"},alias("admin", "services", "clash", "overview"), _("Clash"), 5) page.dependent = true - page.acl_depends = { "luci-app-clash" } + page.acl_depends = {"luci-app-clash"} entry({"admin", "services", "clash", "overview"},cbi("clash/overview"),_("Overview"), 10).leaf = true entry({"admin", "services", "clash", "client"},cbi("clash/client"),_("Client"), 20).leaf = true diff --git a/package/ntlf9t/luci-app-clash/luasrc/model/cbi/clash/client.lua b/package/ntlf9t/luci-app-clash/luasrc/model/cbi/clash/client.lua index 821fff2ef6..60dd78193e 100644 --- a/package/ntlf9t/luci-app-clash/luasrc/model/cbi/clash/client.lua +++ b/package/ntlf9t/luci-app-clash/luasrc/model/cbi/clash/client.lua @@ -29,11 +29,6 @@ o:value("4", translate("Clash(dTun)")) end o.description = translate("Select core, clashr support ssr while clash does not.") - -o = s:option(Flag, "old_conf", translate("Old Config")) -o.description = translate("Proxy/Proxy Groups/Rule") - - o = s:option(ListValue, "g_rules", translate("Game Rules")) o.default = "0" o:value("0", translate("Disable")) diff --git a/package/ntlf9t/luci-app-clash/luasrc/view/clash/core_check.htm b/package/ntlf9t/luci-app-clash/luasrc/view/clash/core_check.htm index 0ef89e80b1..3f796728d4 100644 --- a/package/ntlf9t/luci-app-clash/luasrc/view/clash/core_check.htm +++ b/package/ntlf9t/luci-app-clash/luasrc/view/clash/core_check.htm @@ -1,5 +1,6 @@ <%+cbi/valueheader%> <%local fs=require"nixio.fs"%> +

@@ -16,14 +17,15 @@ function apply_update(){ function poll_check(){ var lv = document.getElementById('core_download'); lv.style.display="inline" - lv.innerText = "" XHR.poll(2, '<%=url([[admin]], [[services]], [[clash]], [[check]])%>', null, - function(x, data) { - if(x && x.status === 200) { - if(typeof(x.responseText) === "string") { - lv.insertAdjacentText("beforeend", x.responseText); - lv.scrollTop = lv.scrollHeight; - }}}); + function(x, data) { + var lv = document.getElementById('core_download'); + if (x.responseText && lv) { + lv.innerHTML += x.responseText; + lv.scrollTop = lv.scrollHeight; + } + } +); } @@ -54,11 +56,13 @@ function hide(){ btn.value = '<%:Download%>'; } + + <% if fs.access("/var/run/core_update") then %> var btn = document.getElementById('apply_update_button'); btn.disabled = true; btn.value = '<%:Downloading...%>'; -poll_check(); + poll_check(); <%end%> diff --git a/package/ntlf9t/luci-app-clash/luasrc/view/clash/geoip.htm b/package/ntlf9t/luci-app-clash/luasrc/view/clash/geoip.htm index bbd46646c7..79ea6dcee9 100644 --- a/package/ntlf9t/luci-app-clash/luasrc/view/clash/geoip.htm +++ b/package/ntlf9t/luci-app-clash/luasrc/view/clash/geoip.htm @@ -17,14 +17,12 @@ function apply_update(){ function poll_check(){ var lv = document.getElementById('geoip_download'); lv.style.display="inline" - lv.innerText = "" XHR.poll(2, '<%=url([[admin]], [[services]], [[clash]], [[check_geoip]])%>', null, function(x, data) { - scroll(); var lv = document.getElementById('geoip_download'); if (x.responseText && lv) { - lv.innerHTML += x.responseText; - lv.scrollTop = lv.scrollHeight; + lv.innerHTML += x.responseText; + lv.scrollTop = lv.scrollHeight; } } ); @@ -60,11 +58,6 @@ function hide(){ } -/*function scroll(){ - var textarea = document.getElementById('geoip_download'); - textarea.scrollTop = textarea.scrollHeight; -}*/ - <% if fs.access("/var/run/geoip_update") then %> var btn = document.getElementById('apply_update_geoip'); diff --git a/package/ntlf9t/luci-app-clash/luasrc/view/clash/status_log.htm b/package/ntlf9t/luci-app-clash/luasrc/view/clash/status_log.htm index 7aff7b46f8..0c392bb933 100644 --- a/package/ntlf9t/luci-app-clash/luasrc/view/clash/status_log.htm +++ b/package/ntlf9t/luci-app-clash/luasrc/view/clash/status_log.htm @@ -1,18 +1,22 @@ <%+cbi/valueheader%> + <%+cbi/valuefooter%> diff --git a/package/ntlf9t/luci-app-clash/root/etc/init.d/clash b/package/ntlf9t/luci-app-clash/root/etc/init.d/clash index 048fe556fd..5f11889530 100644 --- a/package/ntlf9t/luci-app-clash/root/etc/init.d/clash +++ b/package/ntlf9t/luci-app-clash/root/etc/init.d/clash @@ -205,10 +205,10 @@ yml_dns_change(){ check(){ - sed -i 's/Proxy Group:/proxy-groups:/g' "$CONFIG_YAML" - sed -i 's/proxy-provider:/proxy-providers:/g' "$CONFIG_YAML" - sed -i 's/Proxy:/proxies:/g' "$CONFIG_YAML" - sed -i 's/Rule:/rules:/g' "$CONFIG_YAML" + sed -i 's/^Proxy Group:/proxy-groups:/g' "$CONFIG_YAML" + sed -i 's/^proxy-provider:/proxy-providers:/g' "$CONFIG_YAML" + sed -i 's/^Proxy:/proxies:/g' "$CONFIG_YAML" + sed -i 's/^Rule:/rules:/g' "$CONFIG_YAML" } @@ -455,7 +455,7 @@ enable=$(uci get clash.config.enable 2>/dev/null) core=$(uci get clash.config.core 2>/dev/null) mode=$(uci get clash.config.mode 2>/dev/null) tun_mode=$(uci get clash.config.tun_mode 2>/dev/null) -old_conf=$(uci get clash.config.old_conf 2>/dev/null) + if [ -f /etc/clash/config.yaml ];then @@ -508,11 +508,9 @@ elif [ "${core}" -eq 3 ] && [ ! -f /etc/clash/clashtun/clash ]; then echo "Clash for OpenWRT" >$REAL_LOG exit 0 else -if [ -f $CONFIG_YAML ] && [ "$(ls -l $CONFIG_YAML|awk '{print int($5/1024)}')" -ne 0 ] ; then +if [ -f $CONFIG_YAML ] && [ "$(ls -l $CONFIG_YAML|awk '{print int($5)}')" -ne 0 ] ; then - if [ -z "$old_conf" ];then check >/dev/null 2>&1 - fi yml_change >/dev/null 2>&1 diff --git a/package/ntlf9t/luci-app-clash/root/usr/share/clash/clash.sh b/package/ntlf9t/luci-app-clash/root/usr/share/clash/clash.sh index b04a5cb0cb..b551470f32 100755 --- a/package/ntlf9t/luci-app-clash/root/usr/share/clash/clash.sh +++ b/package/ntlf9t/luci-app-clash/root/usr/share/clash/clash.sh @@ -19,13 +19,19 @@ if [ $config_name == "" ] || [ -z $config_name ];then fi sleep 5 echo "Clash for OpenWRT" >$REAL_LOG - exit 0 + exit 0 fi - +if [ ! -f "/usr/share/clashbackup/confit_list.conf" ];then + touch /usr/share/clashbackup/confit_list.conf +fi + + check_name=$(grep -F "${config_name}.yaml" "/usr/share/clashbackup/confit_list.conf") + + if [ ! -z $check_name ];then if [ $lang == "en" ] || [ $lang == "auto" ];then @@ -48,14 +54,14 @@ else sleep 1 if [ "$subtype" = "clash" ];then - curl -sL --connect-timeout 10 --retry 2 "$clash_url" -O 2>&1 >1 $CONFIG_YAML + wget -c4 --no-check-certificate --user-agent="Clash/OpenWRT" "$clash_url" -O 2>&1 >1 $CONFIG_YAML if [ "$?" -eq "0" ]; then echo "${config_name}.yaml#$clash_url#$subtype" >>/usr/share/clashbackup/confit_list.conf fi fi if [ "$subtype" = "ssr2clash" ];then - curl -sL --connect-timeout 10 --retry 2 "https://ssrsub2clashr.herokuapp.com/ssrsub2clash?sub=$ssr_url" -O 2>&1 >1 $CONFIG_YAML + wget -c4 --no-check-certificate --user-agent="Clash/OpenWRT" "https://gfwsb.114514.best/sub?target=clashr&url=$ssr_url" -O 2>&1 >1 $CONFIG_YAML if [ "$?" -eq "0" ]; then echo "${config_name}.yaml#$ssr_url#$subtype" >>/usr/share/clashbackup/confit_list.conf CONFIG_YAMLL="/tmp/conf" @@ -100,7 +106,7 @@ else fi if [ "$subtype" = "v2clash" ];then - curl -sL --connect-timeout 10 --retry 2 "https://tgbot.lbyczf.com/v2rayn2clash?url=$v2_url" -O 2>&1 >1 $CONFIG_YAML + wget -c4 --no-check-certificate --user-agent="Clash/OpenWRT" "https://tgbot.lbyczf.com/v2rayn2clash?url=$v2_url" -O 2>&1 >1 $CONFIG_YAML if [ "$?" -eq "0" ]; then echo "${config_name}.yaml#$v2_url#$subtype" >>/usr/share/clashbackup/confit_list.conf fi diff --git a/package/ntlf9t/luci-app-clash/root/usr/share/clash/dashboard/img/33343e6117c37aaef8886179007ba6b5.png b/package/ntlf9t/luci-app-clash/root/usr/share/clash/dashboard/img/33343e6117c37aaef8886179007ba6b5.png new file mode 100644 index 0000000000..6798639d0f Binary files /dev/null and b/package/ntlf9t/luci-app-clash/root/usr/share/clash/dashboard/img/33343e6117c37aaef8886179007ba6b5.png differ diff --git a/package/ntlf9t/luci-app-clash/root/usr/share/clash/dashboard/js/1.bundle.0bddb85299f970595cb5.min.js b/package/ntlf9t/luci-app-clash/root/usr/share/clash/dashboard/js/1.bundle.0bddb85299f970595cb5.min.js new file mode 100644 index 0000000000..7bc830d892 --- /dev/null +++ b/package/ntlf9t/luci-app-clash/root/usr/share/clash/dashboard/js/1.bundle.0bddb85299f970595cb5.min.js @@ -0,0 +1,2 @@ +/*! For license information please see 1.bundle.0bddb85299f970595cb5.min.js.LICENSE */ +(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[function(e,t,n){"use strict";e.exports=n(51)},function(e,t,n){e.exports=n(55)()},function(e,t,n){var r;!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t=0||(o[n]=e[n]);return o}n.d(t,"a",(function(){return r}))},,,,function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE){0;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}}(),e.exports=n(52)},function(e,t,n){var r=n(42)(Object,"create");e.exports=r},function(e,t,n){var r=n(110);e.exports=function(e,t){for(var n=e.length;n--;)if(r(e[n][0],t))return n;return-1}},function(e,t,n){var r=n(116);e.exports=function(e,t){var n=e.__data__;return r(t)?n["string"==typeof t?"string":"hash"]:n.map}},function(e,t,n){"use strict";var r=Array.isArray,o=Object.keys,i=Object.prototype.hasOwnProperty;e.exports=function e(t,n){if(t===n)return!0;if(t&&n&&"object"==typeof t&&"object"==typeof n){var a,u,l,c=r(t),s=r(n);if(c&&s){if((u=t.length)!=n.length)return!1;for(a=u;0!=a--;)if(!e(t[a],n[a]))return!1;return!0}if(c!=s)return!1;var f=t instanceof Date,d=n instanceof Date;if(f!=d)return!1;if(f&&d)return t.getTime()==n.getTime();var p=t instanceof RegExp,h=n instanceof RegExp;if(p!=h)return!1;if(p&&h)return t.toString()==n.toString();var m=o(t);if((u=m.length)!==o(n).length)return!1;for(a=u;0!=a--;)if(!i.call(n,m[a]))return!1;for(a=u;0!=a--;)if(!e(t[l=m[a]],n[l]))return!1;return!0}return t!=t&&n!=n}},,function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"==typeof window&&(n=window)}e.exports=n},function(e,t){var n=Array.isArray;e.exports=n},function(e,t,n){var r=n(41),o=n(89),i="[object Symbol]";e.exports=function(e){return"symbol"==typeof e||o(e)&&r(e)==i}},function(e,t,n){var r=n(23).Symbol;e.exports=r},function(e,t,n){var r=n(86),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();e.exports=i},function(e,t,n){e.exports=function(){"use strict";var e="millisecond",t="second",n="minute",r="hour",o="day",i="week",a="month",u="quarter",l="year",c=/^(\d{4})-?(\d{1,2})-?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?.?(\d{1,3})?$/,s=/\[([^\]]+)]|Y{2,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,f=function(e,t,n){var r=String(e);return!r||r.length>=t?e:""+Array(t+1-r.length).join(n)+e},d={s:f,z:function(e){var t=-e.utcOffset(),n=Math.abs(t),r=Math.floor(n/60),o=n%60;return(t<=0?"+":"-")+f(r,2,"0")+":"+f(o,2,"0")},m:function(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),r=e.clone().add(n,a),o=t-r<0,i=e.clone().add(n+(o?-1:1),a);return Number(-(n+(t-r)/(o?r-i:i-r))||0)},a:function(e){return e<0?Math.ceil(e)||0:Math.floor(e)},p:function(c){return{M:a,y:l,w:i,d:o,h:r,m:n,s:t,ms:e,Q:u}[c]||String(c||"").toLowerCase().replace(/s$/,"")},u:function(e){return void 0===e}},p={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},h="en",m={};m[h]=p;var v=function(e){return e instanceof w},g=function(e,t,n){var r;if(!e)return h;if("string"==typeof e)m[e]&&(r=e),t&&(m[e]=t,r=e);else{var o=e.name;m[o]=e,r=o}return n||(h=r),r},y=function(e,t,n){if(v(e))return e.clone();var r=t?"string"==typeof t?{format:t,pl:n}:t:{};return r.date=e,new w(r)},b=d;b.l=g,b.i=v,b.w=function(e,t){return y(e,{locale:t.$L,utc:t.$u,$offset:t.$offset})};var w=function(){function f(e){this.$L=this.$L||g(e.locale,null,!0),this.parse(e)}var d=f.prototype;return d.parse=function(e){this.$d=function(e){var t=e.date,n=e.utc;if(null===t)return new Date(NaN);if(b.u(t))return new Date;if(t instanceof Date)return new Date(t);if("string"==typeof t&&!/Z$/i.test(t)){var r=t.match(c);if(r)return n?new Date(Date.UTC(r[1],r[2]-1,r[3]||1,r[4]||0,r[5]||0,r[6]||0,r[7]||0)):new Date(r[1],r[2]-1,r[3]||1,r[4]||0,r[5]||0,r[6]||0,r[7]||0)}return new Date(t)}(e),this.init()},d.init=function(){var e=this.$d;this.$y=e.getFullYear(),this.$M=e.getMonth(),this.$D=e.getDate(),this.$W=e.getDay(),this.$H=e.getHours(),this.$m=e.getMinutes(),this.$s=e.getSeconds(),this.$ms=e.getMilliseconds()},d.$utils=function(){return b},d.isValid=function(){return!("Invalid Date"===this.$d.toString())},d.isSame=function(e,t){var n=y(e);return this.startOf(t)<=n&&n<=this.endOf(t)},d.isAfter=function(e,t){return y(e)=0;d--){var p=o[d];"."===p?s(o,d):".."===p?(s(o,d),f++):f&&(s(o,d),f--)}if(!u)for(;f--;f)o.unshift("..");!u||""===o[0]||o[0]&&c(o[0])||o.unshift("");var h=o.join("/");return n&&"/"!==h.substr(-1)&&(h+="/"),h};function d(e){return e.valueOf?e.valueOf():Object.prototype.valueOf.call(e)}var p=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every((function(t,r){return e(t,n[r])}));if("object"==typeof t||"object"==typeof n){var r=d(t),o=d(n);return r!==t||o!==n?e(r,o):Object.keys(Object.assign({},t,n)).every((function(r){return e(t[r],n[r])}))}return!1},h=!0,m="Invariant failed";var v=function(e,t){if(!e)throw h?new Error(m):new Error(m+": "+(t||""))};function g(e){return"/"===e.charAt(0)?e:"/"+e}function y(e){return"/"===e.charAt(0)?e.substr(1):e}function b(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function w(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function x(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function S(e,t,n,r){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var i=t.indexOf("?");return-1!==i&&(n=t.substr(i),t=t.substr(0,i)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e)).state=t:(void 0===(o=Object(l.a)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(i){throw i instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):i}return n&&(o.key=n),r?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=f(o.pathname,r.pathname)):o.pathname=r.pathname:o.pathname||(o.pathname="/"),o}function E(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var i="function"==typeof e?e(t,n):e;"string"==typeof i?"function"==typeof r?r(i,o):o(!0):o(!1!==i)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,r):n.push(r),f({action:"PUSH",location:r,index:t,entries:n})}}))},replace:function(e,t){var r=S(e,t,d(),g.location);s.confirmTransitionTo(r,"REPLACE",n,(function(e){e&&(g.entries[g.index]=r,f({action:"REPLACE",location:r}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=g.index+e;return t>=0&&t=0;t--){var n=e[t][a];n.modified||(Array.isArray(n.base)?K(n)&&A(n):w(n.base)?Q(n)&&A(n):S(n.base)?X(n)&&A(n):G(n)&&A(n))}}function G(e){for(var t=e.base,n=e.draft,r=Object.keys(n),o=r.length-1;o>=0;o--){var i=r[o],u=t[i];if(void 0===u&&!m(t,i))return!0;var l=n[i],c=l&&l[a];if(c?c.base!==u:!g(l,u))return!0}return r.length!==Object.keys(t).length}function K(e){var t=e.draft;if(t.length!==e.base.length)return!0;var n=Object.getOwnPropertyDescriptor(t,t.length-1);return!(!n||n.get)}function Q(e){var t=e.base,n=e.draft;if(t.size!==n.size)return!0;var r=!1;return n.forEach((function(e,n){r||(r=l(e)?e.modified:e!==t.get(n))})),r}function X(e){var t=e.base,n=e.draft;if(t.size!==n.size)return!0;var r=!1;return n.forEach((function(e,n){r||(r=l(e)?e.modified:!t.has(n))})),r}var J,Z,ee=Object.freeze({__proto__:null,willFinalize:function(e,t,n){e.drafts.forEach((function(e){e[a].finalizing=!0})),n?u(t)&&t[a].scope===e&&Y(e.drafts):(e.patches&&function e(t){if(!t||"object"!=typeof t)return;var n=t[a];if(!n)return;var r=n.base,o=n.draft,i=n.assigned;if(Array.isArray(t)){if(K(n)){if(A(n),i.length=!0,o.lengths&&a[f-1]===u[f+c-1];)--f;for(var d=s;d=f;--d){p=t.concat([d]);n[h+d-f]={op:"add",path:p,value:u[d]},r.push({op:"remove",path:p})}}function he(e,t,n,r){var o=e.base,i=e.copy;p(e.assigned,(function(e,a){var u=v(o,e),l=v(i,e),c=a?m(o,e)?"replace":"add":"remove";if(u!==l||"replace"!==c){var s=t.concat(e);n.push("remove"===c?{op:c,path:s}:{op:c,path:s,value:l}),r.push("add"===c?{op:"remove",path:s}:"remove"===c?{op:"add",path:s,value:u}:{op:"replace",path:s,value:u})}}))}function me(e,t,n,r){var o=e.base,i=e.copy,a=0;o.forEach((function(e){if(!i.has(e)){var o=t.concat([a]);n.push({op:"remove",path:o,value:e}),r.unshift({op:"add",path:o,value:e})}a++})),a=0,i.forEach((function(e){if(!o.has(e)){var i=t.concat([a]);n.push({op:"add",path:i,value:e}),r.unshift({op:"remove",path:i,value:e})}a++}))}function ve(e,t){return t.forEach((function(t){var n=t.path,r=t.op;if(!n.length)throw new Error("Illegal state");for(var o=e,i=0;i=0;n--){var r=t[n];if(0===r.path.length&&"replace"===r.op){e=r.value;break}}return u(e)?ve(e,t):this.produce(e,(function(e){return ve(e,t.slice(n+1))}))},e.prototype.processResult=function(e,t){var n=t.drafts[0],r=void 0!==e&&e!==n;if(this.willFinalize(t,e,r),r){if(n[a].modified)throw t.revoke(),new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.");l(e)&&(e=this.finalize(e,null,t),this.maybeFreeze(e)),t.patches&&(t.patches.push({op:"replace",path:[],value:e}),t.inversePatches.push({op:"replace",path:[],value:n[a].base}))}else e=this.finalize(n,[],t);return t.revoke(),t.patches&&t.patchListener(t.patches,t.inversePatches),e!==o?e:void 0},e.prototype.finalize=function(e,t,n){var r=this,o=e[a];if(!o)return Object.isFrozen(e)?e:this.finalizeTree(e,null,n);if(o.scope!==n)return e;if(!o.modified)return this.maybeFreeze(o.base,!0),o.base;if(!o.finalized){if(o.finalized=!0,this.finalizeTree(o.draft,t,n),this.onDelete&&!S(o.base))if(this.useProxies){p(o.assigned,(function(e,t){var n,i;t||null===(i=(n=r).onDelete)||void 0===i||i.call(n,o,e)}))}else{var i=o.base,u=o.copy;p(i,(function(e){var t,n;m(u,e)||null===(n=(t=r).onDelete)||void 0===n||n.call(t,o,e)}))}this.onCopy&&this.onCopy(o),this.autoFreeze&&n.canAutoFreeze&&P(o.copy,!1),t&&n.patches&&function(e,t,n,r){(Array.isArray(e.base)?pe:S(e.base)?me:he)(e,t,n,r)}(o,t,n.patches,n.inversePatches)}return o.copy},e.prototype.finalizeTree=function(e,t,n){var r=this,o=e[a];o&&(this.useProxies||(o.copy=d(o.draft,!0)),e=o.copy);var i=!!t&&!!n.patches,c=function(a,s,f){if(s===f)throw Error("Immer forbids circular references");var d=!!o&&f===e,y=S(f);if(u(s)){var b=d&&i&&!y&&!m(o.assigned,a)?t.concat(a):null;if(function(e,t,n){w(e)?e.set(t,n):S(e)?(e.delete(t),e.add(n)):Array.isArray(e)||h(e,t)?e[t]=n:Object.defineProperty(e,t,{value:n,writable:!0,configurable:!0})}(f,a,s=r.finalize(s,b,n)),u(s)&&(n.canAutoFreeze=!1),d&&s===v(o.base,a))return}else{if(d&&g(s,v(o.base,a)))return;l(s)&&!Object.isFrozen(s)&&(p(s,c),r.maybeFreeze(s))}d&&r.onAssign&&!y&&r.onAssign(o,a,s)};return p(e,c),e},e.prototype.maybeFreeze=function(e,t){void 0===t&&(t=!1),this.autoFreeze&&!u(e)&&P(e,t)},e}()),be=ye.produce;ye.produceWithPatches.bind(ye),ye.setAutoFreeze.bind(ye),ye.setUseProxies.bind(ye),ye.applyPatches.bind(ye),ye.createDraft.bind(ye),ye.finishDraft.bind(ye);t.a=be}).call(this,n(35))},function(e,t,n){"use strict";var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(o){return!1}}()?Object.assign:function(e,t){for(var n,u,l=a(e),c=1;c=200&&e<300}};l.headers={common:{Accept:"application/json, text/plain, */*"}},r.forEach(["delete","get","head"],(function(e){l.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){l.headers[e]=r.merge(i)})),e.exports=l}).call(this,n(35))},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function u(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var l,c=[],s=!1,f=-1;function d(){s&&l&&(s=!1,l.length?c=l.concat(c):f=-1,c.length&&p())}function p(){if(!s){var e=u(d);s=!0;for(var t=c.length;t;){for(l=c,c=[];++f1)for(var n=1;nM.length&&M.push(e)}function j(e,t,n){return null==e?0:function e(t,n,r,o){var u=typeof t;"undefined"!==u&&"boolean"!==u||(t=null);var l=!1;if(null===t)l=!0;else switch(u){case"string":case"number":l=!0;break;case"object":switch(t.$$typeof){case i:case a:l=!0}}if(l)return r(o,t,""===n?"."+N(t,0):n),1;if(l=0,n=""===n?".":n+":",Array.isArray(t))for(var c=0;c