mirror of
https://github.com/dnscrypt/dnscrypt-server-docker
synced 2024-11-22 19:42:03 +01:00
Preliminary code to move to the new server
This commit is contained in:
parent
1f42134a69
commit
a3efabd367
54
Dockerfile
54
Dockerfile
@ -1,17 +1,17 @@
|
||||
FROM jedisct1/alpine-runit:latest
|
||||
MAINTAINER Frank Denis
|
||||
LABEL maintainer="Frank Denis"
|
||||
SHELL ["/bin/sh", "-x", "-c"]
|
||||
ENV SERIAL 3
|
||||
|
||||
ENV CFLAGS=-Ofast
|
||||
ENV BUILD_DEPS make gcc musl-dev git libevent-dev expat-dev shadow autoconf file openssl-dev byacc linux-headers
|
||||
ENV BUILD_DEPS curl make gcc musl-dev git libevent-dev expat-dev shadow autoconf file openssl-dev byacc linux-headers
|
||||
ENV RUNTIME_DEPS bash util-linux coreutils findutils grep openssl ldns ldns-tools libevent expat libexecinfo coreutils drill ca-certificates
|
||||
|
||||
RUN apk --no-cache upgrade && apk add --no-cache $RUNTIME_DEPS
|
||||
RUN update-ca-certificates 2> /dev/null || true
|
||||
|
||||
ENV UNBOUND_GIT_URL https://github.com/jedisct1/unbound.git
|
||||
ENV UNBOUND_GIT_REVISION 4edb15ba417c78710069a5be8be3a6b5d8bdba9c
|
||||
ENV UNBOUND_GIT_REVISION 35ac577d99d56869f2f87dcc7b5e36b8996df5ca
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
@ -29,53 +29,41 @@ RUN apk add --no-cache $BUILD_DEPS && \
|
||||
rm -fr /opt/unbound/share/man && \
|
||||
rm -fr /tmp/* /var/tmp/*
|
||||
|
||||
ENV LIBSODIUM_GIT_URL https://github.com/jedisct1/libsodium.git
|
||||
ENV RUSTFLAGS "-C target-feature=-crt-static -C link-arg=-s"
|
||||
|
||||
RUN apk add --no-cache $BUILD_DEPS && \
|
||||
git clone --depth=1 --branch stable "$LIBSODIUM_GIT_URL" && \
|
||||
cd libsodium && \
|
||||
./configure --disable-dependency-tracking && \
|
||||
make -j"$(getconf _NPROCESSORS_ONLN)" check && make -j"$(getconf _NPROCESSORS_ONLN)" install && \
|
||||
ldconfig /usr/local/lib && \
|
||||
apk del --purge $BUILD_DEPS && \
|
||||
rm -fr /tmp/* /var/tmp/*
|
||||
|
||||
ENV DNSCRYPT_WRAPPER_GIT_URL https://github.com/jedisct1/dnscrypt-wrapper.git
|
||||
ENV DNSCRYPT_WRAPPER_GIT_BRANCH xchacha-stamps
|
||||
|
||||
COPY queue.h /tmp
|
||||
|
||||
RUN apk add --no-cache $BUILD_DEPS && \
|
||||
git clone --depth=1 --branch="${DNSCRYPT_WRAPPER_GIT_BRANCH}" "${DNSCRYPT_WRAPPER_GIT_URL}" && \
|
||||
cd dnscrypt-wrapper && \
|
||||
sed -i 's#<sys/queue.h>#"/tmp/queue.h"#' compat.h && \
|
||||
sed -i 's#HAVE_BACKTRACE#NO_BACKTRACE#' compat.h && \
|
||||
mkdir -p /opt/dnscrypt-wrapper/empty && \
|
||||
groupadd _dnscrypt-wrapper && \
|
||||
useradd -g _dnscrypt-wrapper -s /etc -d /opt/dnscrypt-wrapper/empty _dnscrypt-wrapper && \
|
||||
groupadd _dnscrypt-signer && \
|
||||
useradd -g _dnscrypt-signer -G _dnscrypt-wrapper -s /etc -d /dev/null _dnscrypt-signer && \
|
||||
make -j"$(getconf _NPROCESSORS_ONLN)" configure && \
|
||||
./configure --prefix=/opt/dnscrypt-wrapper && \
|
||||
make -j"$(getconf _NPROCESSORS_ONLN)" install && \
|
||||
curl -sSf https://sh.rustup.rs | bash -s -- -y --default-toolchain nightly
|
||||
|
||||
RUN source $HOME/.cargo/env && \
|
||||
cargo install encrypted-dns && \
|
||||
mkdir -p /opt/encrypted-dns/sbin && \
|
||||
mkdir -p /opt/encrypted-dns/etc/keys && \
|
||||
mv ~/.cargo/bin/encrypted-dns /opt/encrypted-dns/sbin/ && \
|
||||
strip --strip-all /opt/encrypted-dns/sbin/encrypted-dns && \
|
||||
groupadd _encrypted-dns && \
|
||||
useradd -g _encrypted-dns -s /etc -d /opt/encrypted-dns/empty _encrypted-dns && \
|
||||
chown _encrypted-dns:_encrypted-dns /opt/encrypted-dns/etc/keys && \
|
||||
chmod 700 /opt/encrypted-dns/etc/keys && \
|
||||
apk del --purge $BUILD_DEPS && \
|
||||
rm -fr ~/.cargo ~/.rustup && \
|
||||
rm -fr /tmp/* /var/tmp/*
|
||||
|
||||
RUN mkdir -p \
|
||||
/etc/service/unbound \
|
||||
/etc/service/watchdog
|
||||
|
||||
COPY encrypted-dns.toml.in /opt/encrypted-dns/etc/
|
||||
|
||||
COPY entrypoint.sh /
|
||||
|
||||
COPY unbound.sh /etc/service/unbound/run
|
||||
COPY unbound-check.sh /etc/service/unbound/check
|
||||
|
||||
COPY dnscrypt-wrapper.sh /etc/service/dnscrypt-wrapper/run
|
||||
COPY encrypted-dns.sh /etc/service/encrypted-dns/run
|
||||
|
||||
COPY key-rotation.sh /etc/service/key-rotation/run
|
||||
COPY watchdog.sh /etc/service/watchdog/run
|
||||
|
||||
VOLUME ["/opt/dnscrypt-wrapper/etc/keys"]
|
||||
VOLUME ["/opt/encrypted-dns/etc/keys"]
|
||||
|
||||
EXPOSE 443/udp 443/tcp
|
||||
|
||||
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2016, Frank Denis <github@pureftpd.org>
|
||||
Copyright (c) 2015-2019, Frank Denis <github@pureftpd.org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
17
README.md
17
README.md
@ -13,8 +13,8 @@ to get your resolver up and running.
|
||||
Quickstart
|
||||
==========
|
||||
|
||||
* [How to setup your own DNSCrypt server in less than 10 minutes on Scaleway](https://github.com/jedisct1/dnscrypt-proxy/wiki/How-to-setup-your-own-DNSCrypt-server-in-less-than-10-minutes)
|
||||
* [DNSCrypt server with vultr.com](https://github.com/jedisct1/dnscrypt-proxy/wiki/DNSCrypt-server-with-vultr.com)
|
||||
* [How to setup your own DNSCrypt server in less than 10 minutes on Scaleway](https://github.com/dnscrypt/dnscrypt-proxy/wiki/How-to-setup-your-own-DNSCrypt-server-in-less-than-10-minutes)
|
||||
* [DNSCrypt server with vultr.com](https://github.com/dnscrypt/dnscrypt-proxy/wiki/DNSCrypt-server-with-vultr.com)
|
||||
|
||||
Installation
|
||||
============
|
||||
@ -104,12 +104,10 @@ Details
|
||||
- Caching resolver: [Unbound](https://www.unbound.net/), with DNSSEC, prefetching,
|
||||
and no logs. The number of threads and memory usage are automatically adjusted.
|
||||
Latest stable version, compiled from source. qname minimisation is enabled.
|
||||
- [libsodium](https://download.libsodium.org/doc/) - Latest stable version,
|
||||
minimal build compiled from source.
|
||||
- [dnscrypt-wrapper](https://github.com/Cofyc/dnscrypt-wrapper) - Latest stable version,
|
||||
compiled from source.
|
||||
- [encrypted-dns-server](https://github.com/jedisct1/dnscrypt-dns-server).
|
||||
Compiled from source.
|
||||
|
||||
Keys and certificates are automatically rotated every 12 hour.
|
||||
Keys and certificates are automatically rotated every 8 hour.
|
||||
|
||||
Kubernetes
|
||||
==========
|
||||
@ -128,8 +126,3 @@ in minutes.
|
||||
|
||||
To get your public key just view the logs for the `dnscrypt-init` job. The public
|
||||
IP for your server is merely the `dnscrypt` service address.
|
||||
|
||||
Coming up next
|
||||
==============
|
||||
|
||||
- Better isolation of the certificate signing process, in a dedicated container.
|
||||
|
@ -1,68 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
KEYS_DIR="/opt/dnscrypt-wrapper/etc/keys"
|
||||
STKEYS_DIR="${KEYS_DIR}/short-term"
|
||||
LISTS_DIR="/opt/dnscrypt-wrapper/etc/lists"
|
||||
BLACKLIST="${LISTS_DIR}/blacklist.txt"
|
||||
|
||||
prune() {
|
||||
/usr/bin/find "$STKEYS_DIR" -type f -cmin +1440 -exec rm -f {} \;
|
||||
}
|
||||
|
||||
rotation_needed() {
|
||||
if [ "$(/usr/bin/find "$STKEYS_DIR" -name '*.cert' -type f -cmin -720 -print -quit | wc -l | sed 's/[^0-9]//g')" -le 0 ]; then
|
||||
echo true
|
||||
else
|
||||
echo false
|
||||
fi
|
||||
}
|
||||
|
||||
new_key() {
|
||||
ts=$(date '+%s')
|
||||
/opt/dnscrypt-wrapper/sbin/dnscrypt-wrapper --gen-crypt-keypair \
|
||||
--crypt-secretkey-file="${STKEYS_DIR}/${ts}.key" &&
|
||||
/opt/dnscrypt-wrapper/sbin/dnscrypt-wrapper --gen-cert-file \
|
||||
--xchacha20 \
|
||||
--provider-publickey-file="${KEYS_DIR}/public.key" \
|
||||
--provider-secretkey-file="${KEYS_DIR}/secret.key" \
|
||||
--crypt-secretkey-file="${STKEYS_DIR}/${ts}.key" \
|
||||
--provider-cert-file="${STKEYS_DIR}/${ts}.cert" \
|
||||
--cert-file-expire-days=1
|
||||
[ $? -ne 0 ] && rm -f "${STKEYS_DIR}/${ts}.key" "${STKEYS_DIR}/${ts}.cert"
|
||||
}
|
||||
|
||||
stkeys_files() {
|
||||
res=""
|
||||
for file in $(ls "$STKEYS_DIR"/[0-9]*.key); do
|
||||
res="${res}${file},"
|
||||
done
|
||||
echo "$res"
|
||||
}
|
||||
|
||||
stcerts_files() {
|
||||
res=""
|
||||
for file in $(ls "$STKEYS_DIR"/[0-9]*.cert); do
|
||||
res="${res}${file},"
|
||||
done
|
||||
echo "$res"
|
||||
}
|
||||
|
||||
if [ ! -f "$KEYS_DIR/provider_name" ]; then
|
||||
exit 1
|
||||
fi
|
||||
provider_name=$(cat "$KEYS_DIR/provider_name")
|
||||
|
||||
mkdir -p "$STKEYS_DIR"
|
||||
prune
|
||||
[ "$(rotation_needed)" = true ] && new_key
|
||||
|
||||
[ -r "$BLACKLIST" ] && blacklist_opt="--blacklist-file=${BLACKLIST}"
|
||||
|
||||
exec /opt/dnscrypt-wrapper/sbin/dnscrypt-wrapper \
|
||||
--user=_dnscrypt-wrapper \
|
||||
--listen-address=[::]:443 \
|
||||
--resolver-address=127.0.0.1:553 \
|
||||
--provider-name="$provider_name" \
|
||||
--provider-cert-file="$(stcerts_files)" \
|
||||
--crypt-secretkey-file="$(stkeys_files)" \
|
||||
$blacklist_opt
|
15
encrypted-dns.sh
Executable file
15
encrypted-dns.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
LEGACY_KEYS_DIR="/opt/dnscrypt-wrapper/etc/keys"
|
||||
CONF_DIR="/opt/encrypted-dns/etc"
|
||||
KEYS_DIR="/opt/encrypted-dns/etc/keys"
|
||||
LISTS_DIR="/opt/encrypted-dns/etc/lists"
|
||||
BLACKLIST="${LISTS_DIR}/blacklist.txt"
|
||||
CONFIG_FILE="${CONF_DIR}/encrypted-dns.toml"
|
||||
|
||||
if [ ! -f "$KEYS_DIR/provider_name" ]; then
|
||||
exit 1
|
||||
fi
|
||||
provider_name=$(cat "$KEYS_DIR/provider_name")
|
||||
|
||||
exec /opt/encrypted-dns/sbin/encrypted-dns --config "$CONFIG_FILE"
|
151
encrypted-dns.toml.in
Normal file
151
encrypted-dns.toml.in
Normal file
@ -0,0 +1,151 @@
|
||||
####################################################
|
||||
# #
|
||||
# Encrypted DNS Server configuration #
|
||||
# #
|
||||
####################################################
|
||||
|
||||
|
||||
|
||||
##################################
|
||||
# Global settings #
|
||||
##################################
|
||||
|
||||
|
||||
## IP addresses and ports to listen to, as well as their external IP
|
||||
## If there is no NAT involved, `local` and `external` can be the same.
|
||||
## As many addresses as needed can be configured here, IPv4 and/or IPv6.
|
||||
|
||||
listen_addrs = [
|
||||
{ local = "0.0.0.0:443", external = "@EXTERNAL_IPV4@" }
|
||||
]
|
||||
|
||||
|
||||
## Upstream DNS server and port
|
||||
|
||||
upstream_addr = "127.0.0.1:53"
|
||||
|
||||
|
||||
## File name to save the state to
|
||||
|
||||
state_file = "/opt/encrypted-dns/etc/keys/encrypted-dns.state"
|
||||
|
||||
|
||||
## UDP timeout in seconds
|
||||
|
||||
udp_timeout = 10
|
||||
|
||||
|
||||
## TCP timeout in seconds
|
||||
|
||||
tcp_timeout = 10
|
||||
|
||||
|
||||
## Maximum active UDP sockets
|
||||
|
||||
udp_max_active_connections = 1000
|
||||
|
||||
|
||||
## Maximum active TCP connections
|
||||
|
||||
tcp_max_active_connections = 100
|
||||
|
||||
|
||||
## IP address to connect to upstream servers from.
|
||||
## You probably do not want to change this. `0.0.0.0` should be fine.
|
||||
|
||||
external_addr = "0.0.0.0"
|
||||
|
||||
|
||||
## Built-in DNS cache capacity
|
||||
|
||||
cache_capacity = 50000
|
||||
|
||||
|
||||
## DNS cache: minimum TTL
|
||||
|
||||
cache_ttl_min = 600
|
||||
|
||||
|
||||
## DNS cache: max TTL
|
||||
|
||||
cache_ttl_max = 86400
|
||||
|
||||
|
||||
## DNS cache: error TTL
|
||||
|
||||
cache_ttl_error = 600
|
||||
|
||||
|
||||
## Run as a background process
|
||||
|
||||
daemonize = false
|
||||
|
||||
|
||||
## Log file
|
||||
|
||||
# log_file = "/tmp/encrypted-dns.log"
|
||||
|
||||
|
||||
## PID file
|
||||
|
||||
# pid_file = "/tmp/encrypted-dns.pid"
|
||||
|
||||
|
||||
## User name to drop privileges to, when started as root.
|
||||
|
||||
# user = "nobody"
|
||||
|
||||
|
||||
## Group name to drop privileges to, when started as root.
|
||||
|
||||
# group = "nobody"
|
||||
|
||||
|
||||
## Path to chroot() to, when started as root.
|
||||
## The path to the state file is relative to the chroot base.
|
||||
|
||||
# chroot = "/var/empty"
|
||||
|
||||
|
||||
|
||||
####################################
|
||||
# DNSCrypt settings #
|
||||
####################################
|
||||
|
||||
[dnscrypt]
|
||||
|
||||
## Provider name (with or without the `2.dnscrypt-cert.` prefix)
|
||||
|
||||
provider_name = "@PROVIDER_NAME@"
|
||||
|
||||
|
||||
## Does the server support DNSSEC?
|
||||
|
||||
dnssec = true
|
||||
|
||||
|
||||
## Does the server always returns correct answers (no filtering, including ad blocking)?
|
||||
|
||||
no_filters = true
|
||||
|
||||
|
||||
## Set to `true` if the server doesn't keep any information that can be used to identify users
|
||||
|
||||
no_logs = true
|
||||
|
||||
|
||||
## Key cache capacity, per certificate
|
||||
|
||||
key_cache_capacity = 10000
|
||||
|
||||
|
||||
|
||||
###############################
|
||||
# TLS settings #
|
||||
###############################
|
||||
|
||||
[tls]
|
||||
|
||||
## Where to prooxy TLS connections to (e.g. DoH server)
|
||||
|
||||
# upstream_addr = "127.0.0.1:4343"
|
@ -4,7 +4,11 @@ set -e
|
||||
|
||||
action="$1"
|
||||
|
||||
KEYS_DIR="/opt/dnscrypt-wrapper/etc/keys"
|
||||
LEGACY_KEYS_DIR="/opt/dnscrypt-wrapper/etc/keys"
|
||||
KEYS_DIR="/opt/encrypted-dns/etc/keys"
|
||||
CONF_DIR="/opt/encrypted-dns/etc"
|
||||
CONFIG_FILE="${CONF_DIR}/encrypted-dns.toml"
|
||||
|
||||
|
||||
# -N provider-name -E external-ip-address:port
|
||||
|
||||
@ -37,18 +41,14 @@ init() {
|
||||
esac
|
||||
|
||||
echo "Provider name: [$provider_name]"
|
||||
cd "$KEYS_DIR"
|
||||
/opt/dnscrypt-wrapper/sbin/dnscrypt-wrapper \
|
||||
--gen-provider-keypair --nolog --dnssec --nofilter \
|
||||
--provider-name="$provider_name" --ext-address="$ext_address" |
|
||||
tee "${KEYS_DIR}/provider-info.txt"
|
||||
chmod 640 "${KEYS_DIR}/secret.key"
|
||||
chmod 644 "${KEYS_DIR}/public.key"
|
||||
chown root:_dnscrypt-signer "${KEYS_DIR}/public.key" "${KEYS_DIR}/secret.key"
|
||||
|
||||
echo "$provider_name" > "${KEYS_DIR}/provider_name"
|
||||
chmod 644 "${KEYS_DIR}/provider_name"
|
||||
hexdump -ve '1/1 "%.2x"' < "${KEYS_DIR}/public.key" > "${KEYS_DIR}/public.key.txt"
|
||||
chmod 644 "${KEYS_DIR}/public.key.txt"
|
||||
|
||||
/opt/encrypted-dns/sbin/dnscrypted-dns \
|
||||
--config "$CONFIG_FILE" --dry-run |
|
||||
tee "${KEYS_DIR}/provider-info.txt"
|
||||
|
||||
echo
|
||||
echo -----------------------------------------------------------------------
|
||||
echo
|
||||
@ -59,16 +59,13 @@ init() {
|
||||
|
||||
provider_info() {
|
||||
ensure_initialized
|
||||
echo "Provider name:"
|
||||
cat "${KEYS_DIR}/provider_name"
|
||||
echo
|
||||
echo "Provider public key:"
|
||||
cat "${KEYS_DIR}/public.key.txt"
|
||||
cat "${KEYS_DIR}/provider-info.txt"
|
||||
echo
|
||||
}
|
||||
|
||||
is_initialized() {
|
||||
if [ ! -f "${KEYS_DIR}/public.key" ] && [ ! -f "${KEYS_DIR}/secret.key" ] && [ ! -f "${KEYS_DIR}/provider_name" ]; then
|
||||
if [ ! -f "${KEYS_DIR}/encrypted-dns.state" ] && [ ! -f "${KEYS_DIR}/provider-info.txt" ] && [ ! -f "${KEYS_DIR}/provider_name" ]; then
|
||||
echo no
|
||||
else
|
||||
echo yes
|
||||
@ -104,7 +101,7 @@ Ports 443/udp and 443/tcp have to be publicly exposed.
|
||||
* provider-info: prints the provider name and provider public key.
|
||||
|
||||
This container has a single volume that you might want to securely keep a
|
||||
backup of: /opt/dnscrypt-wrapper/etc/keys
|
||||
backup of: /opt/encrypted-dns/etc/keys
|
||||
EOT
|
||||
exit 1
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
sleep 1800
|
||||
|
||||
KEYS_DIR="/opt/dnscrypt-wrapper/etc/keys"
|
||||
STKEYS_DIR="${KEYS_DIR}/short-term"
|
||||
|
||||
rotation_needed() {
|
||||
if [ "$(/usr/bin/find "$STKEYS_DIR" -type f -cmin -720 -print -quit | wc -l | sed 's/[^0-9]//g')" -le 0 ]; then
|
||||
echo true
|
||||
else
|
||||
echo false
|
||||
fi
|
||||
}
|
||||
|
||||
[ "$(rotation_needed)" = true ] || exit 0
|
||||
sv status dnscrypt-wrapper | grep -E -q '^run:' || exit 0
|
||||
sv restart dnscrypt-wrapper
|
@ -20,7 +20,7 @@ spec:
|
||||
name: dnscrypt
|
||||
volumeMounts:
|
||||
- name: dnscrypt-keys
|
||||
mountPath: /opt/dnscrypt-wrapper/etc/keys
|
||||
mountPath: /opt/encrypted-dns/etc/keys
|
||||
command: ["/entrypoint.sh", "start"]
|
||||
resources:
|
||||
requests:
|
||||
|
@ -13,7 +13,7 @@ spec:
|
||||
command: ["/entrypoint.sh", "init", "-N", "example.com", "-E", "192.168.1.1:443"]
|
||||
volumeMounts:
|
||||
- name: dnscrypt-keys
|
||||
mountPath: /opt/dnscrypt-wrapper/etc/keys
|
||||
mountPath: /opt/encrypted-dns/etc/keys
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: dnscrypt-keys
|
||||
|
574
queue.h
574
queue.h
@ -1,574 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
/*
|
||||
* This file defines five types of data structures: singly-linked lists,
|
||||
* lists, simple queues, tail queues, and circular queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The
|
||||
* elements are singly linked for minimum space and pointer manipulation
|
||||
* overhead at the expense of O(n) removal for arbitrary elements. New
|
||||
* elements can be added to the list after an existing element or at the
|
||||
* head of the list. Elements being removed from the head of the list
|
||||
* should use the explicit macro for this purpose for optimum
|
||||
* efficiency. A singly-linked list may only be traversed in the forward
|
||||
* direction. Singly-linked lists are ideal for applications with large
|
||||
* datasets and few or no removals or for implementing a LIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A simple queue is headed by a pair of pointers, one the head of the
|
||||
* list and the other to the tail of the list. The elements are singly
|
||||
* linked to save space, so elements can only be removed from the
|
||||
* head of the list. New elements can be added to the list after
|
||||
* an existing element, at the head of the list, or at the end of the
|
||||
* list. A simple queue may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the list.
|
||||
* A circle queue may be traversed in either direction, but has a more
|
||||
* complex end of list detection.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*/
|
||||
|
||||
/*
|
||||
* List definitions.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
#define LIST_INIT(head) do { \
|
||||
(head)->lh_first = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
|
||||
(listelm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
(listelm)->field.le_next = (elm); \
|
||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
(elm)->field.le_next = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
|
||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
||||
(head)->lh_first = (elm); \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if ((elm)->field.le_next != NULL) \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->lh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.le_next))
|
||||
|
||||
/*
|
||||
* List access methods.
|
||||
*/
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
|
||||
/*
|
||||
* Singly-linked List definitions.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_INIT(head) do { \
|
||||
(head)->slh_first = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
(elm)->field.sle_next = (slistelm)->field.sle_next; \
|
||||
(slistelm)->field.sle_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.sle_next = (head)->slh_first; \
|
||||
(head)->slh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
(head)->slh_first = (head)->slh_first->field.sle_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->slh_first == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = (head)->slh_first; \
|
||||
while(curelm->field.sle_next != (elm)) \
|
||||
curelm = curelm->field.sle_next; \
|
||||
curelm->field.sle_next = \
|
||||
curelm->field.sle_next->field.sle_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
|
||||
|
||||
/*
|
||||
* Singly-linked List access methods.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first; /* first element */ \
|
||||
struct type **stqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_INIT(head) do { \
|
||||
(head)->stqh_first = NULL; \
|
||||
(head)->stqh_last = &(head)->stqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
|
||||
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||
(head)->stqh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.stqe_next = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
|
||||
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||
(listelm)->field.stqe_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
|
||||
(head)->stqh_last = &(head)->stqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->stqh_first == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} else { \
|
||||
struct type *curelm = (head)->stqh_first; \
|
||||
while (curelm->field.stqe_next != (elm)) \
|
||||
curelm = curelm->field.stqe_next; \
|
||||
if ((curelm->field.stqe_next = \
|
||||
curelm->field.stqe_next->field.stqe_next) == NULL) \
|
||||
(head)->stqh_last = &(curelm)->field.stqe_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->stqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.stqe_next))
|
||||
|
||||
#define STAILQ_CONCAT(head1, head2) do { \
|
||||
if (!STAILQ_EMPTY((head2))) { \
|
||||
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||
(head1)->stqh_last = (head2)->stqh_last; \
|
||||
STAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue access methods.
|
||||
*/
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
|
||||
/*
|
||||
* Simple queue definitions.
|
||||
*/
|
||||
#define SIMPLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sqh_first; /* first element */ \
|
||||
struct type **sqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define SIMPLEQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).sqh_first }
|
||||
|
||||
#define SIMPLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple queue functions.
|
||||
*/
|
||||
#define SIMPLEQ_INIT(head) do { \
|
||||
(head)->sqh_first = NULL; \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(head)->sqh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
*(head)->sqh_last = (elm); \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(listelm)->field.sqe_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
|
||||
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->sqh_first == (elm)) { \
|
||||
SIMPLEQ_REMOVE_HEAD((head), field); \
|
||||
} else { \
|
||||
struct type *curelm = (head)->sqh_first; \
|
||||
while (curelm->field.sqe_next != (elm)) \
|
||||
curelm = curelm->field.sqe_next; \
|
||||
if ((curelm->field.sqe_next = \
|
||||
curelm->field.sqe_next->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(curelm)->field.sqe_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->sqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.sqe_next))
|
||||
|
||||
/*
|
||||
* Simple queue access methods.
|
||||
*/
|
||||
#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
|
||||
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
|
||||
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
|
||||
|
||||
|
||||
/*
|
||||
* Tail queue definitions.
|
||||
*/
|
||||
#define _TAILQ_HEAD(name, type, qual) \
|
||||
struct name { \
|
||||
qual type *tqh_first; /* first element */ \
|
||||
qual type *qual *tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define _TAILQ_ENTRY(type, qual) \
|
||||
struct { \
|
||||
qual type *tqe_next; /* next element */ \
|
||||
qual type *qual *tqe_prev; /* address of previous next element */\
|
||||
}
|
||||
#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_INIT(head) do { \
|
||||
(head)->tqh_first = NULL; \
|
||||
(head)->tqh_last = &(head)->tqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
|
||||
(head)->tqh_first->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(head)->tqh_first = (elm); \
|
||||
(elm)->field.tqe_prev = &(head)->tqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(listelm)->field.tqe_next = (elm); \
|
||||
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next) != NULL) \
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->tqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.tqe_next))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
|
||||
(var); \
|
||||
(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
|
||||
|
||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
TAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* Tail queue access methods.
|
||||
*/
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
|
||||
/*
|
||||
* Circular queue definitions.
|
||||
*/
|
||||
#define CIRCLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *cqh_first; /* first element */ \
|
||||
struct type *cqh_last; /* last element */ \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_HEAD_INITIALIZER(head) \
|
||||
{ (void *)&head, (void *)&head }
|
||||
|
||||
#define CIRCLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *cqe_next; /* next element */ \
|
||||
struct type *cqe_prev; /* previous element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue functions.
|
||||
*/
|
||||
#define CIRCLEQ_INIT(head) do { \
|
||||
(head)->cqh_first = (void *)(head); \
|
||||
(head)->cqh_last = (void *)(head); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
|
||||
(elm)->field.cqe_prev = (listelm); \
|
||||
if ((listelm)->field.cqe_next == (void *)(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
|
||||
(listelm)->field.cqe_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
|
||||
(elm)->field.cqe_next = (listelm); \
|
||||
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
|
||||
if ((listelm)->field.cqe_prev == (void *)(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
|
||||
(listelm)->field.cqe_prev = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.cqe_next = (head)->cqh_first; \
|
||||
(elm)->field.cqe_prev = (void *)(head); \
|
||||
if ((head)->cqh_last == (void *)(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(head)->cqh_first->field.cqe_prev = (elm); \
|
||||
(head)->cqh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.cqe_next = (void *)(head); \
|
||||
(elm)->field.cqe_prev = (head)->cqh_last; \
|
||||
if ((head)->cqh_first == (void *)(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(head)->cqh_last->field.cqe_next = (elm); \
|
||||
(head)->cqh_last = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
||||
if ((elm)->field.cqe_next == (void *)(head)) \
|
||||
(head)->cqh_last = (elm)->field.cqe_prev; \
|
||||
else \
|
||||
(elm)->field.cqe_next->field.cqe_prev = \
|
||||
(elm)->field.cqe_prev; \
|
||||
if ((elm)->field.cqe_prev == (void *)(head)) \
|
||||
(head)->cqh_first = (elm)->field.cqe_next; \
|
||||
else \
|
||||
(elm)->field.cqe_prev->field.cqe_next = \
|
||||
(elm)->field.cqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->cqh_first); \
|
||||
(var) != (const void *)(head); \
|
||||
(var) = ((var)->field.cqe_next))
|
||||
|
||||
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
|
||||
for ((var) = ((head)->cqh_last); \
|
||||
(var) != (const void *)(head); \
|
||||
(var) = ((var)->field.cqe_prev))
|
||||
|
||||
/*
|
||||
* Circular queue access methods.
|
||||
*/
|
||||
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
|
||||
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
||||
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
||||
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
|
||||
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
|
||||
|
||||
#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
|
||||
(((elm)->field.cqe_next == (void *)(head)) \
|
||||
? ((head)->cqh_first) \
|
||||
: (elm->field.cqe_next))
|
||||
#define CIRCLEQ_LOOP_PREV(head, elm, field) \
|
||||
(((elm)->field.cqe_prev == (void *)(head)) \
|
||||
? ((head)->cqh_last) \
|
||||
: (elm->field.cqe_prev))
|
||||
|
||||
#endif /* sys/queue.h */
|
@ -1,6 +1,6 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
KEYS_DIR="/opt/dnscrypt-wrapper/etc/keys"
|
||||
KEYS_DIR="/opt/encrypted-dns/etc/keys"
|
||||
ZONES_DIR="/opt/unbound/etc/unbound/zones"
|
||||
|
||||
reserved=134217728
|
||||
|
@ -2,15 +2,14 @@
|
||||
|
||||
sleep 300
|
||||
|
||||
for service in unbound dnscrypt-wrapper; do
|
||||
for service in unbound encrypted-dns; do
|
||||
sv check "$service" || sv force-restart "$service"
|
||||
done
|
||||
|
||||
KEYS_DIR="/opt/dnscrypt-wrapper/etc/keys"
|
||||
KEYS_DIR="/opt/encrypted-dns/etc/keys"
|
||||
GRACE_PERIOD=60
|
||||
|
||||
provider_key=$(cat "${KEYS_DIR}/public.key.txt")
|
||||
provider_name=$(cat "${KEYS_DIR}/provider_name")
|
||||
|
||||
drill -p 443 -Q TXT "$provider_name" @127.0.0.1 ||
|
||||
sv force-restart dnscrypt-wrapper
|
||||
sv force-restart encrypted-dns
|
||||
|
Loading…
Reference in New Issue
Block a user