Full Code of pymumu/smartdns for AI

master 115db1f4537c cached
405 files
2.5 MB
686.3k tokens
3220 symbols
1 requests
Download .txt
Showing preview only (2,736K chars total). Download the full file or copy to clipboard to get everything.
Repository: pymumu/smartdns
Branch: master
Commit: 115db1f4537c
Files: 405
Total size: 2.5 MB

Directory structure:
gitextract_d_s45j8t/

├── .clang-format
├── .clang-tidy
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── feature.md
│   │   └── issue.md
│   └── workflows/
│       ├── c-cpp.yml
│       ├── docker.yml
│       └── webui.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── Makefile
├── ReadMe.md
├── ReadMe_en.md
├── doc/
│   └── architecture.vsdx
├── etc/
│   ├── default/
│   │   └── smartdns
│   ├── init.d/
│   │   └── smartdns
│   └── smartdns/
│       └── smartdns.conf
├── package/
│   ├── build-pkg.sh
│   ├── copy-smartdns.sh
│   ├── debian/
│   │   ├── DEBIAN/
│   │   │   ├── changelog
│   │   │   ├── compat
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── copyright
│   │   │   ├── prerm
│   │   │   └── rules
│   │   └── make.sh
│   ├── linux/
│   │   ├── install
│   │   └── make.sh
│   ├── luci/
│   │   ├── control/
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── debian-binary
│   │   ├── files/
│   │   │   ├── luci/
│   │   │   │   └── i18n/
│   │   │   │       └── smartdns.zh-cn.po
│   │   │   └── root/
│   │   │       ├── usr/
│   │   │       │   └── share/
│   │   │       │       ├── luci/
│   │   │       │       │   └── menu.d/
│   │   │       │       │       └── luci-app-smartdns.json
│   │   │       │       └── rpcd/
│   │   │       │           └── acl.d/
│   │   │       │               └── luci-app-smartdns.json
│   │   │       └── www/
│   │   │           └── luci-static/
│   │   │               └── resources/
│   │   │                   └── view/
│   │   │                       └── smartdns/
│   │   │                           └── smartdns.js
│   │   └── make.sh
│   ├── luci-compat/
│   │   ├── control/
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── debian-binary
│   │   ├── files/
│   │   │   ├── etc/
│   │   │   │   └── uci-defaults/
│   │   │   │       └── 50_luci-smartdns
│   │   │   ├── luci/
│   │   │   │   ├── controller/
│   │   │   │   │   └── smartdns.lua
│   │   │   │   ├── i18n/
│   │   │   │   │   └── smartdns.zh-cn.po
│   │   │   │   ├── model/
│   │   │   │   │   ├── cbi/
│   │   │   │   │   │   └── smartdns/
│   │   │   │   │   │       ├── smartdns.lua
│   │   │   │   │   │       └── upstream.lua
│   │   │   │   │   └── smartdns.lua
│   │   │   │   └── view/
│   │   │   │       └── smartdns/
│   │   │   │           └── smartdns_status.htm
│   │   │   └── usr/
│   │   │       └── share/
│   │   │           └── rpcd/
│   │   │               └── acl.d/
│   │   │                   └── luci-app-smartdns.json
│   │   └── make.sh
│   ├── luci-lite/
│   │   ├── control/
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── debian-binary
│   │   ├── files/
│   │   │   ├── luci/
│   │   │   │   └── i18n/
│   │   │   │       └── smartdns-lite.zh-cn.po
│   │   │   └── root/
│   │   │       ├── etc/
│   │   │       │   ├── config/
│   │   │       │   │   └── smartdns-lite
│   │   │       │   └── init.d/
│   │   │       │       └── smartdns-lite
│   │   │       ├── usr/
│   │   │       │   └── share/
│   │   │       │       ├── luci/
│   │   │       │       │   └── menu.d/
│   │   │       │       │       └── luci-app-smartdns-lite.json
│   │   │       │       └── rpcd/
│   │   │       │           └── acl.d/
│   │   │       │               └── luci-app-smartdns-lite.json
│   │   │       └── www/
│   │   │           └── luci-static/
│   │   │               └── resources/
│   │   │                   └── view/
│   │   │                       └── smartdns-lite/
│   │   │                           └── smartdns-lite.js
│   │   └── make.sh
│   ├── openwrt/
│   │   ├── Makefile
│   │   ├── address.conf
│   │   ├── blacklist-ip.conf
│   │   ├── control/
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── custom.conf
│   │   ├── debian-binary
│   │   ├── domain-block.list
│   │   ├── domain-forwarding.list
│   │   ├── files/
│   │   │   └── etc/
│   │   │       ├── config/
│   │   │       │   └── smartdns
│   │   │       └── init.d/
│   │   │           └── smartdns
│   │   └── make.sh
│   ├── optware/
│   │   ├── S50smartdns
│   │   ├── control/
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── debian-binary
│   │   ├── make.sh
│   │   └── smartdns-opt.conf
│   ├── redhat/
│   │   └── smartdns.spec
│   ├── run-smartdns
│   ├── tool/
│   │   └── po2lmo/
│   │       ├── Makefile
│   │       └── src/
│   │           ├── po2lmo.c
│   │           ├── template_lmo.c
│   │           └── template_lmo.h
│   └── windows/
│       ├── install.bat
│       ├── reload.bat
│       ├── uninstall.bat
│       └── wsl-run.vbs
├── plugin/
│   ├── demo/
│   │   ├── .gitignore
│   │   ├── Makefile
│   │   ├── demo.c
│   │   └── demo.h
│   └── smartdns-ui/
│       ├── .gitignore
│       ├── Cargo.toml
│       ├── Makefile
│       ├── build.rs
│       ├── src/
│       │   ├── data_server.rs
│       │   ├── data_stats.rs
│       │   ├── data_upstream_server.rs
│       │   ├── db.rs
│       │   ├── http_api_msg.rs
│       │   ├── http_error.rs
│       │   ├── http_jwt.rs
│       │   ├── http_server.rs
│       │   ├── http_server_api.rs
│       │   ├── http_server_stream.rs
│       │   ├── lib.rs
│       │   ├── plugin.rs
│       │   ├── server_log.rs
│       │   ├── smartdns.rs
│       │   ├── utils.rs
│       │   └── whois.rs
│       └── tests/
│           ├── common/
│           │   ├── client.rs
│           │   ├── mod.rs
│           │   └── server.rs
│           ├── httpserver_test.rs
│           └── restapi_test.rs
├── src/
│   ├── .gitignore
│   ├── Makefile
│   ├── dns.c
│   ├── dns_cache.c
│   ├── dns_client/
│   │   ├── client_http2.c
│   │   ├── client_http2.h
│   │   ├── client_http3.c
│   │   ├── client_http3.h
│   │   ├── client_https.c
│   │   ├── client_https.h
│   │   ├── client_mdns.c
│   │   ├── client_mdns.h
│   │   ├── client_quic.c
│   │   ├── client_quic.h
│   │   ├── client_socket.c
│   │   ├── client_socket.h
│   │   ├── client_tcp.c
│   │   ├── client_tcp.h
│   │   ├── client_tls.c
│   │   ├── client_tls.h
│   │   ├── client_udp.c
│   │   ├── client_udp.h
│   │   ├── conn_stream.c
│   │   ├── conn_stream.h
│   │   ├── dns_client.c
│   │   ├── dns_client.h
│   │   ├── ecs.c
│   │   ├── ecs.h
│   │   ├── group.c
│   │   ├── group.h
│   │   ├── packet.c
│   │   ├── packet.h
│   │   ├── pending_server.c
│   │   ├── pending_server.h
│   │   ├── proxy.c
│   │   ├── proxy.h
│   │   ├── query.c
│   │   ├── query.h
│   │   ├── server_info.c
│   │   ├── server_info.h
│   │   ├── wake_event.c
│   │   └── wake_event.h
│   ├── dns_conf/
│   │   ├── address.c
│   │   ├── address.h
│   │   ├── bind.c
│   │   ├── bind.h
│   │   ├── bootstrap_dns.c
│   │   ├── bootstrap_dns.h
│   │   ├── client_rule.c
│   │   ├── client_rule.h
│   │   ├── client_subnet.c
│   │   ├── client_subnet.h
│   │   ├── cname.c
│   │   ├── cname.h
│   │   ├── conf_file.c
│   │   ├── conf_file.h
│   │   ├── ddns_domain.c
│   │   ├── ddns_domain.h
│   │   ├── dhcp_lease_dnsmasq.c
│   │   ├── dhcp_lease_dnsmasq.h
│   │   ├── dns64.c
│   │   ├── dns64.h
│   │   ├── dns_conf.c
│   │   ├── dns_conf.h
│   │   ├── dns_conf_group.c
│   │   ├── dns_conf_group.h
│   │   ├── domain_rule.c
│   │   ├── domain_rule.h
│   │   ├── domain_set.c
│   │   ├── domain_set.h
│   │   ├── get_domain.c
│   │   ├── get_domain.h
│   │   ├── group.c
│   │   ├── group.h
│   │   ├── host_file.c
│   │   ├── host_file.h
│   │   ├── https_record.c
│   │   ├── https_record.h
│   │   ├── ip_alias.c
│   │   ├── ip_alias.h
│   │   ├── ip_rule.c
│   │   ├── ip_rule.h
│   │   ├── ip_set.c
│   │   ├── ip_set.h
│   │   ├── ipset.c
│   │   ├── ipset.h
│   │   ├── local_domain.c
│   │   ├── local_domain.h
│   │   ├── nameserver.c
│   │   ├── nameserver.h
│   │   ├── nftset.c
│   │   ├── nftset.h
│   │   ├── plugin.c
│   │   ├── plugin.h
│   │   ├── proxy_names.c
│   │   ├── proxy_names.h
│   │   ├── proxy_server.c
│   │   ├── proxy_server.h
│   │   ├── ptr.c
│   │   ├── ptr.h
│   │   ├── qtype_soa.c
│   │   ├── qtype_soa.h
│   │   ├── server.c
│   │   ├── server.h
│   │   ├── server_group.c
│   │   ├── server_group.h
│   │   ├── set_file.c
│   │   ├── set_file.h
│   │   ├── smartdns_domain.c
│   │   ├── smartdns_domain.h
│   │   ├── speed_check_mode.c
│   │   ├── speed_check_mode.h
│   │   ├── srv_record.c
│   │   └── srv_record.h
│   ├── dns_plugin.c
│   ├── dns_server/
│   │   ├── address.c
│   │   ├── address.h
│   │   ├── answer.c
│   │   ├── answer.h
│   │   ├── audit.c
│   │   ├── audit.h
│   │   ├── cache.c
│   │   ├── cache.h
│   │   ├── client_rule.c
│   │   ├── client_rule.h
│   │   ├── cname.c
│   │   ├── cname.h
│   │   ├── connection.c
│   │   ├── connection.h
│   │   ├── context.c
│   │   ├── context.h
│   │   ├── ddr.c
│   │   ├── ddr.h
│   │   ├── dns64.c
│   │   ├── dns64.h
│   │   ├── dns_server.c
│   │   ├── dns_server.h
│   │   ├── dualstack.c
│   │   ├── dualstack.h
│   │   ├── ip_rule.c
│   │   ├── ip_rule.h
│   │   ├── ipset_nftset.c
│   │   ├── ipset_nftset.h
│   │   ├── local_addr.c
│   │   ├── local_addr.h
│   │   ├── mdns.c
│   │   ├── mdns.h
│   │   ├── neighbor.c
│   │   ├── neighbor.h
│   │   ├── prefetch.c
│   │   ├── prefetch.h
│   │   ├── ptr.c
│   │   ├── ptr.h
│   │   ├── request.c
│   │   ├── request.h
│   │   ├── request_pending.c
│   │   ├── request_pending.h
│   │   ├── rules.c
│   │   ├── rules.h
│   │   ├── server_http2.c
│   │   ├── server_http2.h
│   │   ├── server_https.c
│   │   ├── server_https.h
│   │   ├── server_socket.c
│   │   ├── server_socket.h
│   │   ├── server_tcp.c
│   │   ├── server_tcp.h
│   │   ├── server_tls.c
│   │   ├── server_tls.h
│   │   ├── server_udp.c
│   │   ├── server_udp.h
│   │   ├── soa.c
│   │   ├── soa.h
│   │   ├── speed_check.c
│   │   └── speed_check.h
│   ├── dns_stats.c
│   ├── fast_ping/
│   │   ├── fast_ping.c
│   │   ├── fast_ping.h
│   │   ├── notify_event.c
│   │   ├── notify_event.h
│   │   ├── ping_fake.c
│   │   ├── ping_fake.h
│   │   ├── ping_host.c
│   │   ├── ping_host.h
│   │   ├── ping_icmp.c
│   │   ├── ping_icmp.h
│   │   ├── ping_icmp6.c
│   │   ├── ping_icmp6.h
│   │   ├── ping_tcp.c
│   │   ├── ping_tcp.h
│   │   ├── ping_tcp_syn.c
│   │   ├── ping_tcp_syn.h
│   │   ├── ping_udp.c
│   │   ├── ping_udp.h
│   │   ├── wakeup_event.c
│   │   └── wakeup_event.h
│   ├── http_parse/
│   │   ├── hpack.c
│   │   ├── hpack.h
│   │   ├── http1_parse.c
│   │   ├── http1_parse.h
│   │   ├── http2.c
│   │   ├── http3_parse.c
│   │   ├── http3_parse.h
│   │   ├── http_parse.c
│   │   ├── http_parse.h
│   │   ├── qpack.c
│   │   └── qpack.h
│   ├── lib/
│   │   ├── art.c
│   │   ├── bitops.c
│   │   ├── conf.c
│   │   ├── idna.c
│   │   ├── radix.c
│   │   ├── rbtree.c
│   │   ├── stringutil.c
│   │   └── timer_wheel.c
│   ├── main.c
│   ├── proxy.c
│   ├── smartdns.c
│   ├── timer.c
│   ├── tlog.c
│   └── utils/
│       ├── alpn.c
│       ├── capbility.c
│       ├── daemon.c
│       ├── dns_debug.c
│       ├── ipset.c
│       ├── misc.c
│       ├── neighbors.c
│       ├── net.c
│       ├── nftset.c
│       ├── ssl.c
│       ├── stack.c
│       ├── tls_header_parse.c
│       └── url.c
├── systemd/
│   └── smartdns.service.in
└── test/
    ├── Makefile
    ├── cases/
    │   ├── test-address.cc
    │   ├── test-audit.cc
    │   ├── test-bind.cc
    │   ├── test-bootstrap.cc
    │   ├── test-cache.cc
    │   ├── test-client-rule.cc
    │   ├── test-cname.cc
    │   ├── test-ddns.cc
    │   ├── test-ddr.cc
    │   ├── test-discard-block-ip.cc
    │   ├── test-dns64.cc
    │   ├── test-domain-rule.cc
    │   ├── test-domain-set.cc
    │   ├── test-dualstack.cc
    │   ├── test-edns.cc
    │   ├── test-group.cc
    │   ├── test-hosts.cc
    │   ├── test-http.cc
    │   ├── test-http2.cc
    │   ├── test-https.cc
    │   ├── test-idna.cc
    │   ├── test-ip-alias.cc
    │   ├── test-ip-rule.cc
    │   ├── test-lib-http2.cc
    │   ├── test-local-domain.cc
    │   ├── test-mdns.cc
    │   ├── test-mock-server.cc
    │   ├── test-nameserver.cc
    │   ├── test-perf.cc
    │   ├── test-ping.cc
    │   ├── test-ptr.cc
    │   ├── test-qtype-soa.cc
    │   ├── test-rule.cc
    │   ├── test-same-pending-query.cc
    │   ├── test-server.cc
    │   ├── test-speed-check.cc
    │   ├── test-srv.cc
    │   ├── test-stress.cc
    │   └── test-subnet.cc
    ├── client.cc
    ├── client.h
    ├── include/
    │   └── utils.h
    ├── server.cc
    ├── server.h
    ├── test.cc
    └── utils.cc

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
#http://clang.llvm.org/docs/ClangFormatStyleOptions.html

BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: ForContinuationAndIndentation
MaxEmptyLinesToKeep: 1
AllowShortFunctionsOnASingleLine: Empty
BreakBeforeBraces: Linux
ColumnLimit: 120


================================================
FILE: .clang-tidy
================================================
Checks: >
  -*,
  modernize-*,
  bugprone-*,
  concurrency-*,
  misc-*,
  readability-*,
  performance-*,
  portability-*,
  google-*,
  linuxkernel-*,
  -bugprone-narrowing-conversions,
  -bugprone-branch-clone,
  -bugprone-reserved-identifier,
  -bugprone-easily-swappable-parameters,
  -bugprone-sizeof-expression,
  -bugprone-implicit-widening-of-multiplication-result,
  -bugprone-suspicious-memory-comparison,
  -bugprone-not-null-terminated-result,
  -bugprone-signal-handler,
  -bugprone-assignment-in-if-condition,
  -concurrency-mt-unsafe,
  -modernize-macro-to-enum,
  -misc-unused-parameters,
  -misc-misplaced-widening-cast,
  -misc-no-recursion,
  -misc-include-cleaner,
  -readability-magic-numbers,
  -readability-use-anyofallof,
  -readability-identifier-length,
  -readability-function-cognitive-complexity,
  -readability-named-parameter,
  -readability-isolate-declaration,
  -readability-else-after-return,
  -readability-redundant-control-flow,
  -readability-suspicious-call-argument,
  -readability-math-missing-parentheses,
  -google-readability-casting,
  -google-readability-todo,
  -performance-no-int-to-ptr,
#   clang-analyzer-*,
#   clang-analyzer-deadcode.DeadStores,
#   clang-analyzer-optin.performance.Padding,
#   -clang-analyzer-security.insecureAPI.*

# Turn all the warnings from the checks above into errors.
FormatStyle: file


================================================
FILE: .github/ISSUE_TEMPLATE/feature.md
================================================
---
name: 需求建议
about: 需求建议描述
title: ''
labels: ''
assignees: ''

---

**需求应用场景**
请描述需求应用的场景和方式。

**建议的方案**
实现上述场景建议的方案。

**设备信息**
1. 设备信息(CPU,厂家)  

2. 固件信息



================================================
FILE: .github/ISSUE_TEMPLATE/issue.md
================================================
---
name: 问题报告
about: 问题现象描述
title: ''
labels: ''
assignees: ''

---

**问题现象**  
简要描述问题出现的现象

**运行环境**
1. 固件型号  

2. 运营商  

3. smartdns来源以及版本

4. 涉及的配置(注意去除个人相关信息)


**重现步骤**
1. 上游DNS配置。  

2. 访问的域名。  


**信息收集**  
1. 将/var/log/smrtdns.log日志作为附件上传(注意去除个人相关信息)。  
2. 如进程异常,请将coredump功能开启,上传coredump信息文件,同时上传配套的smartdns进程文件。  
在自定义界面,开启设置->自定义设置->生成coredump配置,重现问题后提交coredump文件
coredump文件在/tmp目录下



================================================
FILE: .github/workflows/c-cpp.yml
================================================
name: C/C++ CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: prepare
      run: |
        sudo apt update
        sudo apt install libgtest-dev dnsperf
    - name: make
      run: |
        make all -j4
        make clean
    - name: test
      run: |
        make -C test test -j8


================================================
FILE: .github/workflows/docker.yml
================================================
name: Publish Docker Image

on:
  workflow_dispatch:
    inputs:
      version:
        description: 'new image tag(e.g. v1.1.0)'
        required: true
        default: 'latest'

concurrency: 
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
   docker:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout repository
         uses: actions/checkout@v3
       - name: Set up QEMU
         uses: docker/setup-qemu-action@v2
       - name: Set up Docker Buildx
         uses: docker/setup-buildx-action@v2
       - name: Login to DockerHub
         uses: docker/login-action@v2
         with:
           username: ${{ secrets.DOCKERHUB_USERNAME }}
           password: ${{ secrets.DOCKERHUB_TOKEN }}
       - name: Build and push
         uses: docker/build-push-action@v3
         with:
           platforms: linux/amd64,linux/arm64
           push: true
           tags: ${{vars.DOCKERHUB_REPO}}:${{ github.event.inputs.version }}


================================================
FILE: .github/workflows/webui.yml
================================================
name: WebUI CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: actions-rust-lang/setup-rust-toolchain@v1
      with:
        profile: minimal
        toolchain: stable
    - name: test
      run: |
        EXTRA_CFLAGS=-fPIC make -C plugin/smartdns-ui test -j8


================================================
FILE: .gitignore
================================================
.vscode
*.o
*.a
*.pem
.DS_Store
*.swp.
*.a
systemd/smartdns.service
test.bin
package/target
package/*.gz
package/*.ipk
target


================================================
FILE: Dockerfile
================================================
FROM ubuntu:latest AS smartdns-builder
LABEL previous-stage=smartdns-builder

# prepare builder
ARG OPENSSL_VER=3.5.4
ARG NODE_VERSION=20.x
RUN apt update && \
    apt install -y binutils perl curl make gcc clang wget unzip ca-certificates && \
    update-ca-certificates && \
    curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION} | bash - && \
    apt install -y nodejs && \
    node --version && npm --version && \
    \
    curl https://sh.rustup.rs -sSf | sh -s -- -y && \
    export PATH="$HOME/.cargo/bin:$PATH" && \
    \
    mkdir -p /build/openssl && \
    cd /build/openssl && \
    curl -sSL https://www.github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VER}/openssl-${OPENSSL_VER}.tar.gz | tar --strip-components=1 -zxv && \
    \
    OPENSSL_OPTIONS="no-argon2 no-aria no-async no-bf no-blake2 no-camellia no-cmp no-cms " \
    OPENSSL_OPTIONS="$OPENSSL_OPTIONS no-comp no-des no-dh no-dsa no-ec2m no-engine no-gost "\
    OPENSSL_OPTIONS="$OPENSSL_OPTIONS no-http no-idea no-legacy no-md4 no-mdc2 no-multiblock "\
    OPENSSL_OPTIONS="$OPENSSL_OPTIONS no-nextprotoneg no-ocb no-ocsp no-rc2 no-rc4 no-rmd160 "\
    OPENSSL_OPTIONS="$OPENSSL_OPTIONS no-scrypt no-seed no-siphash no-siv no-sm2 no-sm3 no-sm4 "\
    OPENSSL_OPTIONS="$OPENSSL_OPTIONS no-srp no-srtp no-ts no-whirlpool no-apps no-ssl-trace "\
    OPENSSL_OPTIONS="$OPENSSL_OPTIONS no-ssl no-ssl3 no-tests -Os" \
    cd /build/openssl && \
    if [ "$(uname -m)" = "aarch64" ]; then \
        ./config --prefix=/opt/build $OPENSSL_OPTIONS -mno-outline-atomics ; \
    else \ 
        ./config --prefix=/opt/build $OPENSSL_OPTIONS ; \
    fi && \
    mkdir -p /opt/build/lib /opt/build/lib64 && \
    make all -j8 && make install_sw && \
    cd / && rm -rf /build

# do make
COPY . /build/smartdns/
RUN cd /build/smartdns && \
    export CFLAGS="-I /opt/build/include" && \
    export LDFLAGS="-L /opt/build/lib -L /opt/build/lib64" && \
    export PATH="$HOME/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" && \
    rm -fr /build/smartdns/package/*.tar.gz && \
    sh ./package/build-pkg.sh --platform linux --arch `dpkg --print-architecture` --with-ui --static && \
    \
    ( cd package && tar -xvf *.tar.gz && chmod a+x smartdns/etc/init.d/smartdns ) && \
    \
    mkdir -p /release/var/log /release/run /release/var/lib/smartdns && \
    cp package/smartdns/etc /release/ -a && \
    cp package/smartdns/usr /release/ -a && \
    rm -f /release/usr/local/smartdns/lib/libssl* && \
    rm -f /release/usr/local/smartdns/lib/libcrypto* && \
    cp /opt/build/lib/lib*.so* /release/usr/local/lib/smartdns/lib/ -a 2>/dev/null || true && \
    cp /opt/build/lib64/lib*.so* /release/usr/local/lib/smartdns/lib/ -a 2>/dev/null || true && \
    cd / && rm -rf /build

FROM busybox:stable-musl
COPY --from=smartdns-builder /release/ /
EXPOSE 53/udp 6080/tcp
VOLUME ["/etc/smartdns/", "/var/lib/smartdns/"]

CMD ["/usr/sbin/smartdns", "-f", "-x"]


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: Makefile
================================================
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

PKG_CONFIG := pkg-config
DESTDIR :=
PREFIX := /usr
SBINDIR := $(PREFIX)/sbin
SLIBDIR := $(PREFIX)/lib
SYSCONFDIR := /etc
RUNSTATEDIR := /run
SYSTEMDSYSTEMUNITDIR := $(shell ${PKG_CONFIG} --variable=systemdsystemunitdir systemd)
SMARTDNS_SYSTEMD = systemd/smartdns.service

ifneq ($(strip $(DESTDIR)),)
$(shell mkdir -p $(DESTDIR) -m 0755)
override DESTDIR := $(realpath $(DESTDIR))
endif

PLUGINS := 
WITH_UI ?= 0

ifeq ($(WITH_UI), 1)
PLUGINS += plugin/smartdns-ui
endif

define PLUGINS_TARGETS
    $(foreach plugin,$(PLUGINS),$(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) -C $(plugin) $(1);)
endef

.PHONY: all clean install help SMARTDNS_BIN 
all: SMARTDNS_BIN 

SMARTDNS_BIN: $(SMARTDNS_SYSTEMD)
	$(MAKE) $(MFLAGS) -C src all
	$(call PLUGINS_TARGETS, all)

$(SMARTDNS_SYSTEMD): systemd/smartdns.service.in
	cp $< $@
	sed -i 's|@SBINDIR@|$(SBINDIR)|' $@
	sed -i 's|@SYSCONFDIR@|$(SYSCONFDIR)|' $@
	sed -i 's|@RUNSTATEDIR@|$(RUNSTATEDIR)|' $@

help:
	@echo "Options:"
	@echo "  WITH_UI=1: Build with smartdns-ui plugin" 
	@echo "  OPTIMIZE_SIZE=1: Optimize size of the smartdns-ui plugin (only for smartdns-ui)"
	@echo "  DESTDIR: Specify the installation directory prefix"

clean:
	$(MAKE) $(MFLAGS) -C src clean  
	$(RM) $(SMARTDNS_SYSTEMD)
	$(call PLUGINS_TARGETS, clean)

install: SMARTDNS_BIN 
	install -v -m 0640 -D -t $(DESTDIR)$(SYSCONFDIR)/default etc/default/smartdns
	install -v -m 0755 -D -t $(DESTDIR)$(SYSCONFDIR)/init.d etc/init.d/smartdns
	install -v -m 0640 -D -t $(DESTDIR)$(SYSCONFDIR)/smartdns etc/smartdns/smartdns.conf
	install -v -m 0755 -D -t $(DESTDIR)$(SBINDIR) src/smartdns
	install -v -m 0644 -D -t $(DESTDIR)$(SYSTEMDSYSTEMUNITDIR) systemd/smartdns.service
	$(call PLUGINS_TARGETS, install)



================================================
FILE: ReadMe.md
================================================
# SmartDNS

**[English](ReadMe_en.md)**

![SmartDNS](doc/smartdns-banner.png)
SmartDNS 是一个运行在本地的 DNS 服务器,它接受来自本地客户端的 DNS 查询请求,然后从多个上游 DNS 服务器获取 DNS 查询结果,并将访问速度最快的结果返回给客户端,以此提高网络访问速度。
SmartDNS 同时支持指定特定域名 IP 地址,并高性匹配,可达到过滤广告的效果; 支持DOT,DOH,DOQ,DOH3,更好的保护隐私。  

与 DNSmasq 的 all-servers 不同,SmartDNS 返回的是访问速度最快的解析结果。

支持树莓派、OpenWrt、华硕路由器原生固件和 Windows 系统等。

## 使用指导

SmartDNS官网:[https://pymumu.github.io/smartdns](https://pymumu.github.io/smartdns)

## 软件效果展示

### 仪表盘

![SmartDNS-WebUI](doc/smartdns-webui.png)

### 速度对比

**阿里 DNS**  
使用阿里 DNS 查询百度IP,并检测结果。  

```shell
$ nslookup www.baidu.com 223.5.5.5
Server:         223.5.5.5
Address:        223.5.5.5#53

Non-authoritative answer:
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 180.97.33.108
Name:   www.a.shifen.com
Address: 180.97.33.107

$ ping 180.97.33.107 -c 2
PING 180.97.33.107 (180.97.33.107) 56(84) bytes of data.
64 bytes from 180.97.33.107: icmp_seq=1 ttl=55 time=24.3 ms
64 bytes from 180.97.33.107: icmp_seq=2 ttl=55 time=24.2 ms

--- 180.97.33.107 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 24.275/24.327/24.380/0.164 ms
pi@raspberrypi:~/code/smartdns_build $ ping 180.97.33.108 -c 2
PING 180.97.33.108 (180.97.33.108) 56(84) bytes of data.
64 bytes from 180.97.33.108: icmp_seq=1 ttl=55 time=31.1 ms
64 bytes from 180.97.33.108: icmp_seq=2 ttl=55 time=31.0 ms

--- 180.97.33.108 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 31.014/31.094/31.175/0.193 ms
```

**SmartDNS**  
使用 SmartDNS 查询百度 IP,并检测结果。

```shell
$ nslookup www.baidu.com
Server:         192.168.1.1
Address:        192.168.1.1#53

Non-authoritative answer:
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 14.215.177.39

$ ping 14.215.177.39 -c 2
PING 14.215.177.39 (14.215.177.39) 56(84) bytes of data.
64 bytes from 14.215.177.39: icmp_seq=1 ttl=56 time=6.31 ms
64 bytes from 14.215.177.39: icmp_seq=2 ttl=56 time=5.95 ms

--- 14.215.177.39 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
```

从对比看出,SmartDNS 找到了访问 `www.baidu.com` 最快的 IP 地址,比阿里 DNS 速度快了 5 倍。

## 特性

1. **多虚拟DNS服务器**  
   支持多个虚拟DNS服务器,不同虚拟DNS服务器不同的端口,规则,客户端。

1. **多 DNS 上游服务器**  
   支持配置多个上游 DNS 服务器,并同时进行查询,即使其中有 DNS 服务器异常,也不会影响查询。  

1. **支持每个客户端独立控制**  
   支持基于MAC,IP地址控制客户端使用不同查询规则,可实现家长控制等功能。  

1. **返回最快 IP 地址**  
   支持从域名所属 IP 地址列表中查找到访问速度最快的 IP 地址,并返回给客户端,提高网络访问速度。

1. **支持多种查询协议**  
   支持 UDP、TCP、DOT、DOH、DOQ 和 DOH3 查询及服务,以及非 53 端口查询;支持通过socks5,HTTP代理查询;

1. **特定域名 IP 地址指定**  
   支持指定域名的 IP 地址,达到广告过滤效果、避免恶意网站的效果。

1. **域名高性能后缀匹配**  
   支持域名后缀匹配模式,简化过滤配置,过滤 20 万条记录时间 < 1ms。

1. **域名分流**  
   支持域名分流,不同类型的域名向不同的 DNS 服务器查询,支持iptable和nftable更好的分流;支持测速失败的情况下设置域名结果到对应ipset和nftset集合。

1. **Windows / Linux 多平台支持**  
   支持标准 Linux 系统(树莓派)、OpenWrt 系统各种固件和华硕路由器原生固件。同时还支持 WSL(Windows Subsystem for Linux,适用于 Linux 的 Windows 子系统)。

1. **支持 IPv4、IPv6 双栈**  
   支持 IPv4 和 IPV 6网络,支持查询 A 和 AAAA 记录,支持双栈 IP 速度优化,并支持完全禁用 IPv6 AAAA 解析。

1. **支持DNS64**  
   支持DNS64转换。

1. **高性能、占用资源少**  
   多线程异步 IO 模式,cache 缓存查询结果。

1. **主流系统官方支持**  
   主流路由系统官方软件源安装smartdns。

## 架构

![Architecture](https://github.com/pymumu/test/releases/download/blob/architecture.png)

1. SmartDNS 接收本地网络设备的DNS 查询请求,如 PC、手机的查询请求;
1. 然后将查询请求发送到多个上游 DNS 服务器,可支持 UDP 标准端口或非标准端口查询,以及 TCP 查询;
1. 上游 DNS 服务器返回域名对应的服务器 IP 地址列表,SmartDNS 则会检测从本地网络访问速度最快的服务器 IP;
1. 最后将访问速度最快的服务器 IP 返回给本地客户端。

## 编译

- 代码编译:

  SmartDNS 提供了编译软件包的脚本(`package/build-pkg.sh`),支持编译 LuCI、Debian、OpenWrt 和 Optware 安装包。

- 文档编译:

  文档分支为`doc`,安装`mkdocs`工具后,执行`mkdocs build`编译。

## 捐赠

如果你觉得此项目对你有帮助,请捐助我们,使项目能持续发展和更加完善。

### PayPal 贝宝

[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://paypal.me/PengNick/)

### AliPay 支付宝

![alipay](doc/alipay_donate.jpg)

### WeChat Pay 微信支付

![wechat](doc/wechat_donate.jpg)

## 开源声明

SmartDNS 基于 GPL V3 协议开源。


================================================
FILE: ReadMe_en.md
================================================
# SmartDNS

![SmartDNS](doc/smartdns-banner.png)  
SmartDNS is a local DNS server. SmartDNS accepts DNS query requests from local clients, obtains DNS query results from multiple upstream DNS servers, and returns the fastest access results to clients. supports secure DNS protocols like DoT, DoH, DoQ, DoH3, better protect privacy,  
Avoiding DNS pollution and improving network access speed, supports high-performance ad filtering.

Unlike dnsmasq's all-servers, smartdns returns the fastest access resolution.

Support Raspberry Pi, openwrt, ASUS router, Windows and other devices.  

## Usage

Please visit website: [https://pymumu.github.io/smartdns](https://pymumu.github.io/smartdns/en)

## Software Show

### Dashboard

![SmartDNS-WebUI](doc/smartdns-webui.png)

### Speed Comparison

**Ali DNS**  
Use Ali DNS to query Baidu's IP and test the results.  

```shell
pi@raspberrypi:~/code/smartdns_build $ nslookup www.baidu.com 223.5.5.5
Server:         223.5.5.5
Address:        223.5.5.5#53

Non-authoritative answer:
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 180.97.33.108
Name:   www.a.shifen.com
Address: 180.97.33.107

pi@raspberrypi:~/code/smartdns_build $ ping 180.97.33.107 -c 2
PING 180.97.33.107 (180.97.33.107) 56(84) bytes of data.
64 bytes from 180.97.33.107: icmp_seq=1 ttl=55 time=24.3 ms
64 bytes from 180.97.33.107: icmp_seq=2 ttl=55 time=24.2 ms

--- 180.97.33.107 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 24.275/24.327/24.380/0.164 ms
pi@raspberrypi:~/code/smartdns_build $ ping 180.97.33.108 -c 2
PING 180.97.33.108 (180.97.33.108) 56(84) bytes of data.
64 bytes from 180.97.33.108: icmp_seq=1 ttl=55 time=31.1 ms
64 bytes from 180.97.33.108: icmp_seq=2 ttl=55 time=31.0 ms

--- 180.97.33.108 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 31.014/31.094/31.175/0.193 ms
```

**smartdns**  
Use SmartDNS to query Baidu IP and test the results.

```shell
pi@raspberrypi:~/code/smartdns_build $ nslookup www.baidu.com
Server:         192.168.1.1
Address:        192.168.1.1#53

Non-authoritative answer:
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 14.215.177.39

pi@raspberrypi:~/code/smartdns_build $ ping 14.215.177.39 -c 2
PING 14.215.177.39 (14.215.177.39) 56(84) bytes of data.
64 bytes from 14.215.177.39: icmp_seq=1 ttl=56 time=6.31 ms
64 bytes from 14.215.177.39: icmp_seq=2 ttl=56 time=5.95 ms

--- 14.215.177.39 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms

```

From the comparison, smartdns found the fastest IP address to visit www.baidu.com, so accessing Baidu's DNS is 5 times faster than Ali DNS.

## Features

1. **Multiple Virtual DNS server**  
   Support multiple virtual DNS servers with different ports, rules, and clients.

1. **Multiple upstream DNS servers**  
   Support configuring multiple upstream DNS servers and query at the same time.the query will not be affected, Even if there is a DNS server exception.  

1. **Support per-client query control**  
   Support controlling clients using different query rules based on MAC and IP addresses, enabling features such as parental control.  

1. **Return the fastest IP address**  
   Support finding the fastest access IP address from the IP address list of the domain name and returning it to the client to avoid DNS pollution and improve network access speed.

1. **Support for multiple query protocols**  
   Support UDP, TCP, DOT(DNS over TLS), DOH(DNS over HTTPS), DOQ(DNS over Quic), DOH3(DNS over HTTP3) queries and service, and non-53 port queries, effectively avoiding DNS pollution and protect privacy, and support query DNS over socks5, http proxy.

1. **Domain IP address specification**  
   Support configuring IP address of specific domain to achieve the effect of advertising filtering, and avoid malicious websites.

1. **Domain name high performance rule filtering**  
   Support domain name suffix matching mode, simplify filtering configuration, filter 200,000 recording and take time <1ms.

1. **Linux/Windows multi-platform support**  
   Support standard Linux system (Raspberry Pi), openwrt system various firmware, ASUS router native firmware. Support Windows 10 WSL (Windows Subsystem for Linux).

1. **Support IPV4, IPV6 dual stack**  
   Support IPV4, IPV6 network, support query A, AAAA record, dual-stack IP selection, and filter IPV6 AAAA record.

1. **DNS64**  
   Support DNS64 translation.

1. **High performance, low resource consumption**  
   Multi-threaded asynchronous IO mode, cache cache query results.

1. **DNS domain forwarding**  
   Support DNS forwarding, ipset and nftables. Support setting the domain result to ipset and nftset set when speed check fails.

## Architecture

![Architecture](doc/architecture.png)

1. SmartDNS receives DNS query requests from local network devices, such as PCs and mobile phone query requests.
1. SmartDNS sends query requests to multiple upstream DNS servers, using standard UDP queries, non-standard port UDP queries, and TCP queries.
1. The upstream DNS server returns a list of Server IP addresses corresponding to the domain name. SmartDNS detects the fastest Server IP with local network access.
1. Return the fastest accessed Server IP to the local client.

## Compile

smartdns contains scripts for compiling packages, supports compiling luci, debian, openwrt, optware installation packages, and can execute `package/build-pkg.sh` compilation.

## [Donate](#donate)  

If you feel that this project is helpful to you, please donate to us so that the project can continue to develop and be more perfect.

### PayPal

[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://paypal.me/PengNick/)

### Alipay

![alipay](doc/alipay_donate.jpg)

### Wechat
  
![wechat](doc/wechat_donate.jpg)

## Open Source License

Smartdns is licensed to the public under the GPL V3 License.


================================================
FILE: etc/default/smartdns
================================================
# Default settings for smartdns server. This file is sourced by /bin/sh from
# /etc/init.d/smartdns.

# Options to pass to smartdns
SMART_DNS_OPTS=


================================================
FILE: etc/init.d/smartdns
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

### BEGIN INIT INFO
# Provides:        smartdns
# Required-Start:  $network 
# Required-Stop:   $network 
# Default-Start:   2 3 4 5
# Default-Stop:
# Short-Description: Start smartdns server
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin

. /etc/default/smartdns
SMARTDNS=/usr/sbin/smartdns
PIDFILE=/run/smartdns.pid
if [ ! -d "/run" ]; then
	PIDFILE=/var/run/smartdns.pid
fi

test -x $SMARTDNS || exit 5

case $1 in
	start)
		$SMARTDNS "$SMART_DNS_OPTS" -R
		while true; do
			if [ -e "$PIDFILE" ]; then
				break;
			fi
			sleep .5
		done
		PID="$(cat $PIDFILE 2>/dev/null)"
		if [ -z "$PID" ]; then
			echo "start smartdns server failed."
			exit 1
		fi
		if [ ! -e "/proc/$PID" ]; then
			echo "start smartdns server failed."
			exit 1
		fi
		echo "start smartdns server success."
		;;
	stop)
		if [ ! -f "$PIDFILE" ]; then
			echo "smartdns server is stopped."
			exit 0
		fi
		PID="$(cat $PIDFILE 2>/dev/null)"
		if [ ! -e "/proc/$PID" ] || [ -z "$PID" ]; then
			echo "smartdns server is stopped"
			exit 0
		fi

		kill -TERM "$PID"
		if [ $? -ne 0 ]; then
			echo "Stop smartdns server failed."
			exit 1;
		fi
		LOOP=1
		while true; do
			if [ ! -d "/proc/$PID" ]; then
				break;
			fi

			if [ $LOOP -gt 12 ]; then
				kill -9 "$PID"
				break;
			fi
			LOOP=$((LOOP+1))
			sleep .5
		done
		echo "Stop smartdns server success."
		;;
	restart)
		"$0" stop && "$0" start
		;;
	status)
		PID="$(cat "$PIDFILE" 2>/dev/null)"
		if [ ! -e "/proc/$PID" ] || [ -z "$PID" ]; then
			echo "smartdns server is not running."
			exit 1
		fi
		echo "smartdns server is running."
		status=0
		;;
	*)
		echo "Usage: $0 {start|stop|restart|status}"
		exit 2
		;;
esac

exit $status



================================================
FILE: etc/smartdns/smartdns.conf
================================================
# dns server name, default is host name
# server-name, 
# example:
#   server-name smartdns
#

# whether resolv local hostname to ip address
# resolv-hostname yes

# dns server run user
# user [username]
# example: run as nobody
#   user nobody
#

# Include another configuration options, if -group is specified, only include the rules to specified group.
# conf-file [file] [-group group-name]
# conf-file blacklist-ip.conf
# conf-file whitelist-ip.conf -group office
# conf-file *.conf

# dns server bind ip and port, default dns server port is 53, support binding multi ip and port
# bind udp server
#   bind [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection]
# bind tcp server
#   bind-tcp [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection]
# bind tls server
#   bind-tls [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection]
#   bind-cert-key-file [path to file]
#      tls private key file
#   bind-cert-file [path to file]
#      tls cert file
#   bind-cert-key-pass [password]
#      tls private key password
# bind-https server
#   bind-https [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection]
# option:
#   -group: set domain request to use the appropriate server group.
#   -no-rule-addr: skip address rule.
#   -no-rule-nameserver: skip nameserver rule.
#   -no-rule-ipset: skip ipset rule or nftset rule.
#   -no-speed-check: do not check speed.
#   -no-cache: skip cache.
#   -no-rule-soa: Skip address SOA(#) rules.
#   -no-dualstack-selection: Disable dualstack ip selection.
#   -no-ip-alias: ignore ip alias.
#   -force-aaaa-soa: force AAAA query return SOA.
#   -force-https-soa: force HTTPS query return SOA.
#   -no-serve-expired: no serve expired.
#   -no-rules: skip all rules.
#   -ipset ipsetname: use ipset rule.
#   -nftset nftsetname: use nftset rule.
#   -ddr: enable ddr.
# example: 
#  IPV4: 
#    bind :53
#    bind :53@eth0
#    bind :6053 -group office -no-speed-check
#  IPV6:
#    bind [::]:53
#    bind [::]:53@eth0
#    bind-tcp [::]:53
bind [::]:53

# tcp connection idle timeout
# tcp-idle-time [second]

# dns cache size
# cache-size [number]
#   0: for no cache
#   -1: auto set cache size
# cache-size 32768

# dns cache memory size
# cache-mem-size [size]

# enable persist cache when restart
# cache-persist no

# cache persist file
# cache-file /var/cache/smartdns.cache

# cache persist time
# cache-checkpoint-time [second]
# cache-checkpoint-time 86400

# prefetch domain
# prefetch-domain [yes|no]
# prefetch-domain yes

# cache serve expired 
# serve-expired [yes|no]
# serve-expired yes

# cache serve expired TTL
# serve-expired-ttl [num]
# serve-expired-ttl 86400

# reply TTL value to use when replying with expired data
# serve-expired-reply-ttl [num]
# serve-expired-reply-ttl 3

# List of hosts that supply bogus NX domain results 
# bogus-nxdomain [ip/subnet]

# List of IPs that will be filtered when nameserver is configured -blacklist-ip parameter
# blacklist-ip [ip/subnet]

# List of IPs that will be accepted when nameserver is configured -whitelist-ip parameter
# whitelist-ip [ip/subnet]

# List of IPs that will be ignored
# ignore-ip [ip/subnet]

# alias of IPs
# ip-alias [ip/subnet] [ip1[,ip2]...]
# ip-alias 192.168.0.1/24 10.9.0.1,10.9.0.2

# speed check mode
# speed-check-mode [ping|tcp:port|tcp-syn:port|none|,]
# example:
#   speed-check-mode ping,tcp:80,tcp:443
#   speed-check-mode tcp:443,ping
#   speed-check-mode tcp-syn:80,tcp-syn:443
#   speed-check-mode none

# force AAAA query return SOA
# force-AAAA-SOA [yes|no]

# force specific qtype return soa
# force-qtype-SOA [-,][qtypeid |...]
# force-qtype-SOA [qtypeid|start_id-end_id|,...]
# force-qtype-SOA 65 28 add type 65,28
# force-qtype-SOA 65,28 add type 65,28
# force-qtype-SOA 65-68 add type 65-68
# force-qtype-SOA -,65-68, clear type 65-68
# force-qtype-SOA - clear all type
# force-qtype-SOA 65

# Enable IPV4, IPV6 dual stack IP optimization selection strategy
# dualstack-ip-selection-threshold [num] (0~1000)
# dualstack-ip-allow-force-AAAA [yes|no]
# dualstack-ip-selection [yes|no]
# dualstack-ip-selection no

# edns client subnet
# edns-client-subnet [ip/subnet]
# edns-client-subnet 192.168.1.1/24
# edns-client-subnet 8::8/56

# ttl for all resource record
# rr-ttl: ttl for all record
# rr-ttl-min: minimum ttl for resource record
# rr-ttl-max: maximum ttl for resource record
# rr-ttl-reply-max: maximum reply ttl for resource record
# example:
# rr-ttl 300
# rr-ttl-min 60
# rr-ttl-max 86400
# rr-ttl-reply-max 60

# Maximum number of IPs returned to the client|8|number of IPs, 1~16
# example:
# max-reply-ip-num 1

# Maximum number of queries per second|0|number of queries, 0 means no limit.
# example:
# max-query-limit 65535

# response mode
# response-mode [first-ping|fastest-ip|fastest-response]

# set log level
# log-level: [level], level=off, fatal, error, warn, notice, info, debug
# log-file: file path of log file.
# log-console [yes|no]: output log to console.
# log-syslog [yes|no]: output log to syslog.
# log-size: size of each log file, support k,m,g
# log-num: number of logs, 0 means disable log
log-level info

# log-file /var/log/smartdns/smartdns.log
# log-size 128k
# log-num 2
# log-file-mode [mode]: file mode of log file.

# dns audit
# audit-enable [yes|no]: enable or disable audit.
# audit-enable yes
# audit-SOA [yes|no]: enable or disable log soa result.
# audit-size size of each audit file, support k,m,g
# audit-file /var/log/smartdns/smartdns-audit.log
# audit-console [yes|no]: output audit log to console.
# audit-syslog [yes|no]: output audit log to syslog.
# audit-file-mode [mode]: file mode of audit file.
# audit-size 128k
# audit-num 2

# Support reading dnsmasq dhcp file to resolve local hostname
# dnsmasq-lease-file /var/lib/misc/dnsmasq.leases

# certificate file
# ca-file [file]
# ca-file /etc/ssl/certs/ca-certificates.crt

# certificate path
# ca-path [path]
# ca-path /etc/ssl/certs

# remote udp dns server list
# server [IP]:[PORT]|URL [-blacklist-ip] [-whitelist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group]
# default port is 53
#   -blacklist-ip: filter result with blacklist ip
#   -whitelist-ip: filter result with whitelist ip,  result in whitelist-ip will be accepted.
#   -check-edns: result must exist edns RR, or discard result.
#   g|-group [group]: set server to group, use with nameserver /domain/group.
#   e|-exclude-default-group: exclude this server from default group.
#   p|-proxy [proxy-name]: use proxy to connect to server.
#   b|-bootstrap-dns: set as bootstrap dns server.
#   -set-mark: set mark on packets.
#   -subnet [ip/subnet]: set edns client subnet.
#   -host-ip [ip]: set dns server host ip.
#   -interface [interface]: set dns server interface.
#   -fallback: set as fallback dns server.
# server 8.8.8.8 -blacklist-ip -check-edns -group g1 -group g2
# server tls://dns.google:853 
# server quic://dns.gooel.com:443
# server https://dns.google/dns-query

# remote tcp dns server list
# server-tcp [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-group [group] ...] [-exclude-default-group]
# default port is 53
# server-tcp 8.8.8.8

# remote tls dns server list
# server-tls [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
#   -spki-pin: TLS spki pin to verify.
#   -tls-host-verify: cert hostname to verify.
#   -host-name: TLS sni hostname.
#   k|-no-check-certificate: no check certificate.
#   p|-proxy [proxy-name]: use proxy to connect to server.
#   -bootstrap-dns: set as bootstrap dns server.
# Get SPKI with this command:
#    echo | openssl s_client -connect '[ip]:853' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
# default port is 853
# server-tls 8.8.8.8
# server-tls 1.0.0.1

# remote quic dns server list
# server-quic [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
#   -spki-pin: TLS spki pin to verify.
#   -tls-host-verify: cert hostname to verify.
#   -host-name: TLS sni hostname.
#   k|-no-check-certificate: no check certificate.
#   p|-proxy [proxy-name]: use proxy to connect to server.
#   -bootstrap-dns: set as bootstrap dns server.
# Get SPKI with this command:
#    echo | openssl s_client -quic -alpn doq -connect '[ip]:853' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
# default port is 853
# server-quic 223.5.5.5

# remote http3 dns server list
# server-http3 [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
# server-h3 [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
#   -spki-pin: TLS spki pin to verify.
#   -tls-host-verify: cert hostname to verify.
#   -host-name: TLS sni hostname.
#   k|-no-check-certificate: no check certificate.
#   p|-proxy [proxy-name]: use proxy to connect to server.
#   -bootstrap-dns: set as bootstrap dns server.
# Get SPKI with this command:
#    echo | openssl s_client -quic -alpn doq -connect '[ip]:853' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
# default port is 443
# server-http3 https://223.5.5.5/dns-query
# server-h3 h3://223.5.5.5/dns-query

# remote https dns server list
# server-https https://[host]:[port]/path [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
#   -spki-pin: TLS spki pin to verify.
#   -tls-host-verify: cert hostname to verify.
#   -host-name: TLS sni hostname.
#   -http-host: http host.
#   k|-no-check-certificate: no check certificate.
#   p|-proxy [proxy-name]: use proxy to connect to server.
#   -bootstrap-dns: set as bootstrap dns server.
# default port is 443
# server-https https://cloudflare-dns.com/dns-query

# socks5 and http proxy list
# proxy-server URL -name [proxy name]
#   URL: socks5://[username:password@]host:port
#        http://[username:password@]host:port
#   -name: proxy name, use with server -proxy [proxy-name]
# example:
#   proxy-server socks5://user:pass@1.2.3.4:1080 -name proxy
#   proxy-server http://user:pass@1.2.3.4:3128 -name proxy

# specific nameserver to domain
# nameserver [/domain/][group|-]
# nameserer group, set the domain name to use the appropriate server group.
# nameserver /www.example.com/office, Set the domain name to use the appropriate server group.
# nameserver /www.example.com/-, ignore this domain

# expand ptr record from address record
# expand-ptr-from-address yes

# specific address to domain
# address [/domain/][ip1,ip2|-|-4|-6|#|#4|#6]
# address #, block all A and AAAA request.
# address #6, block all AAAA request.
# address -6, allow all AAAA request.
# address /www.example.com/1.2.3.4, return ip 1.2.3.4 to client
# address /www.example.com/1.2.3.4,5.6.7.8, return multiple ip addresses
# address /www.example.com/-, ignore address, query from upstream, suffix 4, for ipv4, 6 for ipv6, none for all
# address /www.example.com/#, return SOA to client, suffix 4, for ipv4, 6 for ipv6, none for all

# specific cname to domain
# cname /domain/target

# add srv record, support multiple srv record.
# srv-record /domain/[target][,port][,priority][,weight]
# srv-record /_ldap._tcp.example.com/ldapserver.example.com,389
# srv-record /_ldap._tcp.example.com/

# https-record /domain/[target=][,port=][,priority=][,alph=][,ech=][,ipv4hint=][,ipv6hint=][,noiphint]
# https-record noipv4hint,noipv6hint,noech
# https-record /www.example.com/ipv4hint=192.168.1.2

# enable DNS64 feature
# dns64 [ip/subnet]
# dns64 64:ff9b::/96

# enable ipset timeout by ttl feature
# ipset-timeout [yes]

# specific ipset to domain
# ipset [/domain/][ipsetname|#4:v4setname|#6:v6setname|-|#4:-|#6:-]
# ipset [ipsetname|#4:v4setname|#6:v6setname], set global ipset.
# ipset /www.example.com/block, set ipset with ipset name of block. 
# ipset /www.example.com/-, ignore this domain.
# ipset ipsetname, set global ipset.

# add to ipset when ping is unreachable
# ipset-no-speed ipsetname
# ipset-no-speed pass

# enable nftset timeout by ttl feature
# nftset-timeout [yes|no]
# nftset-timeout yes

# add to nftset when ping is unreachable
# nftset-no-speed [#4:ip#table#set,#6:ipv6#table#setv6]
# nftset-no-speed #4:ip#table#set

# enable nftset debug, check nftset setting result, output log when error.
# nftset-debug [yes|no]
# nftset-debug yes

# specific nftset to domain
# nftset [/domain/][#4:ip#table#set,#6:ipv6#table#setv6]
# nftset [#4:ip#table#set,#6:ipv6#table#setv6] set global nftset.
# nftset /www.example.com/ip#table#set, equivalent to 'nft add element ip table set { ... }'
# nftset /www.example.com/-, ignore this domain
# nftset /www.example.com/#6:-, ignore ipv6
# nftset #6:ip#table#set, set global nftset.

# set ddns domain
# ddns-domain domain

# set local domain
# local-domain domain

# lookup local network hostname or ip address from mdns
# mdns-lookup [yes|no]
# mdns-lookup no

# set hosts file
# hosts-file [file]

# set domain rules
# domain-rules /domain/ [-speed-check-mode [...]]
# rules:
#   [-c] -speed-check-mode [mode]: speed check mode
#                             speed-check-mode [ping|tcp:port|none|,]
#   [-a] -address [address|-]: same as address option
#   [-n] -nameserver [group|-]: same as nameserver option
#   [-p] -ipset [ipset|-]: same as ipset option
#   [-t] -nftset [nftset|-]: same as nftset option
#   [-d] -dualstack-ip-selection [yes|no]: same as dualstack-ip-selection option
#   [-g|-group group-name]: set domain-rules to group.
#   -no-serve-expired: ignore expired domain
#   -delete: delete domain rule
#   -no-ip-alias: ignore ip alias
#   -no-cache: ignore cache

# collection of domains 
# the domain-set can be used with /domain/ for address, nameserver, ipset, etc.
# domain-set -name [set-name] -type list -file [/path/to/file]
#   [-n] -name [set name]: domain set name
#   [-t] -type [list]: domain set type, list only now
#   [-f] -file [path/to/set]: file path of domain set
# 
# example:
# domain-set -name domain-list -type list -file /etc/smartdns/domain-list.conf
# address /domain-set:domain-list/1.2.3.4
# nameserver /domain-set:domain-list/server-group
# ipset /domain-set:domain-list/ipset
# domain-rules /domain-set:domain-list/ -speed-check-mode ping

# set ip rules
# ip-rules ip-cidrs [-ip-alias [...]]
# rules:
#   [-c] -ip-alias [ip1,ip2]: same as ip-alias option
#   [-a] -whitelist-ip: same as whitelist-ip option
#   [-n] -blacklist-ip: same as blacklist-ip option
#   [-p] -bogus-nxdomain: same as bogus-nxdomain option
#   [-t] -ignore-ip: same as ignore-ip option

# collection of IPs 
# the ip-set can be used with /ip-cidr/ for ip-alias, ignore-ip, etc.
# ip-set -name [set-name] -type list -file [/path/to/file]
#   [-n] -name [set name]: ip set name
#   [-t] -type [list]: ip set type, list only now
#   [-f] -file [path/to/set]: file path of ip set
# 
# example:
# ip-set -name ip-list -file /etc/smartdns/ip-list.conf
# bogus-nxdomain ip-set:ip-list
# ip-alias ip-set:ip-list 1.2.3.4
# ip-alias ip-set:ip-list ip-set:ip-map-list

# set client rules
# client-rules [ip-cidr|mac|ip-set] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection]
# client-rules option is same as bind option, please see bind option for detail.

# set group rules
# group-begin [group-name] [-inherit parent-group|none|default]
# group-match [-g|group group-name] [-domain domain] [-client-ip [ip-cidr|mac|ip-set]]
# group-end

# data directory
# data-dir [path]
# data-dir /var/lib/smartdns

# load plugin
# plugin [path/to/file] [args]

# web ui plugin
# plugin smartdns_ui.so
# smartdns-ui.www-root /usr/share/smartdns/wwwroot
# smartdns-ui.ip http://0.0.0.0:6080
# smartdns-ui.ip https://[::]:6080
# smartdns-ui.token-expire 600
# smartdns-ui.max-query-log-age 86400
# smartdns-ui.enable-terminal yes
# smartdns-ui.enable-cors yes
# smartdns-ui.user admin
# smartdns-ui.password password


================================================
FILE: package/build-pkg.sh
================================================
#!/bin/sh
# Copyright (C) 2018-2025 Nick Peng (pymumu@gmail.com)

CURR_DIR=$(cd $(dirname $0);pwd)
WORKDIR=$CURR_DIR/target
VER="`date +"1.%Y.%m.%d-%H%M"`"
CODE_DIR="$CURR_DIR/.."
IS_BUILD_SMARTDNS=1
OUTPUTDIR=$CURR_DIR
SMARTDNS_WEBUI_URL="https://github.com/pymumu/smartdns-webui/archive/refs/heads/main.zip"
SMARTDNS_WEBUI_SOURCE="$WORKDIR/smartdns-webui"
SMARTDNS_STATIC_DIR="$WORKDIR/smartdns-static"
SMARTDNS_WITH_LIBS=0
MAKE_NJOBS=1

export CC
export STRIP
export WORKDIR

WITH_UI=0

showhelp()
{
	echo "Usage: $0 [OPTION]"
	echo "Options:"
	echo " --platform [luci|luci-compat|debian|openwrt|optware|linux]    build for platform. "
	echo " --arch [all|armhf|arm64|x86-64|...]               build for architecture, e.g. "
	echo " --cross-tool [cross-tool]                         cross compiler, e.g. mips-openwrt-linux-"
	echo " --with-ui                                         build with smartdns-ui plugin."
	echo ""
	echo "Advance Options:"
	echo " --static                                          static link smartdns"
	echo " --only-package                                    only package, not build source"
	echo " --filearch [arch]                                 output file arch, default: equal --arch"
	echo " --outputdir [dir]                                 output package to specific directory"
	echo " "
	echo "Example:"
	echo " build luci:"
	echo "   $0 --platform luci"
	echo " build luci:"
	echo "   $0 --platform luci-compat"
	echo " build debian:"
	echo "   $0 --platform debian --arch x86-64"
	echo " build raspbian pi:"
	echo "   $0 --platform debian --arch arm64 --with-ui"
	echo " build optware mips:"
	echo "   $0 --platform optware --arch mipsbig"
	echo " build openwrt mips:"
	echo "   $0 --platform openwrt --arch mips"
	echo " build generic linux:"
	echo "   $0 --platform linux --arch x86-64 --with-ui"
}

init_env()
{
	if [ -z "$CC" ]; then
		CC=gcc
	fi

	MAKE_NJOBS=$(grep processor /proc/cpuinfo  | wc -l 2>/dev/null || echo 1)
	export MAKE_NJOBS

	mkdir -p $WORKDIR
	if [ $? -ne 0 ]; then
		echo "create work directory failed"
		return 1
	fi

	if [ "$STATIC" = "yes" ] && [ $WITH_UI -eq 1 ]; then
		SMARTDNS_WITH_LIBS=1
	fi

	check_cc="`echo "$CC" | grep -E "(\-gcc|\-cc)"`"
	if [ ! -z "$check_cc" ]; then
		TARGET_ARCH="`$CC -dumpmachine`"
		echo "target arch: $TARGET_ARCH"
	fi

	if [ $SMARTDNS_WITH_LIBS -eq 1 ]; then
		case "$TARGET_ARCH" in
			*arm*)
				NEED_UPDATE_ARM_CP15=1
				echo "Update arm cp15"
				;;
			*)
				;;
		esac

		LINKER_NAME=`$CC -Xlinker -v 2>&1 | grep -oP '(?<=-dynamic-linker )[^ ]+'`
		if [ -z "$LINKER_NAME" ]; then
			echo "get linker name failed"
			return 1
		fi
		LINKER_NAME=`basename $LINKER_NAME`
		LINKER_SYSROOT="`$CC --print-sysroot`"
		export BINDGEN_EXTRA_CLANG_ARGS="--sysroot=$LINKER_SYSROOT"
		echo "linker name: $LINKER_NAME"
	fi
}


copy_smartdns_libs()
{
	SMARTDNS_BIN="$CODE_DIR/src/smartdns"

	copy_libs_recursive $SMARTDNS_BIN
	if [ $? -ne 0 ]; then
		echo "copy libs failed"
		return 1
	fi

	LIB_WEBUI_SO="$CODE_DIR/plugin/smartdns-ui/target/smartdns_ui.so"
	copy_libs_recursive $LIB_WEBUI_SO
	if [ $? -ne 0 ]; then
		echo "copy libs failed"
		return 1
	fi
}

copy_libs_recursive()
{
	local lib=$1
	local lib_path=`$CC -print-file-name=$lib`
	if [ -z "$lib_path" ]; then
		return 0
	fi

	if [ -e $SMARTDNS_STATIC_DIR/lib/$lib ]; then
		return 0
	fi

	local tmp_path="`echo "$lib_path" | grep "libc.so"`"
	if [ ! -z "$tmp_path" ]; then
		LIBC_PATH="$tmp_path"
	fi

	if [ "$lib" != "$SMARTDNS_BIN" ]; then
		echo "copy $lib_path to $SMARTDNS_STATIC_DIR/lib"
		cp $lib_path $SMARTDNS_STATIC_DIR/lib
		if [ $? -ne 0 ]; then
			echo "copy $lib failed"
			return 1
		fi
	fi

	local shared_libs="`objdump -p $lib_path | grep NEEDED | awk '{print $2}'`"
	for sub_lib in $shared_libs; do
		copy_libs_recursive $sub_lib
		if [ $? -ne 0 ]; then
			return 1
		fi
	done

	return 0
}

copy_linker()
{
	LINK_PATH=`$CC -print-file-name=$LINKER_NAME`
	SYM_LINKER_NAME=`readlink -f $LINK_PATH`

	echo "linker: $LINK_PATH"
	echo "sym linker: $SYM_LINKER_NAME"
	echo "libc: $LIBC_PATH"

	if [ "$SYM_LINKER_NAME" = "$LIBC_PATH" ]; then
		ln -f -s $(basename $LIBC_PATH) $SMARTDNS_STATIC_DIR/lib/$(basename $LINKER_NAME)
	else
		cp $LINK_PATH $SMARTDNS_STATIC_DIR/lib -af
		if [ $? -ne 0 ]; then
			echo "copy $lib failed"
			return 1
		fi

		SYM_LINKER_NAME=`readlink $SMARTDNS_STATIC_DIR/lib/$LINKER_NAME`
		if [ ! -e $SMARTDNS_STATIC_DIR/lib/$SYM_LINKER_NAME ]; then
			SYM_LINKER_NAME=`basename $SYM_LINKER_NAME`
			ln -f -s $SYM_LINKER_NAME $SMARTDNS_STATIC_DIR/lib/$LINKER_NAME
		fi
	fi

	ln -f -s ${LINKER_NAME} ${SMARTDNS_STATIC_DIR}/lib/ld-linux.so
	if [ $? -ne 0 ]; then
		echo "copy $lib failed"
		return 1
	fi

	return 0
}

build_smartdns()
{
	MAKE_WITH_UI=""
	if [ $WITH_UI -eq 1 ]; then
		MAKE_WITH_UI="WITH_UI=1 OPTIMIZE_SIZE=1"
	fi

	if [ "$PLATFORM" = "luci" ]; then
		return 0
	fi

	make -C $CODE_DIR clean $MAKE_ARGS
	if [ $SMARTDNS_WITH_LIBS -eq 1 ]; then
		LINK_LDFLAGS='-Wl,-dynamic-linker,'lib/$(echo $LINKER_NAME)' -Wl,-rpath,\$$ORIGIN:\$$ORIGIN/lib'
		export LDFLAGS="$LDFLAGS $LINK_LDFLAGS"
		echo "LDFLAGS: $LDFLAGS"
		RUSTFLAGS='-C link-arg=-Wl,-rpath,$$ORIGIN'
		echo "Building smartdns with specific linker..."
		unset STATIC
	fi

	RUSTFLAGS="$RUSTFLAGS" make -C $CODE_DIR $MAKE_WITH_UI all -j$MAKE_NJOBS VER=$VER $MAKE_ARGS
	if [ $? -ne 0 ]; then
		echo "make smartdns failed"
		exit 1
	fi

	$STRIP -d $CODE_DIR/src/smartdns >/dev/null 2>&1

	rm -fr $SMARTDNS_STATIC_DIR
	if [ $SMARTDNS_WITH_LIBS -eq 0 ]; then
		return 0;
	fi

	echo "copy smartdns binary to $SMARTDNS_STATIC_DIR"
	mkdir -p $SMARTDNS_STATIC_DIR/lib
	if [ $? -ne 0 ]; then
		echo "create target directory failed"
		return 1
	fi

	cp $CODE_DIR/src/smartdns $SMARTDNS_STATIC_DIR/
	if [ $? -ne 0 ]; then
		echo "copy smartdns binary failed"
		return 1
	fi

	cp $CURR_DIR/run-smartdns $SMARTDNS_STATIC_DIR
	chmod +x $SMARTDNS_STATIC_DIR/run-smartdns
	if [ "$NEED_UPDATE_ARM_CP15" = "1" ]; then
		sed -i 's/NEED_CHECK_ARM_CP15=0/NEED_CHECK_ARM_CP15=1/' $SMARTDNS_STATIC_DIR/run-smartdns
		if [ $? -ne 0 ]; then
			echo "sed run-smartdns failed"
			return 1
		fi
	fi

	copy_smartdns_libs
	if [ $? -ne 0 ]; then
		echo "copy smartdns libs failed"
		return 1
	fi
	rm $SMARTDNS_STATIC_DIR/lib/smartdns_ui.so >/dev/null 2>&1

	copy_linker
	if [ $? -ne 0 ]; then
		echo "copy linker failed"
		return 1
	fi

	return 0
}

build_webpages()
{
	if [ ! -f "$WORKDIR/smartdns-webui.zip" ]; then
		echo "smartdns-webui source not found, downloading..."
		wget -O $WORKDIR/smartdns-webui.zip $SMARTDNS_WEBUI_URL
		if [ $? -ne 0 ]; then
			echo "Failed to download smartdns-webui source at $SMARTDNS_WEBUI_URL"
			return 1
		fi
	fi

	if [ ! -d "$SMARTDNS_WEBUI_SOURCE" ]; then
		echo "smartdns-webui source not found, unzipping..."
		unzip -q $WORKDIR/smartdns-webui.zip -d $WORKDIR
		if [ $? -ne 0 ]; then
			echo "Failed to unzip smartdns-webui source."
			return 1
		fi
		mv $WORKDIR/smartdns-webui-main $SMARTDNS_WEBUI_SOURCE
		if [ $? -ne 0 ]; then
			echo "Failed to rename smartdns-webui directory."
			return 1
		fi
	fi

	if [ ! -d "$SMARTDNS_WEBUI_SOURCE" ]; then
		echo "smartdns-webui source not found."
		return 1
	fi

	if [ ! -f "$SMARTDNS_WEBUI_SOURCE/package.json" ]; then
		echo "smartdns-webui source is not valid."
		return 1
	fi

	if [ -f "$SMARTDNS_WEBUI_SOURCE/out/index.html" ]; then
		echo "smartdns-webui already built, skipping build."
		return 0
	fi

	echo "Building smartdns-webui..."
	npm install --prefix $SMARTDNS_WEBUI_SOURCE
	if [ $? -ne 0 ]; then
		echo "Failed to install smartdns-webui dependencies."
		return 1
	fi

	npm run build --prefix $SMARTDNS_WEBUI_SOURCE
	if [ $? -ne 0 ]; then
		echo "Failed to build smartdns-webui."
		return 1
	fi

	echo "smartdns-webui build completed."

	return 0
}

build()
{
	echo "build package for $PLATFORM"

	if [ $IS_BUILD_SMARTDNS -eq 1 ]; then
		build_smartdns
		if [ $? -ne 0 ]; then
			return 1
		fi
	fi

	WITH_UI_ARGS=""
	if [ $WITH_UI -eq 1 ] && [ "$PLATFORM" != "luci" ]; then
		build_webpages
		if [ $? -ne 0 ]; then
			echo "build smartdns-ui failed"
			return 1
		fi
		WITH_UI_ARGS="--with-ui"
	fi

	chmod +x $CODE_DIR/package/$PLATFORM/make.sh
	$CODE_DIR/package/$PLATFORM/make.sh -o $CURR_DIR --arch $ARCH --ver $VER --filearch $FILEARCH $WITH_UI_ARGS -o $OUTPUTDIR 
	if [ $? -ne 0 ]; then
		echo "build package for $PLATFORM failed"
		return 1
	fi

	echo "build package for $PLATFORM success."
	return 0
}

main()
{
	OPTS=`getopt -o o:h --long arch:,filearch:,ver:,platform:,cross-tool:,with-nftables,static,only-package,with-ui,outputdir: \
		-n  "" -- "$@"`

	if [ "$#" -le "1" ]; then
		showhelp
		exit 1
	fi

	if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

	# Note the quotes around `$TEMP': they are essential!
	eval set -- "$OPTS"

	while true; do
		case "$1" in
		--arch)
			ARCH="$2"
			shift 2;;
		--filearch)
			FILEARCH="$2"
			shift 2;;
		--platform)
			PLATFORM="$2"
			shift 2;;
		--cross-tool)
			CROSS_TOOL="$2"
			shift 2;;
		--static)
			export STATIC="yes"
			shift 1;;
		--only-package)
			IS_BUILD_SMARTDNS=0
			shift 1;;
		--outputdir)
			OUTPUTDIR="$2"
			shift 2;;
		--with-ui)
			WITH_UI=1
			shift 1;;
		--ver)
			VER="$2"
			shift 2;;
		-h | --help )
			showhelp
			return 0
			shift ;;
		-- ) shift; break ;;
		* ) break ;;
		esac
	done

	if [ -z "$PLATFORM" ]; then
		echo "please input platform"
		echo "run $0 -h for help."
		return 1
	fi
	
	if [ "$PLATFORM" = "luci" ]; then
		ARCH="all"
	fi

	if [ -z "$ARCH" ]; then
		echo "please input arch."
		echo "run $0 -h for help."
		return 1
	fi

	if [ -z "$FILEARCH" ]; then 
		FILEARCH="$ARCH"
	fi

	if [ -z "$OUTPUTDIR" ]; then
		OUTPUTDIR=$CURR_DIR
	fi

	if [ ! -z "$CROSS_TOOL" ]; then
		CC="${CROSS_TOOL}gcc"
		STRIP="${CROSS_TOOL}strip"
	fi

	if [ -z "$CC" ]; then
		CC="gcc"
	fi

	if [ -z "$STRIP" ]; then
		if [ ! -z "`echo $CC | grep '\-gcc'`" ]; then
			STRIP="`echo "$CC" | sed 's/-gcc\$/-strip/g'`"
		else
			STRIP="strip"
		fi
	fi

	if [ ! -e "`which $CC`" ]; then
		echo "Cannot find compiler $CC"
		return 1
	fi

	init_env

	build
}

main $@
exit $?


================================================
FILE: package/copy-smartdns.sh
================================================
#!/bin/sh

CURR_DIR=$(cd $(dirname $0);pwd)
WORKDIR=$CURR_DIR/target
CODE_DIR="$CURR_DIR/.."
SMARTDNS_STATIC_DIR="$WORKDIR/smartdns-static"

main() {
	TARGET_DIR=$1
	PREFIX=$2
	if [ -z "$TARGET_DIR" ]; then
		echo "Usage: $0 <target_directory> [prefix_directory]"
		exit 1
	fi

	if [ ! -d "$TARGET_DIR" ]; then
		echo "Target directory $TARGET_DIR does not exist."
		exit 1
	fi


	if [ ! -f "$SMARTDNS_STATIC_DIR/smartdns" ]; then
		cp "$CODE_DIR/src/smartdns" "$TARGET_DIR$PREFIX/usr/sbin/smartdns"
		if [ $? -ne 0 ]; then
			echo "Failed to copy smartdns binary to $TARGET_DIR$PREFIX/usr/sbin."
			return 1
		fi

		chmod +x "$TARGET_DIR$PREFIX/usr/sbin/smartdns"

		return 0
	fi

	if [ ! -f "$SMARTDNS_STATIC_DIR/smartdns" ]; then
		echo "SmartDNS binary not found in $SMARTDNS_STATIC_DIR."
		return 1
	fi

	mkdir -p "$TARGET_DIR$PREFIX/usr/local/lib/smartdns"
	if [ $? -ne 0 ]; then
		echo "Failed to create directory $TARGET_DIR$PREFIX/usr/local/lib/smartdns."
		return 1
	fi

	cp $SMARTDNS_STATIC_DIR/* $TARGET_DIR$PREFIX/usr/local/lib/smartdns/ -a
	if [ $? -ne 0 ]; then
		echo "Failed to copy smartdns static files to $TARGET_DIR$PREFIX/usr/local/lib/smartdns."
		return 1
	fi

	ln -f -s "$PREFIX/usr/local/lib/smartdns/run-smartdns" "$TARGET_DIR$PREFIX/usr/sbin/smartdns"
	if [ $? -ne 0 ]; then
		echo "Failed to create symlink for smartdns in $TARGET_DIR$PREFIX/usr/sbin."
		return 1
	fi
	chmod +x "$TARGET_DIR$PREFIX/usr/local/lib/smartdns/run-smartdns"

	echo "SmartDNS files copied successfully to $TARGET_DIR$PREFIX."
	return 0
}

main $@


================================================
FILE: package/debian/DEBIAN/changelog
================================================
smartdns (1:1.2022.04.05) stable; urgency=low

  * Initial build

 -- initial release. <pymumu@gmail.com>  Mon, 9 jul 2018 21:20:28 +0800


================================================
FILE: package/debian/DEBIAN/compat
================================================
9


================================================
FILE: package/debian/DEBIAN/conffiles
================================================
/etc/smartdns/smartdns.conf


================================================
FILE: package/debian/DEBIAN/control
================================================
Source: smartdns  
Maintainer: Nick Peng <pymumu@gmail.com>
Build-Depends: debhelper (>= 8.0.0)
Version: 
Section: net
Package: smartdns  
Priority: extra  
Architecture: armhf
Description: a smartdns server


================================================
FILE: package/debian/DEBIAN/copyright
================================================
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: smartdns
Source: http://github.com/pymumu/smartdns

Files: *
Copyright: 2018-2025 Nick peng
License: proprietary


================================================
FILE: package/debian/DEBIAN/prerm
================================================
#!/bin/sh

systemctl stop smartdns
systemctl disable smartdns


================================================
FILE: package/debian/DEBIAN/rules
================================================
#!/usr/bin/make -f  
%:  
	dh $@ --with systemd --builddirectory=./target/

clean:
	make -C ../src clean

build:
	make -C ../src

override_dh_systemd_enable:
	dh_systemd_enable --name=smartdns 

override_dh_installinit:
	dh_installinit --name=smartdns 

override_dh_installdeb:
	dh_installdeb
	cp ../systemd/smartdns.service ${CURDIR}/debian/




================================================
FILE: package/debian/make.sh
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
CURR_DIR=$(cd $(dirname $0);pwd)
VER="`date +"1.%Y.%m.%d-%H%M"`"
SMARTDNS_DIR=$CURR_DIR/../../
SMARTDNS_CP=$SMARTDNS_DIR/package/copy-smartdns.sh
SMARTDNS_BIN=$SMARTDNS_DIR/src/smartdns
IS_BUILD_SMARTDNS_UI=0

showhelp()
{
	echo "Usage: make [OPTION]"
	echo "Options:"
	echo " -o               output directory."
	echo " --arch           archtecture."
	echo " --ver            version."
	echo " --with-ui        build with smartdns-ui plugin."
	echo " -h               show this message."
}

build()
{
	ROOT=/tmp/smartdns-deiban
	rm -fr $ROOT
	mkdir -p $ROOT
	cd $ROOT/

	cp $CURR_DIR/DEBIAN $ROOT/ -af
	CONTROL=$ROOT/DEBIAN/control
	mkdir $ROOT/usr/sbin -p
	mkdir $ROOT/etc/smartdns/ -p
	mkdir $ROOT/etc/default/ -p
	mkdir $ROOT/lib/systemd/system/ -p


	pkgver=$(echo ${VER}| sed 's/^1\.//g')
	sed -i "s/Version:.*/Version: ${pkgver}/" $ROOT/DEBIAN/control
	sed -i "s/Architecture:.*/Architecture: $ARCH/" $ROOT/DEBIAN/control
	chmod 0755 $ROOT/DEBIAN/prerm

	cp $SMARTDNS_DIR/etc/smartdns/smartdns.conf  $ROOT/etc/smartdns/
	cp $SMARTDNS_DIR/etc/default/smartdns  $ROOT/etc/default/
	cp $SMARTDNS_DIR/systemd/smartdns.service $ROOT/lib/systemd/system/ 

	if [ $IS_BUILD_SMARTDNS_UI -eq 1 ]; then
		mkdir $ROOT/usr/local/lib/smartdns -p
		mkdir $ROOT/usr/share/smartdns/wwwroot -p
		cp $SMARTDNS_DIR/plugin/smartdns-ui/target/smartdns_ui.so $ROOT/usr/local/lib/smartdns/smartdns_ui.so -a
		if [ $? -ne 0 ]; then
			echo "Failed to copy smartdns-ui plugin."
			return 1
		fi

		cp $WORKDIR/smartdns-webui/out/* $ROOT/usr/share/smartdns/wwwroot/ -a
		if [ $? -ne 0 ]; then
			echo "Failed to copy smartdns-ui plugin."
			return 1
		fi
	else
		echo "smartdns-ui plugin not found, skipping copy."
	fi

	$SMARTDNS_CP $ROOT
	if [ $? -ne 0 ]; then
		echo "copy smartdns file failed."
		return 1
	fi
	chmod +x $ROOT/usr/sbin/smartdns 2>/dev/null

	dpkg -b $ROOT $OUTPUTDIR/smartdns.$VER.$FILEARCH.deb

	rm -fr $ROOT/
}

main()
{
	OPTS=`getopt -o o:h --long arch:,ver:,with-ui,filearch: \
		-n  "" -- "$@"`

	if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

	# Note the quotes around `$TEMP': they are essential!
	eval set -- "$OPTS"

	while true; do
		case "$1" in
		--arch)
			ARCH="$2"
			shift 2;;
		--filearch)
			FILEARCH="$2"
			shift 2;;
		--with-ui)
			IS_BUILD_SMARTDNS_UI=1
			shift ;;
		--ver)
			VER="$2"
			shift 2;;
		-o )
			OUTPUTDIR="$2"
			shift 2;;
		-h | --help )
			showhelp
			return 0
			shift ;;
		-- ) shift; break ;;
		* ) break ;;
		esac
	done

	if [ -z "$ARCH" ]; then
		echo "please input arch."
		return 1;
	fi

	if [ -z "$FILEARCH" ]; then
		FILEARCH=$ARCH
	fi

	if [ -z "$OUTPUTDIR" ]; then
		OUTPUTDIR=$CURR_DIR;
	fi

	build
}

main $@
exit $?


================================================
FILE: package/linux/install
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

INST_DIR=$(cd $(dirname $0);pwd)
ISWSL=1 # 1 means not WSL, 0 means wsl 

showhelp()
{
	echo "Usage: install [OPTION]"
	echo "Options:"
	echo " -i               install smartdns."
	echo " -u               uninstall smartdns."
	echo " -U               upgrade install smartdns."
	echo " --prefix [dir]   prefix directory."
	echo " -h               show this message."
}

start_service()
{
	if [ $ISSYSTEMD -ne 0 ]; then
		chkconfig smartdns on >/dev/null 2>&1
		service smartdns start
		return $?
	fi

	systemctl daemon-reload
	systemctl enable smartdns
	systemctl start smartdns
}

stop_service()
{
	if [ $ISSYSTEMD -ne 0 ]; then
		service smartdns stop
		chkconfig smartdns off >/dev/null 2>&1
		return 0
	fi

	systemctl stop smartdns
	systemctl disable smartdns

	return 0
}

clean_service()
{
	if [ $ISSYSTEMD -ne 0 ]; then
		return 0
	fi
	systemctl daemon-reload
}

get_systemd_path()
{
	service="`systemctl --no-legend| grep '\.service' | head -n 1 | awk '{print $1}' 2>/dev/null`"
	SERVICE_PATH="`systemctl show $service | grep FragmentPath | awk -F'=' '{print $2}' 2>/dev/null`"
	if [ ! -z "$SERVICE_PATH" ]; then
		SERVICE_PATH="`dirname $SERVICE_PATH 2>/dev/null`"
		if [ -d "$SERVICE_PATH" ]; then
			echo "$SERVICE_PATH"
			return 0
		fi 
	fi

	SERVICE_PATH="`pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null`"
	if [ ! -z "$SERVICE_PATH" ]; then
		if [ -d "$SERVICE_PATH" ]; then
			echo "$SERVICE_PATH"
			return 0
		fi 
	fi

	SERVICE_PATH="/lib/systemd/system"
	if [ -d "$SERVICE_PATH" ]; then
		echo "$SERVICE_PATH"
		return 0
	fi

	return 1
}

install_files()
{
	install -v -d $SMARTDNS_CONF_DIR
	if [ $? -ne 0 ]; then
		return 1
	fi

	install -v -d $SMARTDNS_UI_WWWROOT
	if [ $? -ne 0 ]; then
		return 1
	fi

	install -v -d $SMARTDNS_PLUIGN_DIR
	if [ $? -ne 0 ]; then
		return 1
	fi

	install -v -t $SMARTDNS_PLUIGN_DIR $INST_DIR/usr/local/lib/smartdns/smartdns_ui.so
	if [ $? -ne 0 ]; then
		echo "smartdns-ui plugin not found, skipping copy."
	fi

	if [ -d "$INST_DIR/usr/local/lib/smartdns" ]; then
		cp $INST_DIR/usr/local/lib/smartdns/* $SMARTDNS_PLUIGN_DIR/ -a
		if [ $? -ne 0 ]; then
			echo "Failed to copy smartdns library files."
			return 1
		fi
	fi

	if [ -d "$INST_DIR/usr/share/smartdns/wwwroot/" ]; then
		cp $INST_DIR/usr/share/smartdns/wwwroot/* $SMARTDNS_UI_WWWROOT/ -a
		if [ $? -ne 0 ]; then
			echo "Failed to copy smartdns-webui files."
			return 1
		fi
	fi

	cp $INST_DIR/usr/sbin/smartdns $PREFIX/usr/sbin -a
	if [ $? -ne 0 ]; then
		return 1
	fi
	chmod +x $PREFIX/usr/sbin/smartdns

	if [ -e "$PREFIX$SMARTDNS_CONF_DIR/smartdns.conf" ]; then
		cp $INST_DIR/etc/smartdns/smartdns.conf $PREFIX$SMARTDNS_CONF_DIR/smartdns.conf.pkg
	else 
		install -v -m 0640 -t  $PREFIX$SMARTDNS_CONF_DIR $INST_DIR/etc/smartdns/smartdns.conf
		if [ $? -ne 0 ]; then
			return 1
		fi
	fi

	install -v -m 0640 -t  $PREFIX/etc/default $INST_DIR/etc/default/smartdns
	if [ $? -ne 0 ]; then
		return 1
	fi
	
	install -v -m 0755 -t $SMARTDNS_INIT_DIR $INST_DIR/etc/init.d/smartdns 
	if [ $? -ne 0 ]; then
		if [ $ISSYSTEMD -ne 0 ]; then
			return 1
		fi
	fi

	if [ $ISSYSTEMD -eq 0 ]; then
		SYSTEM_UNIT_PATH="`get_systemd_path`"
		if [ -z "$SYSTEM_UNIT_PATH" ]; then
			echo "cannot find systemd path"
			return 1
		fi
		install -v -m 0644 -t $PREFIX$SYSTEM_UNIT_PATH $INST_DIR/systemd/smartdns.service 
		if [ $? -ne 0 ]; then
			return 1
		fi
	fi

	return 0
}

uninstall_smartdns()
{
	if [ -z "$PREFIX" ]; then
		stop_service 2>/dev/null
	fi	
	rmdir $PREFIX$SMARTDNS_CONF_DIR 2>/dev/null
	rm -f $PREFIX/usr/sbin/smartdns
	rm -f $PREFIX/etc/default/smartdns
	rm -f $PREFIX/etc/init.d/smartdns
	rm -fr $PREFIX/usr/share/smartdns/wwwroot
	rmdir $PREFIX/usr/share/smartdns 2>/dev/null
	rm -fr $PREFIX/usr/local/lib/smartdns 2>/dev/null

	if [ $ISWSL -eq 0 ]; then
		sed -i '\#%sudo ALL=NOPASSWD: /etc/init.d/smartdns#d' /etc/sudoers 2>/dev/null
	fi

	if [ $ISSYSTEMD -eq 0 ]; then
		SYSTEM_UNIT_PATH="`get_systemd_path`"
		if [ ! -z "$SYSTEM_UNIT_PATH" ]; then
			rm -f $PREFIX$SYSTEM_UNIT_PATH/smartdns.service
		fi
	fi

	if [ -z "$PREFIX" ]; then
		clean_service
	fi	
}


install_smartdns()
{
	local ret

	which smartdns >/dev/null 2>&1
	if [ $? -eq 0 ]; then
		echo "Already installed."
		return 1
	fi

	install_files
	ret=$?
	if [ $ret -ne 0 ]; then
		uninstall_smartdns
		return $ret
	fi

	if [ -z "$PREFIX" ]; then
		start_service
	fi

	if [ $ISWSL -eq 0 ]; then
		grep "%sudo ALL=NOPASSWD: /etc/init.d/smartdns" /etc/sudoers >/dev/null 2>&1
		if [ $? -ne 0 ]; then
			echo "%sudo ALL=NOPASSWD: /etc/init.d/smartdns" >> /etc/sudoers
		fi
	fi

	return 0
}

init_dir()
{
	local ID=`id -u`
	if [ $ID -ne 0 ]; then
		echo "Please run as root."
		return 1
	fi

	SMARTDNS_CONF_DIR=$PREFIX/etc/smartdns
	SMARTDNS_INIT_DIR=$PREFIX/etc/init.d
	SMARTDNS_UI_WWWROOT=$PREFIX/usr/share/smartdns/wwwroot
	SMARTDNS_PLUIGN_DIR=$PREFIX/usr/local/lib/smartdns

	which systemctl >/dev/null 2>&1
	ISSYSTEMD="$?"
	# Running under WSL (Windows Subsystem for Linux)?
	cat /proc/version | grep -E '[Mm]icrosoft' >/dev/null 2>&1; 
	if [ $? -eq 0 ]; then
		ISSYSTEMD=1
		ISWSL=0
	fi

	cd $INST_DIR
}

main()
{
	ACTION=""

	OPTS=`getopt -o iuhU --long help,prefix: \
		-n  "" -- "$@"`

	if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

	# Note the quotes around `$TEMP': they are essential!
	eval set -- "$OPTS"

	while true; do
		case "$1" in
		--prefix)
			PREFIX="$2"
			shift 2;;
		-h | --help )
			showhelp
			return 0
			shift ;;
		-i )
			ACTION="INSTALL"
			shift ;;
		-u )
			ACTION="UNINSTALL"
			shift ;;
		-U )
			ACTION="UPGRADE"
			shift ;;
		-- ) shift; break ;;
		* ) break ;;
  		esac
	done

	init_dir

	if [ -z "$ACTION" ]; then
		showhelp
		return 0
	elif [ "$ACTION" = "INSTALL" ]; then
		install_smartdns
		return $?
	elif [ "$ACTION" = "UNINSTALL" ]; then
		uninstall_smartdns
		return 0
	elif [ "$ACTION" = "UPGRADE" ]; then
		uninstall_smartdns
		install_smartdns
		return $?
	else
		showhelp
		return 1
	fi

}

main $@
exit $?




================================================
FILE: package/linux/make.sh
================================================
#!/bin/sh

CURR_DIR=$(cd $(dirname $0);pwd)
VER="`date +"1.%Y.%m.%d-%H%M"`"
SMARTDNS_DIR=$CURR_DIR/../../
SMARTDNS_CP=$SMARTDNS_DIR/package/copy-smartdns.sh
SMARTDNS_BIN=$SMARTDNS_DIR/src/smartdns
IS_BUILD_SMARTDNS_UI=0

showhelp()
{
	echo "Usage: make [OPTION]"
	echo "Options:"
	echo " -o               output directory."
	echo " --arch           archtecture."
	echo " --ver            version."
	echo " --with-ui        build with smartdns-ui plugin."
	echo " -h               show this message."
}

build()
{
	PKG_ROOT=/tmp/smartdns-linux
	rm -fr $PKG_ROOT
	mkdir -p $PKG_ROOT/smartdns
	cd $PKG_ROOT/

	# Generic x86_64
	mkdir $PKG_ROOT/smartdns/usr/sbin -p
	mkdir $PKG_ROOT/smartdns/package -p
	mkdir $PKG_ROOT/smartdns/systemd -p
	
	cd $SMARTDNS_DIR
	cp package/windows $PKG_ROOT/smartdns/package/ -a
	cp etc *.md LICENSE package/linux/install $PKG_ROOT/smartdns/ -a
	cp systemd/smartdns.service $PKG_ROOT/smartdns/systemd

	$SMARTDNS_CP $PKG_ROOT/smartdns
	if [ $? -ne 0 ]; then
		echo "copy smartdns file failed."
		rm -fr $PKG_ROOT
		return 1
	fi

	if [ $IS_BUILD_SMARTDNS_UI -eq 1 ]; then
		mkdir $PKG_ROOT/smartdns/usr/local/lib/smartdns -p
		mkdir $PKG_ROOT/smartdns/usr/share/smartdns/wwwroot -p
		cp plugin/smartdns-ui/target/smartdns_ui.so $PKG_ROOT/smartdns/usr/local/lib/smartdns/smartdns_ui.so -a
		cp $WORKDIR/smartdns-webui/out/* $PKG_ROOT/smartdns/usr/share/smartdns/wwwroot/ -a
		if [ $? -ne 0 ]; then
			echo "Failed to copy smartdns-ui plugin."
			return 1
		fi
	else
		echo "smartdns-ui plugin not found, skipping copy."
	fi

	chmod +x $PKG_ROOT/smartdns/install

	if [ $? -ne 0 ]; then
		echo "copy smartdns file failed"
		rm -fr $PKG_ROOT
		exit 1
	fi
	cd $PKG_ROOT
	tar  zcf $OUTPUTDIR/smartdns.$VER.$FILEARCH.tar.gz smartdns
	if [ $? -ne 0 ]; then
		echo "create package failed"
		rm -fr $PKG_ROOT
		exit 1
	fi
	cd $CURR_DIR
	rm -fr $PKG_ROOT
}

main()
{
	OPTS=`getopt -o o:h --long arch:,ver:,with-ui,filearch: \
		-n  "" -- "$@"`

	if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

	# Note the quotes around `$TEMP': they are essential!
	eval set -- "$OPTS"

	while true; do
		case "$1" in
		--arch)
			ARCH="$2"
			shift 2;;
		--filearch)
			FILEARCH="$2"
			shift 2;;
		--with-ui)
			IS_BUILD_SMARTDNS_UI=1
			shift ;;
		--ver)
			VER="$2"
			shift 2;;
		-o )
			OUTPUTDIR="$2"
			shift 2;;
		-h | --help )
			showhelp
			return 0
			shift ;;
		-- ) shift; break ;;
		* ) break ;;
  		esac
	done

	if [ -z "$ARCH" ]; then
		echo "please input arch."
		return 1;
	fi

	if [ -z "$FILEARCH" ]; then
		FILEARCH=$ARCH
	fi

	if [ -z "$OUTPUTDIR" ]; then
		OUTPUTDIR=$CURR_DIR;
	fi

	build
}

main $@
exit $?


================================================
FILE: package/luci/control/control
================================================
Package: luci-app-smartdns
Version: git-18.201.27126-7bf0367-1
Depends: libc, smartdns
Source: feeds/luci/applications/luci-app-smartdns
Section: luci
Architecture: all
Description:  A smartdns server


================================================
FILE: package/luci/control/postinst
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0
[ -e ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_postinst $0 $@


================================================
FILE: package/luci/control/prerm
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

[ -e ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_prerm $0 $@


================================================
FILE: package/luci/debian-binary
================================================
2.0


================================================
FILE: package/luci/files/luci/i18n/smartdns.zh-cn.po
================================================

msgid "Additional Args for upstream dns servers"
msgstr "额外的上游 DNS 服务器参数"

msgid ""
"Additional Flags for rules, read help on domain-rule for more information."
msgstr "额外的规则标识,具体参考domain-rule的帮助说明。"

msgid ""
"Additional Flags for rules, read help on ip-rule for more information."
msgstr "额外的规则标识,具体参考ip-rule的帮助说明。"

msgid "Additional Rule Flag"
msgstr "额外规则标识"

msgid "Additional Server Args"
msgstr "额外的服务器参数"

msgid "Additional server args, refer to the help description of the bind option."
msgstr "额外的服务器参数,参考bind选项的帮助说明。"

msgid "Advanced Settings"
msgstr "高级设置"

msgid "Audit Log Output Mode"
msgstr "审计日志输出模式"

msgid "Audit Log Size"
msgstr "审计日志大小"

msgid "Audit Log Number"
msgstr "审计日志数量"

msgid "Audit Log File"
msgstr "审计日志文件路径"

msgid ""
"Attempts to serve old responses from cache with a TTL of 0 in the response "
"without waiting for the actual resolution to finish."
msgstr "查询性能优化,有请求时尝试回应TTL为0的过期记录,以避免查询等待。"

msgid "Automatically Set Dnsmasq"
msgstr "自动设置Dnsmasq"

msgid "Automatically set as upstream of dnsmasq when port changes."
msgstr "端口更改时自动设为 dnsmasq 的上游。"

msgid "Basic Settings"
msgstr "基本设置"

msgid "Blacklist IP"
msgstr "黑名单"

msgid "Blacklist IP Rule, Decline IP addresses within the range."
msgstr "黑名单规则,拒绝指定范围的IP地址。"

msgid "Bind Device"
msgstr "绑定到设备"

msgid "Bind Device Name"
msgstr "绑定的设备名称"

msgid "Bogus nxdomain"
msgstr "假冒IP"

msgid "Block domain"
msgstr "屏蔽域名"

msgid "Block domain."
msgstr "屏蔽域名。"

msgid "Cache Persist"
msgstr "持久化缓存"

msgid "Cache Size"
msgstr "缓存大小"

msgid "Client Rules"
msgstr "客户端规则"

msgid "Client Address"
msgstr "客户端地址"

msgid "Client Address File"
msgstr "客户端地址文件"

msgid "Client Rules Settings, can achieve parental control functionality."
msgstr "客户端规则设置,可以实现家长控制功能。"

msgid "Collecting data ..."
msgstr "正在收集数据..."

msgid ""
"Configure IP blacklists that will be filtered from the results of specific "
"DNS server."
msgstr "配置需要从指定域名服务器结果过滤的IP黑名单。"

msgid "Configure block domain list."
msgstr "配置屏蔽域名列表"

msgid "Configure domain rule list."
msgstr "配置域名规则列表"

msgid "Configure forwarding domain name list."
msgstr "配置分流域名列表"

msgid "Configure ip rule list."
msgstr "配置IP规则列表"

msgid "Custom Settings"
msgstr "自定义设置"

msgid "Do not use these IP addresses."
msgstr "忽略这些IP地址"

msgid "DOH Server"
msgstr "DOH服务器"

msgid "DOH Server Port"
msgstr "DOH服务器端口"

msgid "DOT Server"
msgstr "DOT服务器"

msgid "DOT Server Port"
msgstr "DOT服务器端口"

msgid "DNS Block Setting"
msgstr "域名屏蔽设置"

msgid "DNS Forwarding Setting"
msgstr "域名分流设置"

msgid "DNS Server Name"
msgstr "DNS服务器名称"

msgid "DNS Server group"
msgstr "服务器组"

msgid "DNS Server group belongs to, such as office, home."
msgstr "设置服务器组,例如office,home"

msgid "DNS Server ip"
msgstr "DNS服务器IP"

msgid "DNS Server port"
msgstr "DNS服务器端口"

msgid "DNS Server type"
msgstr "协议类型"

msgid "DNS domain result cache size"
msgstr "缓存DNS的结果,缓存大小,配置零则不缓存。"

msgid "DNS64"
msgstr "DNS64"

msgid "DNS64 Server Settings"
msgstr "DNS64服务器配置"

msgid "default"
msgstr "默认"

msgid "Description"
msgstr "描述"

msgid "Dnsmasq Forwarded To Smartdns Failure"
msgstr "重定向dnsmasq到smartdns失败"

msgid "Do not check certificate."
msgstr "不校验证书的合法性。"

msgid "Do not check speed."
msgstr "禁用测速。"

msgid "Domain Address"
msgstr "域名地址"

msgid "Domain List"
msgstr "域名列表"

msgid "Domain List File"
msgstr "域名列表文件"

msgid "Domain Rule List"
msgstr "域名规则列表"

msgid "Domain Rule Name"
msgstr "域名规则名称"

msgid "Domain Rules"
msgstr "域名规则"

msgid "Domain Rules Settings"
msgstr "域名规则设置"

msgid "Domain TTL"
msgstr "域名TTL"

msgid "Domain TTL Max"
msgstr "域名TTL最大值"

msgid "Domain TTL Min"
msgstr "域名TTL最小值"

msgid "Domain prefetch"
msgstr "域名预加载"

msgid "Donate"
msgstr "捐助"

msgid "Donate to smartdns"
msgstr "捐助smartdns项目"

msgid "Download Files"
msgstr "下载文件"

msgid "Download Files Setting"
msgstr "下载文件设置"

msgid ""
"Download domain list files for domain-rule and include config files, please "
"refresh the page after download to take effect."
msgstr ""
"下载域名规则所需要的域名列表文件和smartdns配置文件,下载完成后刷新页面。"

msgid "Dual-stack IP Selection"
msgstr "双栈IP优选"

msgid "Enable"
msgstr "启用"

msgid "Enable Auto Update"
msgstr "启用自动更新"

msgid "Enable IP selection between IPV4 and IPV6"
msgstr "启用 IPV4 和 IPV6 间的 IP 优选策略。"

msgid "Enable IPV6 DNS Server"
msgstr "启用IPV6服务器。"

msgid "Enable TCP DNS Server"
msgstr "启用TCP服务器。"

msgid "Enable daily (weekly) auto update."
msgstr "启用每日(每周)自动更新"

msgid "Enable DOH DNS Server"
msgstr "启用DOH服务器"

msgid "Enable DOT DNS Server"
msgstr "启用DOT服务器"

msgid "Update time (every day)"
msgstr "更新时间(每天)"

msgid "Update Time (Every Week)"
msgstr "更新时间(每周)"

msgid "Enable Audit Log"
msgstr "启用审计日志"

msgid "Every Day"
msgstr "每天"

msgid "Every Monday"
msgstr "每周一"

msgid "Every Tuesday"
msgstr "每周二"

msgid "Every Wednesday"
msgstr "每周三"

msgid "Every Thursday"
msgstr "每周四"

msgid "Every Friday"
msgstr "每周五"

msgid "Every Saturday"
msgstr "每周六"

msgid "Every Sunday"
msgstr "每周日"

msgid "Enable domain prefetch, accelerate domain response speed."
msgstr "启用域名预加载,加速域名响应速度。"

msgid "Enable or disable second DNS server."
msgstr "是否启用第二DNS服务器。"

msgid "Enable or disable smartdns server"
msgstr "启用或禁用SmartDNS服务"

msgid "Exclude DNS Server from default group."
msgstr "从default默认服务器组中排除。"

msgid "Exclude Default Group"
msgstr "从默认组中排除"

msgid "file"
msgstr "文件"

msgid "Fastest IP"
msgstr "最快IP"

msgid "Fastest Response"
msgstr "最快响应"

msgid "File Name"
msgstr "文件名"

msgid "File Type"
msgstr "文件类型"

msgid "Filtering IP with blacklist"
msgstr "使用IP黑名单过滤"

msgid "First Ping"
msgstr "最快PING"

msgid "Force AAAA SOA"
msgstr "停用IPV6地址解析"

msgid "Force AAAA SOA."
msgstr "停用IPV6地址解析。"

msgid "Force HTTPS SOA"
msgstr "停用HTTPS记录解析"

msgid "Force HTTPS SOA."
msgstr "停用HTTPS记录解析。"

msgid "General Settings"
msgstr "常规设置"

msgid "Generate Coredump"
msgstr "生成coredump"

msgid ""
"Generate Coredump file when smartdns crash, coredump file is located at /tmp/"
"smartdns.xxx.core."
msgstr ""
"当smartdns异常时生成coredump文件,coredump文件在/tmp/smartdns.xxx.core."

msgid "Grant access to LuCI app smartdns"
msgstr "授予访问 LuCI 应用 smartdns 的权限"

msgid "Hosts File"
msgstr "Hosts文件"

msgid "HTTP Host"
msgstr "HTTP主机"

msgid "IP Blacklist"
msgstr "IP黑名单"

msgid "IP Blacklist Filtering"
msgstr "IP黑名单过滤"

msgid "IPV6 Server"
msgstr "IPV6服务器"

msgid "IP alias"
msgstr "IP别名"

msgid "IP Addresses"
msgstr "IP地址"

msgid "IP Address Mapping, Can be used for CDN acceleration with Anycast IP, such as Cloudflare's CDN."
msgstr "IP地址映射,可用于支持AnyCast IP的CDN加速,比如Cloudflare的CDN。"

msgid "Ignore IP"
msgstr "忽略IP"

msgid "IP Rules"
msgstr "IP规则"

msgid "IP Rules Settings"
msgstr "IP规则设置"

msgid "IP Rule List"
msgstr "IP规则列表"

msgid "IP Rule Name"
msgstr "IP规则名称"

msgid "IP Set File"
msgstr "IP集合列表文件"

msgid "IP addresses, CIDR format."
msgstr "IP地址,CIDR格式。"

msgid "IPset Name"
msgstr "IPset名称"

msgid "IPset name."
msgstr "IPset名称。"

msgid ""
"If a client address is specified, only that client will apply this "
"rule. You can enter an IP address, such as 1.2.3.4, or a MAC address, "
"such as aa:bb:cc:dd:ee:ff."
msgstr ""
"如果指定了客户端,那么对应的客户端会应用相应的规则,可以输入IP地址,如:1.2.3.4,或MAC地址,如:aa:bb:cc:dd:ee:ff。"

msgid "If you like this software, please buy me a cup of coffee."
msgstr "如果本软件对你有帮助,请给作者加个蛋。"

msgid "Include Config Files<br>/etc/smartdns/conf.d"
msgstr "包含配置文件<br>/etc/smartdns/conf.d"

msgid "Include hosts file."
msgstr "包含hosts文件。"

msgid ""
"Include other config files from /etc/smartdns/conf.d or custom path, can be "
"downloaded from the download page."
msgstr ""
"包含配置文件,路径为/etc/smartdns/conf.d,或自定义配置文件路径,可以从下载页"
"面配置自动下载。"

msgid "Ipset name, Add domain result to ipset when speed check fails."
msgstr "IPset名称,当测速失败时,将查询到的结果添加到对应的IPSet集合中。"

msgid "List of files to download."
msgstr "下载文件列表。"

msgid "Listen only on the specified interfaces."
msgstr "监听在指定的设备上,避免非本地网络的DNS查询请求。"

msgid "Local Port"
msgstr "本地端口"

msgid "Log Output Mode"
msgstr "日志输出模式"

msgid "Log Size"
msgstr "日志大小"

msgid "Log Level"
msgstr "日志级别"

msgid "Log Number"
msgstr "日志数量"

msgid "Log File"
msgstr "日志文件路径"

msgid "mDNS Lookup"
msgstr "mDNS查询"

msgid "Marking Packets"
msgstr "数据包标记"

msgid "Maximum TTL for all domain result."
msgstr "所有域名的最大 TTL 值。"

msgid "Minimum TTL for all domain result."
msgstr "所有域名的最小 TTL 值。"

msgid "NFTset Name"
msgstr "NFTSet名称"

msgid "NFTset name format error, format: [#[4|6]:[family#table#set]]"
msgstr "NFTSet名称格式错误,格式:[#[4|6]:[family#table#set]]"

msgid "NFTset name, format: [#[4|6]:[family#table#set]]"
msgstr "NFTSet名称,格式:[#[4|6]:[family#table#set]]"

msgid "NOT RUNNING"
msgstr "未运行"

msgid "Name of device name listen on."
msgstr "绑定的设备名称。"

msgid ""
"Nftset name, Add domain result to nftset when speed check fails, format: "
"[#[4|6]:[family#table#set]]"
msgstr "NFTset名称,当测速失败时,将查询到的结果添加到对应的NFTSet集合中。"

msgid "No"
msgstr "否"

msgid "No Speed IPset Name"
msgstr "无速度时IPSet名称"

msgid "No Speed NFTset Name"
msgstr "无速度时NFTSet名称"

msgid "No check certificate"
msgstr "停用证书校验"

msgid "None"
msgstr "无"

msgid "Only socks5 proxy support udp server."
msgstr "仅SOCKS5代理支持UDP服务器。"

msgid "Please check the system logs and check if the configuration is valid."
msgstr "请检查系统日志,并检查配置是否合法。"

msgid "Please set proxy server first."
msgstr "请先设置代理服务器。"

msgid "Proxy Server"
msgstr "代理服务器"

msgid "Proxy Server Settings"
msgstr "代理服务器设置"

msgid "Proxy Server URL, format: [socks5|http]://user:pass@ip:port."
msgstr "代理服务器地址,格式:[socks5|http]://user:pass@ip:port。"

msgid ""
"Proxy server URL format error, format: [socks5|http]://user:pass@ip:port."
msgstr "代理服务器地址格式错误,格式:[socks5|http]://user:pass@ip:port。"

msgid "Query DNS through specific dns server group, such as office, home."
msgstr "使用指定服务器组查询,比如office, home。"

msgid "RUNNING"
msgstr "运行中"

msgid "Reply Domain TTL Max"
msgstr "回应的域名TTL最大值"

msgid "Reply maximum TTL for all domain result."
msgstr "设置返回给客户端的域名TTL最大值。"

msgid "Report bugs"
msgstr "报告BUG"

msgid "Return SOA when the requested result contains a specified IP address."
msgstr "当结果包含对应范围的IP时,返回SOA。"

msgid "Resolve Local Hostnames"
msgstr "解析本地主机名"

msgid "Resolve local hostnames by reading Dnsmasq lease file."
msgstr "读取Dnsmasq的租约文件解析本地主机名。"

msgid "Resolve local network hostname via mDNS protocol."
msgstr "使用mDNS协议解析本地网络主机名。"

msgid "Response Mode"
msgstr "响应模式"

msgid "Restart"
msgstr "重启"

msgid "Restart Service"
msgstr "重启服务"

msgid "syslog"
msgstr "系统日志"

msgid "Second Server Settings"
msgstr "第二DNS服务器"

msgid "Server certificate file path."
msgstr "服务器证书文件路径。"

msgid "Server certificate key file path."
msgstr "服务器证书私钥文件路径。"

msgid "Server certificate key file password."
msgstr "服务器证书私钥文件密码。"

msgid "Serve expired"
msgstr "缓存过期服务"

msgid "Server Group"
msgstr "服务器组"

msgid "Server Group %s not exists"
msgstr "服务器组%s不存在"

msgid "Server Name"
msgstr "服务器名称"

msgid "Server Cert"
msgstr "服务器证书"

msgid "Server Cert Key"
msgstr "服务器证书私钥"

msgid "Server Cert Key Pass"
msgstr "服务器证书私钥密码"

msgid "Set Specific domain ip address."
msgstr "设置指定域名的IP地址。"

msgid "Set Specific domain rule list."
msgstr "设置指定域名的规则列表。"

msgid "Set Specific ip blacklist."
msgstr "设置指定的 IP 黑名单列表。"

msgid "Set Specific ip rule list."
msgstr "设置对应IP的规则。"

msgid "Set TLS hostname to verify."
msgstr "设置校验TLS主机名。"

msgid "Set mark on packets."
msgstr "设置数据包标记。"

msgid ""
"Set the HTTP host used for the query. Use this parameter when the host of "
"the URL address is an IP address."
msgstr "设置查询时使用的HTTP主机,当URL地址的host是IP地址时,使用此参数。"

msgid "Sets the server name indication for query. '-' for disable SNI name."
msgstr "设置服务器SNI名称,‘-’表示禁用SNI名称。"

msgid "Settings"
msgstr "设置"

msgid "Skip Address Rules"
msgstr "跳过address规则"

msgid "Skip Cache"
msgstr "跳过cache"

msgid "Skip Cache."
msgstr "跳过cache。"

msgid "Skip Dualstack Selection"
msgstr "跳过双栈优选"

msgid "Skip Dualstack Selection."
msgstr "跳过双栈优选。"

msgid "Skip IP Alias"
msgstr "跳过IP别名"

msgid "Skip Ipset Rule"
msgstr "跳过ipset规则"

msgid "Skip Nameserver Rule"
msgstr "跳过Nameserver规则"

msgid "Skip SOA Address Rule"
msgstr "跳过address SOA(#)规则"

msgid "Skip SOA address rules."
msgstr "跳过address SOA(#)规则。"

msgid "Skip Speed Check"
msgstr "跳过测速"

msgid "Skip address rules."
msgstr "跳过address规则。"

msgid "Skip ipset rules."
msgstr "跳过ipset规则。"

msgid "Skip nameserver rules."
msgstr "跳过Nameserver规则。"

msgid "SmartDNS"
msgstr "SmartDNS"

msgid "Smartdns DOH server port."
msgstr "Smartdns DOH服务器端口号。

msgid "Smartdns DOT server port."
msgstr "Smartdns DOT服务器端口号。"

msgid "SmartDNS Server"
msgstr "SmartDNS 服务器"

msgid ""
"SmartDNS is a local high-performance DNS server, supports finding fastest "
"IP, supports ad filtering, and supports avoiding DNS poisoning."
msgstr "SmartDNS是一个本地高性能DNS服务器,支持返回最快IP,支持广告过滤。"

msgid "SmartDNS official website"
msgstr "SmartDNS官方网站"

msgid "Smartdns local server port"
msgstr "SmartDNS本地服务端口"

msgid ""
"Smartdns local server port, smartdns will be automatically set as main dns "
"when the port is 53."
msgstr ""
"SmartDNS本地服务端口,当端口号设置为53时,smartdns将会自动配置为主dns。"

msgid ""
"Smartdns response mode, First Ping: return the first ping IP, Fastest IP: "
"return the fastest IP, Fastest Response: return the fastest DNS response."
msgstr ""
"SmartDNS响应模式,最快PING: 返回最早有ping结果的IP,速度适中;最快IP: 返回"
"最快IP,查询请求可能延长; 最快响应:返回最快响应的结果,查询请求时间短。"

msgid "Smartdns server name"
msgstr "SmartDNS的服务器名称,默认为smartdns,留空为主机名"

msgid "Smartdns speed check mode."
msgstr "SmartDNS测速模式。"

msgid ""
"Specify an IP address to return for any host in the given domains, Queries "
"in the domains are never forwarded and always replied to with the specified "
"IP address which may be IPv4 or IPv6."
msgstr ""
"配置特定域名返回特定的IP地址,域名查询将不到上游服务器请求,直接返回配置的IP"
"地址,可用于广告屏蔽。"

msgid "Speed Check Mode"
msgstr "测速模式"

msgid "Speed check mode is invalid."
msgstr "测速模式无效。"

msgid "TCP Server"
msgstr "TCP服务器"

msgid "TCP port is empty"
msgstr "TCP端口号为空"

msgid "TLS Hostname Verify"
msgstr "校验TLS主机名"

msgid "TLS SNI name"
msgstr "TLS SNI名称"

msgid "TLS SPKI Pinning"
msgstr "TLS SPKI 指纹"

msgid "TTL for all domain result."
msgstr "设置所有域名的 TTL 值。"

msgid "Technical Support"
msgstr "技术支持"

msgid "URL"
msgstr "URL"

msgid "URL format error, format: http:// or https://"
msgstr "URL格式错误,格式:http://或https://"

msgid "Update"
msgstr "更新"

msgid "Update Files"
msgstr "更新文件"

msgid "Upload client address file, same as Client Address function."
msgstr "上传客户端地址文件,与客户端地址功能相同。"

msgid "Upload Config File"
msgstr "上传配置文件"

msgid "Upload Domain List File"
msgstr "上传域名列表文件"

msgid "Upload domain list file to /etc/smartdns/domain-set"
msgstr "上传域名列表文件到/etc/smartdns/domain-set"

msgid ""
"Upload domain list file, or configure auto download from Download File "
"Setting page."
msgstr "上传域名列表文件,或在下载文件设置页面设置自动下载。"

msgid "Upload domain list file."
msgstr "上传域名列表文件"

msgid "Upload File"
msgstr "上传文件"

msgid "Upload IP set file."
msgstr "上传IP集合列表文件。"

msgid "Upload smartdns config file to /etc/smartdns/conf.d"
msgstr "上传配置文件到/etc/smartdns/conf.d"

msgid "Upstream Servers"
msgstr "上游服务器"

msgid ""
"Upstream Servers, support UDP, TCP protocol. Please configure multiple DNS "
"servers, including multiple foreign DNS servers."
msgstr ""
"上游 DNS 服务器,支持 UDP,TCP 协议。请配置多个上游 DNS 服务器,包括多个国内"
"外服务器。"

msgid "Use Proxy"
msgstr "使用代理"

msgid "Use proxy to connect to upstream DNS server."
msgstr "使用代理连接上游DNS服务器。"

msgid ""
"Used to verify the validity of the TLS server, The value is Base64 encoded "
"SPKI fingerprint, leaving blank to indicate that the validity of TLS is not "
"verified."
msgstr ""
"用于校验 TLS 服务器的有效性,数值为 Base64 编码的 SPKI 指纹,留空表示不验证 "
"TLS 的合法性。"

msgid "Whitelist IP"
msgstr "白名单"

msgid "Whitelist IP Rule, Accept IP addresses within the range."
msgstr "白名单规则,接受指定范围的IP地址。"

msgid "Write cache to disk on exit and load on startup."
msgstr "退出时保存cache到磁盘,启动时加载。"

msgid "Yes"
msgstr "是"

msgid "default"
msgstr "默认"

msgid "domain list (/etc/smartdns/domain-set)"
msgstr "域名列表(/etc/smartdns/domain-set)"

msgid "other file (/etc/smartdns/download)"
msgstr "其它文件(/etc/smartdns/download)"

msgid "https"
msgstr "https"

msgid "ip"
msgstr "ip"

msgid "ip-set file (/etc/smartdns/ip-set)"
msgstr "IP集合列表文件(/etc/smartdns/ip-set)"

msgid "ipset name format error, format: [#[4|6]:]ipsetname"
msgstr "IPset名称格式错误,格式:[#[4|6]:]ipsetname"

msgid "open website"
msgstr "打开网站"

msgid "port"
msgstr "端口"

msgid "smartdns config (/etc/smartdns/conf.d)"
msgstr "smartdns 配置文件(/etc/smartdns/conf.d)"

msgid "smartdns custom settings"
msgstr "smartdns 自定义设置,具体配置参数参考指导"

msgid "tcp"
msgstr "tcp"

msgid "tls"
msgstr "tls"

msgid "type"
msgstr "类型"

msgid "udp"
msgstr "udp"


================================================
FILE: package/luci/files/root/usr/share/luci/menu.d/luci-app-smartdns.json
================================================
{
	"admin/services/smartdns": {
		"title": "SmartDNS",
		"action": {
			"type": "view",
			"path": "smartdns/smartdns"
		},
		"depends": {
			"acl": [ "luci-app-smartdns" ],
			"uci": { "smartdns": true }
		}
	}
}


================================================
FILE: package/luci/files/root/usr/share/rpcd/acl.d/luci-app-smartdns.json
================================================
{
	"luci-app-smartdns": {
		"description": "Grant access to LuCI app smartdns",
		"read": {
			"file": {
				"/etc/smartdns/*": [ "read" ]
			},
			"ubus": {
				"service": [ "list" ]
			},
			"uci": [ "smartdns" ]
		},
		"write": {
			"file": {
				"/etc/smartdns/*": [ "write" ],
				"/etc/init.d/smartdns restart": [ "exec" ],
				"/etc/init.d/smartdns updatefiles": [ "exec" ]
			},
			"uci": [ "smartdns" ]
		}
	}
}


================================================
FILE: package/luci/files/root/www/luci-static/resources/view/smartdns/smartdns.js
================================================
/*************************************************************************
 *
 * Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
 *
 * smartdns is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * smartdns is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


'use strict';
'require fs';
'require uci';
'require form';
'require view';
'require poll';
'require rpc';
'require ui';

var conf = 'smartdns';
var callServiceList = rpc.declare({
	object: 'service',
	method: 'list',
	params: ['name'],
	expect: { '': {} }
});
var pollAdded = false;

function getServiceStatus() {
	return L.resolveDefault(callServiceList(conf), {})
		.then(function (res) {
			var is_running = false;
			try {
				is_running = res[conf]['instances']['smartdns']['running'];
			} catch (e) { }
			return is_running;
		});
}

function smartdnsServiceStatus() {
	return Promise.all([
		getServiceStatus()
	]);
}

function smartdnsRenderStatus(res) {
	var renderHTML = "";
	var isRunning = res[0];

	var autoSetDnsmasq = uci.get_first('smartdns', 'smartdns', 'auto_set_dnsmasq');
	var smartdnsPort = uci.get_first('smartdns', 'smartdns', 'port');
	var smartdnsEnable = uci.get_first('smartdns', 'smartdns', 'enabled');
	var dnsmasqServer = uci.get_first('dhcp', 'dnsmasq', 'server');

	if (isRunning) {
		renderHTML += "<span style=\"color:green;font-weight:bold\">SmartDNS - " + _("RUNNING") + "</span>";
	} else {
		renderHTML += "<span style=\"color:red;font-weight:bold\">SmartDNS - " + _("NOT RUNNING") + "</span>";
		if (smartdnsEnable === '1') {
			renderHTML += "<br /><span style=\"color:red;font-weight:bold\">" + _("Please check the system logs and check if the configuration is valid.");
			renderHTML += "</span>";
		}
		return renderHTML;
	}

	if (autoSetDnsmasq === '1' && smartdnsPort != '53') {
		var matchLine = "127.0.0.1#" + smartdnsPort;

		uci.unload('dhcp');
		uci.load('dhcp');
		if (dnsmasqServer == undefined || dnsmasqServer.indexOf(matchLine) < 0) {
			renderHTML += "<br /><span style=\"color:red;font-weight:bold\">" + _("Dnsmasq Forwarded To Smartdns Failure") + "</span>";
		}
	}

	return renderHTML;
}
return view.extend({
	load: function () {
		return Promise.all([
			uci.load('dhcp'),
			uci.load('smartdns'),
		]);
	},
	render: function (stats) {
		var m, s, o;
		var ss, so;
		var servers, download_files;

		m = new form.Map('smartdns', _('SmartDNS'));
		m.title = _("SmartDNS Server");
		m.description = _("SmartDNS is a local high-performance DNS server, supports finding fastest IP, "
			+ "supports ad filtering, and supports avoiding DNS poisoning.");

		s = m.section(form.NamedSection, '_status');
		s.anonymous = true;
		s.render = function (section_id) {
			var renderStatus = function () {
				return L.resolveDefault(smartdnsServiceStatus()).then(function (res) {
					var view = document.getElementById("service_status");
					if (view == null) {
						return;
					}

					view.innerHTML = smartdnsRenderStatus(res);
				});
			}

			if (pollAdded == false) {
				poll.add(renderStatus, 1);
				pollAdded = true;
			}

			return E('div', { class: 'cbi-section' }, [
				E('div', { id: 'service_status' },
					_('Collecting data ...'))
			]);
		}

		////////////////
		// Basic;
		////////////////
		s = m.section(form.TypedSection, "smartdns", _("Settings"), _("General Settings"));
		s.anonymous = true;

		s.tab("settings", _("General Settings"));
		s.tab("advanced", _('Advanced Settings'));
		s.tab("seconddns", _("Second Server Settings"));
		s.tab("dns64", _("DNS64 Server Settings"));
		s.tab("files", _("Download Files Setting"), _("Download domain list files for domain-rule and include config files, please refresh the page after download to take effect."));
		s.tab("proxy", _("Proxy Server Settings"));
		s.tab("custom", _("Custom Settings"));

		///////////////////////////////////////
		// Basic Settings
		///////////////////////////////////////
		o = s.taboption("settings", form.Flag, "enabled", _("Enable"), _("Enable or disable smartdns server"));
		o.rmempty = false;
		o.default = o.disabled;

		// server name;
		o = s.taboption("settings", form.Value, "server_name", _("Server Name"), _("Smartdns server name"));
		o.placeholder = "server name";
		o.datatype = "hostname";
		o.rempty = true;

		// Port;
		o = s.taboption("settings", form.Value, "port", _("Local Port"),
			_("Smartdns local server port, smartdns will be automatically set as main dns when the port is 53."));
		o.placeholder = 53;
		o.default = 53;
		o.datatype = "port";
		o.rempty = false;

		// auto-conf-dnsmasq;
		o = s.taboption("settings", form.Flag, "auto_set_dnsmasq", _("Automatically Set Dnsmasq"), _("Automatically set as upstream of dnsmasq when port changes."));
		o.rmempty = false;
		o.default = o.enabled;

		///////////////////////////////////////
		// advanced settings;
		///////////////////////////////////////
		// Speed check mode;
		o = s.taboption("advanced", form.Value, "speed_check_mode", _("Speed Check Mode"), _("Smartdns speed check mode."));
		o.rmempty = true;
		o.placeholder = "default";
		o.value("", _("default"));
		o.value("ping,tcp:80,tcp:443");
		o.value("ping,tcp:443,tcp:80");
		o.value("tcp:80,tcp:443,ping");
		o.value("tcp:443,tcp:80,ping");
		o.value("none", _("None"));
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			if (value == "none") {
				return true;
			}

			var check_mode = value.split(",")
			for (var i = 0; i < check_mode.length; i++) {
				if (check_mode[i] == "ping") {
					continue;
				}

				if (check_mode[i].indexOf("tcp:") == 0) {
					var port = check_mode[i].split(":")[1];
					if (port == "") {
						return _("TCP port is empty");
					}

					continue;
				}

				return _("Speed check mode is invalid.");
			}

			return true;
		}

		// response mode;
		o = s.taboption("advanced", form.ListValue, "response_mode", _("Response Mode"),
			_("Smartdns response mode, First Ping: return the first ping IP, Fastest IP: return the fastest IP, Fastest Response: return the fastest DNS response."));
		o.rmempty = true;
		o.placeholder = "default";
		o.value("", _("default"));
		o.value("first-ping", _("First Ping"));
		o.value("fastest-ip", _("Fastest IP"));
		o.value("fastest-response", _("Fastest Response"));

		// Enable TCP server;
		o = s.taboption("advanced", form.Flag, "tcp_server", _("TCP Server"), _("Enable TCP DNS Server"));
		o.rmempty = false;
		o.default = o.enabled;

		// Enable DOT server;
		o = s.taboption("advanced", form.Flag, "tls_server", _("DOT Server"), _("Enable DOT DNS Server"));
		o.rmempty = false;
		o.default = o.disabled;

		o = s.taboption("advanced", form.Value, "tls_server_port", _("DOT Server Port"), _("Smartdns DOT server port."));
		o.placeholder = 853;
		o.default = 853;
		o.datatype = "port";
		o.rempty = false;
		o.depends('tls_server', '1');

		// Enable DOH server;
		o = s.taboption("advanced", form.Flag, "doh_server", _("DOH Server"), _("Enable DOH DNS Server"));
		o.rmempty = false;
		o.default = o.disabled;

		o = s.taboption("advanced", form.Value, "doh_server_port", _("DOH Server Port"), _("Smartdns DOH server port."));
		o.placeholder = 843;
		o.default = 843;
		o.datatype = "port";
		o.rempty = false;
		o.depends('doh_server', '1');

		o = s.taboption("advanced", form.Value, "bind_cert", _("Server Cert"), _("Server certificate file path."));
		o.datatype = "string";
		o.placeholder = "/var/etc/smartdns/smartdns/smartdns-cert.pem"
		o.rempty = true;
		o.depends('tls_server', '1');
		o.depends('doh_server', '1');
	
		o = s.taboption("advanced", form.Value, "bind_cert_key", _("Server Cert Key"), _("Server certificate key file path."));
		o.datatype = "string";
		o.placeholder = "/var/etc/smartdns/smartdns/smartdns-key.pem"
		o.rempty = false;
		o.depends('tls_server', '1');
		o.depends('doh_server', '1');

		o = s.taboption("advanced", form.Value, "bind_cert_key_pass", _("Server Cert Key Pass"), _("Server certificate key file password."));
		o.datatype = "string";
		o.rempty = false;
		o.depends('tls_server', '1');
		o.depends('doh_server', '1');

		// Support IPV6;
		o = s.taboption("advanced", form.Flag, "ipv6_server", _("IPV6 Server"), _("Enable IPV6 DNS Server"));
		o.rmempty = false;
		o.default = o.enabled;

		// bind to device;
		o = s.taboption("advanced", form.Flag, "bind_device", _("Bind Device"), _("Listen only on the specified interfaces."));
		o.rmempty = false;
		o.default = o.enabled;

		// bind device name;
		o = s.taboption("advanced", form.Value, "bind_device_name", _("Bind Device Name"), _("Name of device name listen on."));
		o.placeholder = "default";
		o.rempty = true;
		o.datatype = "string";

		// Support DualStack ip selection;
		o = s.taboption("advanced", form.Flag, "dualstack_ip_selection", _("Dual-stack IP Selection"),
			_("Enable IP selection between IPV4 and IPV6"));
		o.rmempty = false;
		o.default = o.enabled;

		// Domain prefetch load ;
		o = s.taboption("advanced", form.Flag, "prefetch_domain", _("Domain prefetch"),
			_("Enable domain prefetch, accelerate domain response speed."));
		o.rmempty = true;
		o.default = o.disabled;

		// Domain Serve expired
		o = s.taboption("advanced", form.Flag, "serve_expired", _("Serve expired"),
			_("Attempts to serve old responses from cache with a TTL of 0 in the response without waiting for the actual resolution to finish."));
		o.rmempty = false;
		o.default = o.enabled;

		// cache-size;
		o = s.taboption("advanced", form.Value, "cache_size", _("Cache Size"), _("DNS domain result cache size"));
		o.rempty = true;

		// cache-persist;
		o = s.taboption("advanced", form.Flag, "cache_persist", _("Cache Persist"), _("Write cache to disk on exit and load on startup."));
		o.rmempty = false;
		o.default = o.enabled;

		// resolve local hostname;
		o = s.taboption("advanced", form.Flag, "resolve_local_hostnames", _("Resolve Local Hostnames"), _("Resolve local hostnames by reading Dnsmasq lease file."));
		o.rmempty = false;
		o.default = o.enabled;

		// resolve local network hostname via mDNS;
		o = s.taboption("advanced", form.Flag, "mdns_lookup", _("mDNS Lookup"), _("Resolve local network hostname via mDNS protocol."));
		o.rmempty = true;
		o.default = o.disabled;

		// Force AAAA SOA
		o = s.taboption("advanced", form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
		o.rmempty = true;
		o.default = o.disabled;

		// Force HTTPS SOA
		o = s.taboption("advanced", form.Flag, "force_https_soa", _("Force HTTPS SOA"), _("Force HTTPS SOA."));
		o.rmempty = false;
		o.default = o.enabled;

		// ipset name;
		o = s.taboption("advanced", form.Value, "ipset_name", _("IPset Name"), _("IPset name."));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var ipset = value.split(",")
			for (var i = 0; i < ipset.length; i++) {
				if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
					return _("ipset name format error, format: [#[4|6]:]ipsetname");
				}
			}

			return true;
		}

		// Ipset no speed.
		o = s.taboption("advanced", form.Value, "ipset_no_speed", _("No Speed IPset Name"),
			_("Ipset name, Add domain result to ipset when speed check fails."));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var ipset = value.split(",")
			for (var i = 0; i < ipset.length; i++) {
				if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
					return _("ipset name format error, format: [#[4|6]:]ipsetname");
				}
			}

			return true;
		}
		
		// NFTset name;
		o = s.taboption("advanced", form.Value, "nftset_name", _("NFTset Name"), _("NFTset name, format: [#[4|6]:[family#table#set]]"));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var nftset = value.split(",")
			for (var i = 0; i < nftset.length; i++) {
				if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
					return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
				}
			}

			return true;
		}

		// NFTset no speed.
		o = s.taboption("advanced", form.Value, "nftset_no_speed", _("No Speed NFTset Name"),
			_("Nftset name, Add domain result to nftset when speed check fails, format: [#[4|6]:[family#table#set]]"));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var nftset = value.split(",")
			for (var i = 0; i < nftset.length; i++) {
				if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
					return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
				}
			}

			return true;
		}

		// rr-ttl;
		o = s.taboption("advanced", form.Value, "rr_ttl", _("Domain TTL"), _("TTL for all domain result."));
		o.rempty = true;

		// rr-ttl-min;
		o = s.taboption("advanced", form.Value, "rr_ttl_min", _("Domain TTL Min"),
			_("Minimum TTL for all domain result."));
		o.rempty = true;
		o.placeholder = "600";
		o.default = 600;
		o.optional = true;

		// rr-ttl-max;
		o = s.taboption("advanced", form.Value, "rr_ttl_max", _("Domain TTL Max"),
			_("Maximum TTL for all domain result."));
		o.rempty = true;

		// rr-ttl-reply-max;
		o = s.taboption("advanced", form.Value, "rr_ttl_reply_max", _("Reply Domain TTL Max"),
			_("Reply maximum TTL for all domain result."));
		o.rempty = true;

		// other args
		o = s.taboption("advanced", form.Value, "server_flags", _("Additional Server Args"),
			_("Additional server args, refer to the help description of the bind option."))
		o.default = ""
		o.rempty = true

		// include config
		download_files = uci.sections('smartdns', 'download-file');
		o = s.taboption("advanced", form.DynamicList, "conf_files", _("Include Config Files<br>/etc/smartdns/conf.d"),
			_("Include other config files from /etc/smartdns/conf.d or custom path, can be downloaded from the download page."));
		for (var i = 0; i < download_files.length; i++) {
			if (download_files[i].type == undefined) {
				continue;
			}

			if (download_files[i].type != 'config') {
				continue
			}

			o.value(download_files[i].name);
		}

		o = s.taboption("advanced", form.DynamicList, "hosts_files", _("Hosts File"), _("Include hosts file."));
		o.rmempty = true;
		for (var i = 0; i < download_files.length; i++) {
			if (download_files[i].type == undefined) {
				continue;
			}

			if (download_files[i].type != 'other') {
				continue
			}

			o.value(download_files[i].name);
		}
	
		///////////////////////////////////////
		// second dns server;
		///////////////////////////////////////
		// Enable;
		o = s.taboption("seconddns", form.Flag, "seconddns_enabled", _("Enable"),
			_("Enable or disable second DNS server."));
		o.default = o.disabled;
		o.rempty = true;

		// Port;
		o = s.taboption("seconddns", form.Value, "seconddns_port", _("Local Port"), _("Smartdns local server port"));
		o.placeholder = 6553;
		o.default = 6553;
		o.datatype = "port";
		o.rempty = false;

		// Enable TCP server;
		o = s.taboption("seconddns", form.Flag, "seconddns_tcp_server", _("TCP Server"), _("Enable TCP DNS Server"));
		o.rmempty = false;
		o.default = o.enabled;

		// dns server group;
		o = s.taboption("seconddns", form.Value, "seconddns_server_group", _("Server Group"),
			_("Query DNS through specific dns server group, such as office, home."));
		o.rmempty = true;
		o.placeholder = "default";
		o.datatype = "hostname";
		o.rempty = true;

		o = s.taboption("seconddns", form.Flag, "seconddns_no_speed_check", _("Skip Speed Check"),
			_("Do not check speed."));
		o.rmempty = true;
		o.default = o.disabled;

		// skip address rules;
		o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_addr", _("Skip Address Rules"),
			_("Skip address rules."));
		o.rmempty = true;
		o.default = o.disabled;

		// skip name server rules;
		o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_nameserver", _("Skip Nameserver Rule"),
			_("Skip nameserver rules."));
		o.rmempty = true;
		o.default = o.disabled;

		// skip ipset rules;
		o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_ipset", _("Skip Ipset Rule"),
			_("Skip ipset rules."));
		o.rmempty = true;
		o.default = o.disabled;

		// skip soa address rule;
		o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_soa", _("Skip SOA Address Rule"),
			_("Skip SOA address rules."));
		o.rmempty = true;
		o.default = o.disabled;

		o = s.taboption("seconddns", form.Flag, "seconddns_no_dualstack_selection", _("Skip Dualstack Selection"),
			_("Skip Dualstack Selection."));
		o.rmempty = true;
		o.default = o.disabled;

		// skip cache;
		o = s.taboption("seconddns", form.Flag, "seconddns_no_cache", _("Skip Cache"), _("Skip Cache."));
		o.rmempty = true;
		o.default = o.disabled;

		// Force AAAA SOA
		o = s.taboption("seconddns", form.Flag, "seconddns_force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
		o.rmempty = true;
		o.default = o.disabled;
		
		// Force HTTPS SOA
		o = s.taboption("seconddns", form.Flag, "seconddns_force_https_soa", _("Force HTTPS SOA"), _("Force HTTPS SOA."));
		o.rmempty = true;
		o.default = o.disabled;

		o = s.taboption("seconddns", form.Flag, "seconddns_no_ip_alias", _("Skip IP Alias"));
		o.rmempty = true;
		o.default = o.disabled;

		o = s.taboption("seconddns", form.Value, "seconddns_ipset_name", _("IPset Name"), _("IPset name."));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var ipset = value.split(",")
			for (var i = 0; i < ipset.length; i++) {
				if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
					return _("ipset name format error, format: [#[4|6]:]ipsetname");
				}
			}

			return true;
		}

		o = s.taboption("seconddns", form.Value, "seconddns_nftset_name", _("NFTset Name"), _("NFTset name, format: [#[4|6]:[family#table#set]]"));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var nftset = value.split(",")
			for (var i = 0; i < nftset.length; i++) {
				if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
					return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
				}
			}

			return true;
		}

		// other args
		o = s.taboption("seconddns", form.Value, "seconddns_server_flags", _("Additional Server Args"),
			_("Additional server args, refer to the help description of the bind option."))
		o.default = ""
		o.rempty = true

		///////////////////////////////////////
		// DNS64 Settings
		///////////////////////////////////////
		o = s.taboption("dns64", form.Value, "dns64", _("DNS64"));
		o.placeholder = "64:ff9b::/96";
		o.datatype = "ip6addr";
		o.rempty = true;

		///////////////////////////////////////
		// download Files Settings
		///////////////////////////////////////
		o = s.taboption("files", form.Flag, "enable_auto_update", _("Enable Auto Update"), _("Enable daily (weekly) auto update."));
		o.rmempty = true;
		o.default = o.disabled;
		o.rempty = true;

		o = s.taboption("files", form.ListValue, "auto_update_week_time", _("Update Time (Every Week)"));
		o.value('*', _('Every Day'));
		o.value('1', _('Every Monday'));
		o.value('2', _('Every Tuesday'));
		o.value('3', _('Every Wednesday'));
		o.value('4', _('Every Thursday'));
		o.value('5', _('Every Friday'));
		o.value('6', _('Every Saturday'));
		o.value('0', _('Every Sunday'));
		o.default = "*";
		o.depends('enable_auto_update', '1');

		o = s.taboption('files', form.ListValue, 'auto_update_day_time', _("Update time (every day)"));
		for (var i = 0; i < 24; i++)
			o.value(i, i + ':00');
		o.default = '5';
		o.depends('enable_auto_update', '1');

		o = s.taboption("files", form.FileUpload, "upload_conf_file", _("Upload Config File"),
			_("Upload smartdns config file to /etc/smartdns/conf.d"));
		o.rmempty = true
		o.datatype = "file"
		o.rempty = true
		o.root_directory = "/etc/smartdns/conf.d"

		o = s.taboption("files", form.FileUpload, "upload_list_file", _("Upload Domain List File"),
			_("Upload domain list file to /etc/smartdns/domain-set"));
		o.rmempty = true
		o.datatype = "file"
		o.rempty = true
		o.root_directory = "/etc/smartdns/domain-set"

		o = s.taboption("files", form.FileUpload, "upload_other_file", _("Upload File"));
		o.rmempty = true
		o.datatype = "file"
		o.rempty = true
		o.root_directory = "/etc/smartdns/download"

		o = s.taboption('files', form.DummyValue, "_update", _("Update Files"));
		o.renderWidget = function () {
			return E('button', {
				'class': 'btn cbi-button cbi-button-apply',
				'id': 'btn_update',
				'click': ui.createHandlerFn(this, function () {
					return fs.exec('/etc/init.d/smartdns', ['updatefiles'])
						.catch(function (e) { ui.addNotification(null, E('p', e.message), 'error') });
				})
			}, [_("Update")]);
		}

		o = s.taboption('files', form.SectionValue, '__files__', form.GridSection, 'download-file', _('Download Files'),
			_('List of files to download.'));

		ss = o.subsection;

		ss.addremove = true;
		ss.anonymous = true;
		ss.sortable = true;

		so = ss.option(form.Value, 'name', _('File Name'), _('File Name'));
		so.rmempty = true;
		so.datatype = 'file';

		so = ss.option(form.Value, 'url', _('URL'), _('URL'));
		so.rmempty = true;
		so.datatype = 'string';
		so.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			if (!value.match(/^(http|https|ftp|sftp):\/\//)) {
				return _("URL format error, format: http:// or https://");
			}

			return true;
		}

		so = ss.option(form.ListValue, "type", _("type"), _("File Type"));
		so.value("list", _("domain list (/etc/smartdns/domain-set)"));
		so.value("config", _("smartdns config (/etc/smartdns/conf.d)"));
		so.value("ip-set", _("ip-set file (/etc/smartdns/ip-set)"));
		so.value("other", _("other file (/etc/smartdns/download)"));
		so.default = "list";
		so.rempty = false;

		so = ss.option(form.Value, 'desc', _('Description'), _('Description'));
		so.rmempty = true;
		so.datatype = 'string';

		///////////////////////////////////////
		// Proxy server settings;
		///////////////////////////////////////
		o = s.taboption("proxy", form.Value, "proxy_server", _("Proxy Server"), _("Proxy Server URL, format: [socks5|http]://user:pass@ip:port."));
		o.datatype = 'string';
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			if (!value.match(/^(socks5|http):\/\//)) {
				return _("Proxy server URL format error, format: [socks5|http]://user:pass@ip:port.");
			}

			return true;
		}

		///////////////////////////////////////
		// custom settings;
		///////////////////////////////////////
		o = s.taboption("custom", form.TextValue, "custom_conf",
			"", _("smartdns custom settings"));
		o.rows = 20;
		o.cfgvalue = function (section_id) {
			return fs.trimmed('/etc/smartdns/custom.conf');
		};
		o.write = function (section_id, formvalue) {
			return this.cfgvalue(section_id).then(function (value) {
				if (value == formvalue) {
					return
				}
				return fs.write('/etc/smartdns/custom.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
			});
		};

		o = s.taboption("custom", form.Flag, "coredump", _("Generate Coredump"),
			_("Generate Coredump file when smartdns crash, coredump file is located at /tmp/smartdns.xxx.core."));
		o.rmempty = true;
		o.default = o.disabled;

		o = s.taboption("custom", form.ListValue, "log_level", _("Log Level"));
		o.rmempty = true;
		o.placeholder = "default";
		o.value("", _("default"));
		o.value("debug");
		o.value("info");
		o.value("notice");
		o.value("warn");
		o.value("error");
		o.value("fatal");
		o.value("off");

		o = s.taboption("custom", form.ListValue, "log_output_mode", _("Log Output Mode"));
		o.rmempty = true;
		o.placeholder = _("file");
		o.value("file", _("file"));
		o.value("syslog", _("syslog"));
	
		o = s.taboption("custom", form.Value, "log_size", _("Log Size"));
		o.rmempty = true;
		o.placeholder = "default";
		o.depends("log_output_mode", "file");

		o = s.taboption("custom", form.Value, "log_num", _("Log Number"));
		o.rmempty = true;
		o.placeholder = "default";
		o.depends("log_output_mode", "file");

		o = s.taboption("custom", form.Value, "log_file", _("Log File"))
		o.rmempty = true
		o.placeholder = "/var/log/smartdns/smartdns.log"
		o.depends("log_output_mode", "file");

		o = s.taboption("custom", form.Flag, "enable_audit_log", _("Enable Audit Log"));
		o.rmempty = true;
		o.default = o.disabled;
		o.rempty = true;

		o = s.taboption("custom", form.ListValue, "audit_log_output_mode", _("Audit Log Output Mode"));
		o.rmempty = true;
		o.placeholder = _("file");
		o.value("file", _("file"));
		o.value("syslog", _("syslog"));
		o.depends("enable_audit_log", "1");

		o = s.taboption("custom", form.Value, "audit_log_size", _("Audit Log Size"));
		o.rmempty = true;
		o.placeholder = "default";
		o.depends({"enable_audit_log":"1", "audit_log_output_mode":"file"});

		o = s.taboption("custom", form.Value, "audit_log_num", _("Audit Log Number"));
		o.rmempty = true;
		o.placeholder = "default";
		o.depends({"enable_audit_log":"1", "audit_log_output_mode":"file"});

		o = s.taboption("custom", form.Value, "audit_log_file", _("Audit Log File"))
		o.rmempty = true
		o.placeholder = "/var/log/smartdns/smartdns-audit.log"
		o.depends({"enable_audit_log":"1", "audit_log_output_mode":"file"});

		////////////////
		// Upstream servers;
		////////////////
		s = m.section(form.GridSection, "server", _("Upstream Servers"),
			_("Upstream Servers, support UDP, TCP protocol. Please configure multiple DNS servers, "
				+ "including multiple foreign DNS servers."));
		s.anonymous = true;
		s.addremove = true;
		s.sortable = true;

		s.tab('general', _('General Settings'));
		s.tab('advanced', _('Advanced Settings'));

		// enable flag;
		o = s.taboption("general", form.Flag, "enabled", _("Enable"), _("Enable"));
		o.rmempty = false;
		o.default = o.enabled;
		o.editable = true;

		// name;
		o = s.taboption("general", form.Value, "name", _("DNS Server Name"), _("DNS Server Name"));

		// IP address;
		o = s.taboption("general", form.Value, "ip", _("ip"), _("DNS Server ip"));
		o.datatype = "or(ipaddr, string)";
		o.rmempty = false;

		// port;
		o = s.taboption("general", form.Value, "port", _("port"), _("DNS Server port"));
		o.placeholder = "default";
		o.datatype = "port";
		o.rempty = true;
		o.depends("type", "udp");
		o.depends("type", "tcp");
		o.depends("type", "tls");

		// type;
		o = s.taboption("general", form.ListValue, "type", _("type"), _("DNS Server type"));
		o.placeholder = "udp";
		o.value("udp", _("udp"));
		o.value("tcp", _("tcp"));
		o.value("tls", _("tls"));
		o.value("https", _("https"));
		o.default = "udp";
		o.rempty = false;

		// server group
		o = s.taboption("general", form.Value, "server_group", _("Server Group"), _("DNS Server group"))
		o.rmempty = true;
		o.placeholder = "default";
		o.datatype = "hostname";
		o.rempty = true;
		servers = uci.sections('smartdns', 'server');
		var groupnames = new Set();
		for (var i = 0; i < servers.length; i++) {
			if (servers[i].server_group == undefined) {
				continue;
			}
			groupnames.add(servers[i].server_group);
		}

		for (const groupname of groupnames) {
			o.value(groupname);
		}

		// Advanced Options
		o = s.taboption("advanced", form.Flag, "exclude_default_group", _("Exclude Default Group"), _("Exclude DNS Server from default group."))
		o.rmempty = true;
		o.default = o.disabled;
		o.editable = true;
		o.modalonly = true;

		// blacklist_ip
		o = s.taboption("advanced", form.Flag, "blacklist_ip", _("IP Blacklist Filtering"),
			_("Filtering IP with blacklist"))
		o.rmempty = true
		o.default = o.disabled
		o.modalonly = true;

		// TLS host verify
		o = s.taboption("advanced", form.Value, "tls_host_verify", _("TLS Hostname Verify"),
			_("Set TLS hostname to verify."))
		o.default = ""
		o.datatype = "string"
		o.rempty = true
		o.modalonly = true;
		o.depends("type", "tls")
		o.depends("type", "https")

		// certificate verify
		o = s.taboption("advanced", form.Flag, "no_check_certificate", _("No check certificate"),
			_("Do not check certificate."))
		o.rmempty = true
		o.default = o.disabled
		o.modalonly = true;
		o.depends("type", "tls")
		o.depends("type", "https")

		// SNI host name
		o = s.taboption("advanced", form.Value, "host_name", _("TLS SNI name"),
			_("Sets the server name indication for query. '-' for disable SNI name."))
		o.default = ""
		o.datatype = "hostname"
		o.rempty = true
		o.modalonly = true;
		o.depends("type", "tls")
		o.depends("type", "https")

		// http host
		o = s.taboption("advanced", form.Value, "http_host", _("HTTP Host"),
			_("Set the HTTP host used for the query. Use this parameter when the host of the URL address is an IP address."))
		o.default = ""
		o.datatype = "hostname"
		o.rempty = true
		o.modalonly = true;
		o.depends("type", "https")

		// SPKI pin
		o = s.taboption("advanced", form.Value, "spki_pin", _("TLS SPKI Pinning"),
			_("Used to verify the validity of the TLS server, The value is Base64 encoded SPKI fingerprint, "
				+ "leaving blank to indicate that the validity of TLS is not verified."))
		o.default = ""
		o.datatype = "string"
		o.rempty = true
		o.modalonly = true;
		o.depends("type", "tls")
		o.depends("type", "https")

		// mark
		o = s.taboption("advanced", form.Value, "set_mark", _("Marking Packets"),
			_("Set mark on packets."))
		o.default = ""
		o.rempty = true
		o.datatype = "uinteger"
		o.modalonly = true;

		// use proxy
		o = s.taboption("advanced", form.Flag, "use_proxy", _("Use Proxy"),
			_("Use proxy to connect to upstream DNS server."))
		o.default = o.disabled
		o.modalonly = true;
		o.optional = true;
		o.rempty = true;
		o.validate = function (section_id, value) {
			var flag = this.formvalue(section_id);
			if (flag == "0") {
				return true;
			}

			var proxy_server = uci.sections("smartdns", "smartdns")[0].proxy_server;
			var server_type = this.section.formvalue(section_id, "type");
			if (proxy_server == "" || proxy_server == undefined) {
				return _("Please set proxy server first.");
			}

			if (server_type == "udp" && !proxy_server.match(/^(socks5):\/\//)) {
				return _("Only socks5 proxy support udp server.");
			}

			return true;
		}

		// other args
		o = s.taboption("advanced", form.Value, "addition_arg", _("Additional Server Args"),
			_("Additional Args for upstream dns servers"))
		o.default = ""
		o.rempty = true
		o.modalonly = true;

		////////////////
		// client rules;
		////////////////
		s = m.section(form.TypedSection, "client-rule", _("Client Rules"), _("Client Rules Settings, can achieve parental control functionality."));
		s.anonymous = true;
		s.nodescriptions = true;

		s.tab("basic", _('Basic Settings'));
		s.tab("advanced", _('Advanced Settings'));
		s.tab("block", _("DNS Block Setting"));

		o = s.taboption("basic", form.Flag, "enabled", _("Enable"));
		o.rmempty = false;
		o.default = o.disabled;

		o = s.taboption("basic", form.DynamicList, "client_addr", _("Client Address"), 
		_("If a client address is specified, only that client will apply this rule. You can enter an IP address, such as 1.2.3.4, or a MAC address, such as aa:bb:cc:dd:ee:ff."));
		o.rempty = true
		o.rmempty = true;
		o.modalonly = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			if (value.match(/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\/([0-9]|[1-2][0-9]|3[0-2]))?$/)) {
				return true;
			}

			if (value.match(/^([a-fA-F0-9]*:){1,7}[a-fA-F0-9]*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$/)) {
				return true;
			}

			if (value.match(/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/)) {
				return true;
			}
			
			return _("Client address format error, please input ip adress or mac address.");
		}

		o = s.taboption("basic", form.FileUpload, "client_addr_file", _("Client Address File"),
			_("Upload client address file, same as Client Address function."));
		o.rmempty = true
		o.datatype = "file"
		o.rempty = true
		o.modalonly = true;
		o.root_directory = "/etc/smartdns/ip-set"
		
		o = s.taboption("basic", form.Value, "server_group", _("Server Group"), _("DNS Server group belongs to, such as office, home."))
		o.rmempty = true
		o.placeholder = "default"
		o.datatype = "hostname"
		o.rempty = true
		for (const groupname of groupnames) {
			o.value(groupname);
		}
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var val = uci.sections('smartdns', 'server');
			for (var i = 0; i < val.length; i++) {
				if (value == val[i].server_group) {
					return true;
				}
			}

			return _('Server Group %s not exists').format(value);

		}

		// Speed check mode;
		o = s.taboption("advanced", form.Value, "speed_check_mode", _("Speed Check Mode"), _("Smartdns speed check mode."));
		o.rmempty = true;
		o.placeholder = "default";
		o.value("", _("default"));
		o.value("ping,tcp:80,tcp:443");
		o.value("ping,tcp:443,tcp:80");
		o.value("tcp:80,tcp:443,ping");
		o.value("tcp:443,tcp:80,ping");
		o.value("none", _("None"));
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			if (value == "none") {
				return true;
			}

			var check_mode = value.split(",")
			for (var i = 0; i < check_mode.length; i++) {
				if (check_mode[i] == "ping") {
					continue;
				}

				if (check_mode[i].indexOf("tcp:") == 0) {
					var port = check_mode[i].split(":")[1];
					if (port == "") {
						return _("TCP port is empty");
					}

					continue;
				}

				return _("Speed check mode is invalid.");
			}

			return true;
		}

		// Support DualStack ip selection;
		o = s.taboption("advanced", form.Flag, "dualstack_ip_selection", _("Dual-stack IP Selection"),
			_("Enable IP selection between IPV4 and IPV6"));
		o.rmempty = false;
		o.default = o.enabled;

		// Force AAAA SOA
		o = s.taboption("advanced", form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
		o.rmempty = true;
		o.default = o.disabled;

		// Force HTTPS SOA
		o = s.taboption("advanced", form.Flag, "force_https_soa", _("Force HTTPS SOA"), _("Force HTTPS SOA."));
		o.rmempty = false;
		o.default = o.enabled;

		// ipset name;
		o = s.taboption("advanced", form.Value, "ipset_name", _("IPset Name"), _("IPset name."));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var ipset = value.split(",")
			for (var i = 0; i < ipset.length; i++) {
				if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
					return _("ipset name format error, format: [#[4|6]:]ipsetname");
				}
			}

			return true;
		}
		
		// NFTset name;
		o = s.taboption("advanced", form.Value, "nftset_name", _("NFTset Name"), _("NFTset name, format: [#[4|6]:[family#table#set]]"));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var nftset = value.split(",")
			for (var i = 0; i < nftset.length; i++) {
				if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
					return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
				}
			}

			return true;
		}

		// include config
		download_files = uci.sections('smartdns', 'download-file');
		o = s.taboption("advanced", form.DynamicList, "conf_files", _("Include Config Files<br>/etc/smartdns/conf.d"),
			_("Include other config files from /etc/smartdns/conf.d or custom path, can be downloaded from the download page."));
		for (var i = 0; i < download_files.length; i++) {
			if (download_files[i].type == undefined) {
				continue;
			}

			if (download_files[i].type != 'config') {
				continue
			}

			o.value(download_files[i].name);
		}

		o = s.taboption("block", form.FileUpload, "block_domain_set_file", _("Domain List File"), _("Upload domain list file."));
		o.rmempty = true
		o.datatype = "file"
		o.rempty = true
		o.editable = true
		o.root_directory = "/etc/smartdns/domain-set"


		////////////////
		// domain rules;
		////////////////
		s = m.section(form.TypedSection, "domain-rule", _("Domain Rules"), _("Domain Rules Settings"));
		s.anonymous = true;
		s.nodescriptions = true;

		s.tab("forwarding", _('DNS Forwarding Setting'));
		s.tab("block", _("DNS Block Setting"));
		s.tab("domain-rule-list", _("Domain Rule List"), _("Set Specific domain rule list."));
		s.tab("domain-address", _("Domain Address"), _("Set Specific domain ip address."));

		///////////////////////////////////////
		// domain forwarding;
		///////////////////////////////////////
		o = s.taboption("forwarding", form.Value, "server_group", _("Server Group"), _("DNS Server group belongs to, such as office, home."))
		o.rmempty = true
		o.placeholder = "default"
		o.datatype = "hostname"
		o.rempty = true
		for (const groupname of groupnames) {
			o.value(groupname);
		}
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var val = uci.sections('smartdns', 'server');
			for (var i = 0; i < val.length; i++) {
				if (value == val[i].server_group) {
					return true;
				}
			}

			return _('Server Group %s not exists').format(value);

		}

		// Speed check mode;
		o = s.taboption("forwarding", form.Value, "speed_check_mode", _("Speed Check Mode"), _("Smartdns speed check mode."));
		o.rmempty = true;
		o.placeholder = "default";
		o.value("", _("default"));
		o.value("ping,tcp:80,tcp:443");
		o.value("ping,tcp:443,tcp:80");
		o.value("tcp:80,tcp:443,ping");
		o.value("tcp:443,tcp:80,ping");
		o.value("none", _("None"));
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			if (value == "none") {
				return true;
			}

			var check_mode = value.split(",")
			for (var i = 0; i < check_mode.length; i++) {
				if (check_mode[i] == "ping") {
					continue;
				}

				if (check_mode[i].indexOf("tcp:") == 0) {
					var port = check_mode[i].split(":")[1];
					if (port == "") {
						return _("TCP port is empty");
					}

					continue;
				}

				return _("Speed check mode is invalid.");
			}

			return true;
		}

		// Support DualStack ip selection;
		o = s.taboption("forwarding", form.ListValue, "dualstack_ip_selection", _("Dual-stack IP Selection"),
			_("Enable IP selection between IPV4 and IPV6"));
		o.rmempty = true;
		o.default = "default";
		o.modalonly = true;
		o.value("", _("default"));
		o.value("yes", _("Yes"));
		o.value("no", _("No"));

		o = s.taboption("forwarding", form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
		o.rmempty = true;
		o.default = o.disabled;

		o = s.taboption("forwarding", form.Value, "ipset_name", _("IPset Name"), _("IPset name."));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var ipset = value.split(",")
			for (var i = 0; i < ipset.length; i++) {
				if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
					return _("ipset name format error, format: [#[4|6]:]ipsetname");
				}
			}

			return true;
		}

		o = s.taboption("forwarding", form.Value, "nftset_name", _("NFTset Name"), _("NFTset name, format: [#[4|6]:[family#table#set]]"));
		o.rmempty = true;
		o.datatype = "string";
		o.rempty = true;
		o.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var nftset = value.split(",")
			for (var i = 0; i < nftset.length; i++) {
				if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
					return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
				}
			}

			return true;
		}

		// other args
		o = s.taboption("forwarding", form.Value, "addition_flag", _("Additional Rule Flag"),
			_("Additional Flags for rules, read help on domain-rule for more information."))
		o.default = ""
		o.rempty = true
		o.modalonly = true;

		o = s.taboption("forwarding", form.FileUpload, "forwarding_domain_set_file", _("Domain List File"),
			_("Upload domain list file, or configure auto download from Download File Setting page."));
		o.rmempty = true
		o.datatype = "file"
		o.rempty = true
		o.editable = true
		o.root_directory = "/etc/smartdns/domain-set"

		o = s.taboption("forwarding", form.TextValue, "domain_forwarding_list",
			_("Domain List"), _("Configure forwarding domain name list."));
		o.rows = 10;
		o.cols = 64;
		o.monospace = true;
		o.cfgvalue = function (section_id) {
			return fs.trimmed('/etc/smartdns/domain-forwarding.list').catch(function (e) {
				return "";
			});
		};
		o.write = function (section_id, formvalue) {
			return this.cfgvalue(section_id).then(function (value) {
				if (value == formvalue) {
					return
				}
				return fs.write('/etc/smartdns/domain-forwarding.list', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
			});
		};

		///////////////////////////////////////
		// domain block;
		///////////////////////////////////////
		o = s.taboption("block", form.FileUpload, "block_domain_set_file", _("Domain List File"), _("Upload domain list file."));
		o.rmempty = true
		o.datatype = "file"
		o.rempty = true
		o.editable = true
		o.root_directory = "/etc/smartdns/domain-set"

		o = s.taboption("block", form.TextValue, "domain_block_list",
			_("Domain List"), _("Configure block domain list."));
		o.rows = 10;
		o.cols = 64;
		o.cfgvalue = function (section_id) {
			return fs.trimmed('/etc/smartdns/domain-block.list').catch(function (e) {
				return "";
			});
		};
		o.write = function (section_id, formvalue) {
			return this.cfgvalue(section_id).then(function (value) {
				if (value == formvalue) {
					return
				}
				return fs.write('/etc/smartdns/domain-block.list', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
			});
		};

		///////////////////////////////////////
		// domain rule list;
		///////////////////////////////////////
		o = s.taboption('domain-rule-list', form.SectionValue, '__domain-rule-list__', form.GridSection, 'domain-rule-list', _('Domain Rule List'),
			_('Configure domain rule list.'));

		ss = o.subsection;

		ss.addremove = true;
		ss.anonymous = true;
		ss.sortable = true;

		// enable flag;
		so = ss.option(form.Flag, "enabled", _("Enable"), _("Enable"));
		so.rmempty = false;
		so.default = so.enabled;
		so.editable = true;

		// name;
		so = ss.option(form.Value, "name", _("Domain Rule Name"), _("Domain Rule Name"));

		so = ss.option(form.Value, "server_group", _("Server Group"), _("DNS Server group belongs to, such as office, home."))
		so.rmempty = true
		so.placeholder = "default"
		so.datatype = "hostname"
		so.rempty = true
		for (const groupname of groupnames) {
			so.value(groupname);
		}
		so.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var val = uci.sections('smartdns', 'server');
			for (var i = 0; i < val.length; i++) {
				if (value == val[i].server_group) {
					return true;
				}
			}

			return _('Server Group %s not exists').format(value);

		}

		so = ss.option(form.FileUpload, "domain_list_file", _("Domain List File"),
			_("Upload domain list file, or configure auto download from Download File Setting page."));
		so.rmempty = true
		so.datatype = "file"
		so.rempty = true
		so.root_directory = "/etc/smartdns/domain-set"

		so = ss.option(form.ListValue, "block_domain_type", _("Block domain"), _("Block domain."));
		so.rmempty = true;
		so.value("none", _("None"));
		so.value("all", "IPv4/IPv6");
		so.value("ipv4", "IPv4");
		so.value("ipv6", "IPv6");
		so.modalonly = true;

		// Support DualStack ip selection;
		so = ss.option(form.ListValue, "dualstack_ip_selection", _("Dual-stack IP Selection"),
			_("Enable IP selection between IPV4 and IPV6"));
		so.rmempty = true;
		so.default = "default";
		so.modalonly = true;
		so.value("", _("default"));
		so.value("yes", _("Yes"));
		so.value("no", _("No"));

		so = ss.option(form.Value, "speed_check_mode", _("Speed Check Mode"), _("Smartdns speed check mode."));
		so.rmempty = true;
		so.placeholder = "default";
		so.modalonly = true;
		so.value("", _("default"));
		so.value("ping,tcp:80,tcp:443");
		so.value("ping,tcp:443,tcp:80");
		so.value("tcp:80,tcp:443,ping");
		so.value("tcp:443,tcp:80,ping");
		so.value("none", _("None"));
		so.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			if (value == "none") {
				return true;
			}

			var check_mode = value.split(",")
			for (var i = 0; i < check_mode.length; i++) {
				if (check_mode[i] == "ping") {
					continue;
				}

				if (check_mode[i].indexOf("tcp:") == 0) {
					var port = check_mode[i].split(":")[1];
					if (port == "") {
						return _("TCP port is empty");
					}

					continue;
				}

				return _("Speed check mode is invalid.");
			}

			return true;
		}

		so = ss.option(form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
		so.rmempty = true;
		so.default = so.disabled;
		so.modalonly = true;


		so = ss.option(form.Value, "ipset_name", _("IPset Name"), _("IPset name."));
		so.rmempty = true;
		so.datatype = "hostname";
		so.rempty = true;
		so.modalonly = true;

		so = ss.option(form.Value, "nftset_name", _("NFTset Name"), _("NFTset name, format: [#[4|6]:[family#table#set]]"));
		so.rmempty = true;
		so.datatype = "string";
		so.rempty = true;
		so.modalonly = true;
		so.validate = function (section_id, value) {
			if (value == "") {
				return true;
			}

			var nftset = value.split(",")
			for (var i = 0; i < nftset.length; i++) {
				if (!nftset[i].match(/#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
					return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
				}
			}

			return true;
		}

		// other args
		so = ss.option(form.Value, "addition_flag", _("Additional Rule Flag"),
			_("Additional Flags for rules, read help on domain-rule for more information."))
		so.default = ""
		so.rempty = true
		so.modalonly = true;

		///////////////////////////////////////
		// domain address
		///////////////////////////////////////
		o = s.taboption("domain-address", form.TextValue, "address_conf",
			"",
			_("Specify an IP address to return for any host in the given domains, Queries in the domains are never "
				+ "forwarded and always replied to with the specified IP address which may be IPv4 or IPv6."));
		o.rows = 20;
		o.cfgvalue = function (section_id) {
			return fs.trimmed('/etc/smartdns/address.conf');
		};
		o.write = function (section_id, formvalue) {
			return this.cfgvalue(section_id).then(function (value) {
				if (value == formvalue) {
					return
				}
				return fs.write('/etc/smartdns/address.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
			});
		};


		////////////////
		// ip rules;
		////////////////
		s = m.section(form.TypedSection, "ip-rule", _("IP Rules"), _("IP Rules Settings"));
		s.anonymous = true;
		s.nodescriptions = true;

		s.tab("ip-rule-list", _("IP Rule List"), _("Set Specific ip rule list."));
		s.tab("blackip-list", _("IP Blacklist"), _("Set Specific ip blacklist."));

		///////////////////////////////////////
		// ip rule list;
		///////////////////////////////////////
		o = s.taboption('ip-rule-list', form.SectionValue, '__ip-rule-list__', form.GridSection, 'ip-rule-list', _('IP Rule List'),
			_('Configure ip rule list.'));

		ss = o.subsection;

		ss.addremove = true;
		ss.anonymous = true;
		ss.sortable = true;

		// enable flag;
		so = ss.option(form.Flag, "enabled", _("Enable"), _("Enable"));
		so.rmempty = false;
		so.default = so.enabled;
		so.editable = true;

		// name;
		so = ss.option(form.Value, "name", _("IP Rule Name"), _("IP Rule Name"));
		so.rmempty = true;
		so.datatype = "string";

		so = ss.option(form.FileUpload, "ip_set_file", _("IP Set File"), _("Upload IP set file."));
		so.rmempty = true
		so.datatype = "file"
		so.modalonly = true;
		so.root_directory = "/etc/smartdns/ip-set"

		so = ss.option(form.DynamicList, "ip_addr", _("IP Addresses"), _("IP addresses, CIDR format."));
		so.rmempty = true;
		so.datatype = "ipaddr"
		so.modalonly = true;

		so = ss.option(form.Flag, "whitelist_ip", _("Whitelist IP"), _("Whitelist IP Rule, Accept IP addresses within the range."));
		so.rmempty = true;
		so.default = so.disabled;
		so.modalonly = true;

		so = ss.option(form.Flag, "blacklist_ip", _("Blacklist IP"), _("Blacklist IP Rule, Decline IP addresses within the range."));
		so.rmempty = true;
		so.default = so.disabled;
		so.modalonly = true;

		so = ss.option(form.Flag, "ignore_ip", _("Ignore IP"), _("Do not use these IP addresses."));
		so.rmempty = true;
		so.default = so.disabled;
		so.modalonly = true;

		so = ss.option(form.Flag, "bogus_nxdomain", _("Bogus nxdomain"), _("Return SOA when the requested result contains a specified IP address."));
		so.rmempty = true;
		so.default = so.disabled;
		so.modalonly = true;

		so = ss.option(form.DynamicList, "ip_alias", _("IP alias"), _("IP Address Mapping, Can be used for CDN acceleration with Anycast IP, such as Cloudflare's CDN."));
		so.rmempty = true;
		so.datatype = 'ipaddr("nomask")';
		so.modalonly = true;

		// other args
		so = ss.option(form.Value, "addition_flag", _("Additional Rule Flag"),
			_("Additional Flags for rules, read help on ip-rule for more information."))
		so.default = ""
		so.rempty = true
		so.modalonly = true;
		///////////////////////////////////////
		// IP Blacklist;
		///////////////////////////////////////
		// blacklist;
		o = s.taboption("blackip-list", form.TextValue, "blackip_ip_conf",
			"", _("Configure IP blacklists that will be filtered from the results of specific DNS server."));
		o.rows = 20;
		o.cfgvalue = function (section_id) {
			return fs.trimmed('/etc/smartdns/blacklist-ip.conf');
		};
		o.write = function (section_id, formvalue) {
			return this.cfgvalue(section_id).then(function (value) {
				if (value == formvalue) {
					return
				}
				return fs.write('/etc/smartdns/blacklist-ip.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
			});
		};

		////////////////
		// Support
		////////////////
		s = m.section(form.TypedSection, "smartdns", _("Technical Support"),
			_("If you like this software, please buy me a cup of coffee."));
		s.anonymous = true;

		o = s.option(form.Button, "web");
		o.title = _("SmartDNS official website");
		o.inputtitle = _("open website");
		o.inputstyle = "apply";
		o.onclick = function () {
			window.open("https://pymumu.github.io/smartdns", '_blank');
		};

		o = s.option(form.Button, "report");
		o.title = _("Report bugs");
		o.inputtitle = _("Report bugs");
		o.inputstyle = "apply";
		o.onclick = function () {
			window.open("https://github.com/pymumu/smartdns/issues", '_blank');
		};

		o = s.option(form.Button, "Donate");
		o.title = _("Donate to smartdns");
		o.inputtitle = _("Donate");
		o.inputstyle = "apply";
		o.onclick = function () {
			window.open("https://pymumu.github.io/smartdns/#donate", '_blank');
		};

		o = s.option(form.DummyValue, "_restart", _("Restart Service"));
		o.renderWidget = function () {
			return E('button', {
				'class': 'btn cbi-button cbi-button-apply',
				'id': 'btn_restart',
				'click': ui.createHandlerFn(this, function () {
					return fs.exec('/etc/init.d/smartdns', ['restart'])
						.catch(function (e) { ui.addNotification(null, E('p', e.message), 'error') });
				})
			}, [_("Restart")]);
		}
		return m.render();
	}
});


================================================
FILE: package/luci/make.sh
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
CURR_DIR=$(cd $(dirname $0);pwd)

VER="`date +"1.%Y.%m.%d-%H%M"`"
SMARTDNS_DIR=$CURR_DIR/../../
PO2LMO=

showhelp()
{
	echo "Usage: make [OPTION]"
	echo "Options:"
	echo " -o               output directory."
	echo " --arch           archtecture."
	echo " --ver            version."
	echo " -h               show this message."
}

build_tool()
{
	make -C $ROOT/tool/po2lmo -j 
	PO2LMO="$ROOT/tool/po2lmo/src/po2lmo"

}

clean_tool()
{
	make -C $ROOT/tool/po2lmo clean
}

build()
{

	ROOT=/tmp/luci-app-smartdns
	rm -fr $ROOT

	mkdir -p $ROOT
	cp $CURR_DIR/* $ROOT/ -af
	cp $CURR_DIR/../tool $ROOT/ -af
	cd $ROOT/
	build_tool
	
	mkdir $ROOT/root/usr/lib/lua/luci -p
	mkdir $ROOT/root/usr/share/rpcd/acl.d/ -p
	cp $ROOT/files/luci/i18n $ROOT/root/usr/lib/lua/luci/ -avf

	#Generate Language
	$PO2LMO $ROOT/files/luci/i18n/smartdns.zh-cn.po $ROOT/root/usr/lib/lua/luci/i18n/smartdns.zh-cn.lmo
	rm $ROOT/root/usr/lib/lua/luci/i18n/smartdns.zh-cn.po

	cp $ROOT/files/root/* $ROOT/root/ -avf
	INST_SIZE="`du -sb $ROOT/root/ | awk '{print $1}'`"
	
	sed -i "s/^Architecture.*/Architecture: all/g" $ROOT/control/control
	sed -i "s/Version:.*/Version: $VER/" $ROOT/control/control

	if [ ! -z "$INST_SIZE" ]; then
		echo "Installed-Size: $INST_SIZE" >> $ROOT/control/control
	fi

	cd $ROOT/control
	chmod +x *
	tar zcf ../control.tar.gz ./
	cd $ROOT

	tar zcf $ROOT/data.tar.gz -C root .
	tar zcf $OUTPUTDIR/luci-app-smartdns.$VER.$FILEARCH.ipk ./control.tar.gz ./data.tar.gz ./debian-binary

	which apk >/dev/null 2>&1
	if [ $? -eq 0 ]; then
		APK_VER="`echo $VER | sed 's/[-]/-r/'`"
		ARCH="`echo $ARCH | sed 's/all/noarch/g'`"
		apk mkpkg \
			--info "name:luci-app-smartdns" \
			--info "version:$APK_VER" \
			--info "description:smartdns luci" \
			--info "arch:$ARCH" \
			--info "license:GPL" \
			--info "origin: https://github.com/pymumu/smartdns.git" \
			--info "depends:libc smartdns" \
			--script "post-install:$ROOT/control/postinst" \
			--script "pre-deinstall:$ROOT/control/prerm" \
			--files "$ROOT/root/" \
			--output "$OUTPUTDIR/luci-app-smartdns.$VER.$FILEARCH.apk"
		if [ $? -ne 0 ]; then
			echo "build apk package failed."
			rm -fr $ROOT/
			return 1
		fi
	else
		echo "== warning: apk tool not found, skip build apk package. =="
	fi

	rm -fr $ROOT/
}

main()
{
	OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
		-n  "" -- "$@"`

	if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

	# Note the quotes around `$TEMP': they are essential!
	eval set -- "$OPTS"

	while true; do
		case "$1" in
		--arch)
			ARCH="$2"
			shift 2;;
		--filearch)
			FILEARCH="$2"
			shift 2;;
		--ver)
			VER="$2"
			shift 2;;
		-o )
			OUTPUTDIR="$2"
			shift 2;;
		-h | --help )
			showhelp
			return 0
			shift ;;
		-- ) shift; break ;;
		* ) break ;;
		esac
	done

	if [ -z "$ARCH" ]; then
		echo "please input arch."
		return 1;
	fi

	if [ -z "$FILEARCH" ]; then
		FILEARCH=$ARCH
	fi

	if [ -z "$OUTPUTDIR" ]; then
		OUTPUTDIR=$CURR_DIR;
	fi

	build
}

main $@
exit $?




================================================
FILE: package/luci-compat/control/control
================================================
Package: luci-app-smartdns
Version: git-18.201.27126-7bf0367-1
Depends: libc, smartdns
Source: feeds/luci/applications/luci-app-smartdns
Section: luci
Architecture: all
Description:  A smartdns server


================================================
FILE: package/luci-compat/control/postinst
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0
[ -e ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_postinst $0 $@


================================================
FILE: package/luci-compat/control/prerm
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

[ -e ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_prerm $0 $@


================================================
FILE: package/luci-compat/debian-binary
================================================
2.0


================================================
FILE: package/luci-compat/files/etc/uci-defaults/50_luci-smartdns
================================================
#!/bin/sh
#
# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
#
# smartdns is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# smartdns is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

uci -q batch <<-EOF >/dev/null
	delete ucitrack.@smartdns[-1]
	add ucitrack smartdns
	set ucitrack.@smartdns[-1].init=smartdns
	commit ucitrack
EOF

rm -f /tmp/luci-indexcache
exit 0


================================================
FILE: package/luci-compat/files/luci/controller/smartdns.lua
================================================
--
-- Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.
--
-- smartdns is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- smartdns is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

module("luci.controller.smartdns", package.seeall)
local smartdns = require "luci.model.smartdns"

function index()
	if not nixio.fs.access("/etc/config/smartdns") then
		return
	end

	local page
	page = entry({"admin", "services", "smartdns"}, cbi("smartdns/smartdns"), _("SmartDNS"), 60)
	page.dependent = true
	page = entry({"admin", "services", "smartdns", "status"}, call("act_status"))
	page.leaf = true
	page = entry({"admin", "services", "smartdns", "upstream"}, cbi("smartdns/upstream"), nil)
	page.leaf = true
end

local function is_running()
	return luci.sys.call("pidof smartdns >/dev/null") == 0
end

function act_status()
	local e={}
	local ipv6_server;
	local dnsmasq_server = smartdns.get_config_option("dhcp", "dnsmasq", "server", {nil})[1]
	local auto_set_dnsmasq = smartdns.get_config_option("smartdns", "smartdns", "auto_set_dnsmasq", nil);
	
	e.auto_set_dnsmasq = auto_set_dnsmasq
	e.dnsmasq_server = dnsmasq_server
	e.local_port = smartdns.get_config_option("smartdns", "smartdns", "port", nil);
	if e.local_port ~= nil and e.local_port ~= "53" and auto_set_dnsmasq ~= nil and auto_set_dnsmasq == "1" then
		local str;
		str = "127.0.0.1#" .. e.local_port 
		if dnsmasq_server ~= str then
			e.dnsmasq_redirect_failure = 1
		end
	end
	e.running = is_running()
	luci.http.prepare_content("application/json")
	luci.http.write_json(e)
end


================================================
FILE: package/luci-compat/files/luci/i18n/smartdns.zh-cn.po
================================================

msgid "Additional Args for upstream dns servers"
msgstr "额外的上游 DNS 服务器参数"

msgid ""
"Additional Flags for rules, read help on domain-rule for more information."
msgstr "额外的规则标识,具体参考domain-rule的帮助说明。"

msgid ""
"Additional Flags for rules, read help on ip-rule for more information."
msgstr "额外的规则标识,具体参考ip-rule的帮助说明。"

msgid "Additional Rule Flag"
msgstr "额外规则标识"

msgid "Additional Server Args"
msgstr "额外的服务器参数"

msgid "Additional server args, refer to the help description of the bind option."
msgstr "额外的服务器参数,参考bind选项的帮助说明。"

msgid "Advanced Settings"
msgstr "高级设置"

msgid "Audit Log Output Mode"
msgstr "审计日志输出模式"

msgid "Audit Log Size"
msgstr "审计日志大小"

msgid "Audit Log Number"
msgstr "审计日志数量"

msgid "Audit Log File"
msgstr "审计日志文件路径"

msgid ""
"Attempts to serve old responses from cache with a TTL of 0 in the response "
"without waiting for the actual resolution to finish."
msgstr "查询性能优化,有请求时尝试回应TTL为0的过期记录,以避免查询等待。"

msgid "Automatically Set Dnsmasq"
msgstr "自动设置Dnsmasq"

msgid "Automatically set as upstream of dnsmasq when port changes."
msgstr "端口更改时自动设为 dnsmasq 的上游。"

msgid "Basic Settings"
msgstr "基本设置"

msgid "Bind Device"
msgstr "绑定到设备"

msgid "Bind Device Name"
msgstr "绑定的设备名称"

msgid "Bogus nxdomain"
msgstr "假冒IP"

msgid "Blacklist IP"
msgstr "黑名单"

msgid "Blacklist IP Rule, Decline IP addresses within the range."
msgstr "黑名单规则,拒绝指定范围的IP地址。"

msgid "Block domain"
msgstr "屏蔽域名"

msgid "Block domain."
msgstr "屏蔽域名。"

msgid "Cache Persist"
msgstr "持久化缓存"

msgid "Cache Size"
msgstr "缓存大小"

msgid "Client Rules"
msgstr "客户端规则"

msgid "Client Address"
msgstr "客户端地址"

msgid "Client Address File"
msgstr "客户端地址文件"

msgid "Client Rules Settings, can achieve parental control functionality."
msgstr "客户端规则设置,可以实现家长控制功能。"

msgid "Collecting data ..."
msgstr "正在收集数据..."

msgid ""
"Configure IP blacklists that will be filtered from the results of specific "
"DNS server."
msgstr "配置需要从指定域名服务器结果过滤的IP黑名单。"

msgid "Configure block domain list."
msgstr "配置屏蔽域名列表"

msgid "Configure domain rule list."
msgstr "配置域名规则列表"

msgid "Configure forwarding domain name list."
msgstr "配置分流域名列表"

msgid "Custom Settings"
msgstr "自定义设置"

msgid "Do not use these IP addresses."
msgstr "忽略这些IP地址"

msgid "DOH Server"
msgstr "DOH服务器"

msgid "DOH Server Port"
msgstr "DOH服务器端口"

msgid "DOT Server"
msgstr "DOT服务器"

msgid "DOT Server Port"
msgstr "DOT服务器端口"

msgid "DNS Block Setting"
msgstr "域名屏蔽设置"

msgid "DNS Forwarding Setting"
msgstr "域名分流设置"

msgid "DNS Server Name"
msgstr "DNS服务器名称"

msgid "DNS Server group"
msgstr "服务器组"

msgid "DNS Server group belongs to, such as office, home."
msgstr "设置服务器组,例如office,home"

msgid "DNS Server ip"
msgstr "DNS服务器IP"

msgid "DNS Server port"
msgstr "DNS服务器端口"

msgid "DNS Server type"
msgstr "协议类型"

msgid "DNS domain result cache size"
msgstr "缓存DNS的结果,缓存大小,配置零则不缓存。"

msgid "DNS64"
msgstr "DNS64"

msgid "DNS64 Server Settings"
msgstr "DNS64服务器配置"

msgid "default"
msgstr "默认"

msgid "Description"
msgstr "描述"

msgid "Dnsmasq Forwarded To Smartdns Failure"
msgstr "重定向dnsmasq到smartdns失败"

msgid "Do not check certificate."
msgstr "不校验证书的合法性。"

msgid "Do not check speed."
msgstr "禁用测速。"

msgid "Domain Address"
msgstr "域名地址"

msgid "Domain List"
msgstr "域名列表"

msgid "Domain List File"
msgstr "域名列表文件"

msgid "Domain Rule List"
msgstr "域名规则列表"

msgid "Domain Rule Name"
msgstr "域名规则名称"

msgid "Domain Rules"
msgstr "域名规则"

msgid "Domain Rules Settings"
msgstr "域名规则设置"

msgid "Domain TTL"
msgstr "域名TTL"

msgid "Domain TTL Max"
msgstr "域名TTL最大值"

msgid "Domain TTL Min"
msgstr "域名TTL最小值"

msgid "Domain prefetch"
msgstr "域名预加载"

msgid "Donate"
msgstr "捐助"

msgid "Donate to smartdns"
msgstr "捐助smartdns项目"

msgid "Download Files"
msgstr "下载文件"

msgid "Download Files Setting"
msgstr "下载文件设置"

msgid ""
"Download domain list files for domain-rule and include config files, please "
"refresh the page after download to take effect."
msgstr ""
"下载域名规则所需要的域名列表文件和smartdns配置文件,下载完成后刷新页面。"

msgid "Dual-stack IP Selection"
msgstr "双栈IP优选"

msgid "Enable"
msgstr "启用"

msgid "Enable Auto Update"
msgstr "启用自动更新"

msgid "Enable IP selection between IPV4 and IPV6"
msgstr "启用 IPV4 和 IPV6 间的 IP 优选策略。"

msgid "Enable IPV6 DNS Server"
msgstr "启用IPV6服务器。"

msgid "Enable TCP DNS Server"
msgstr "启用TCP服务器。"

msgid "Enable daily(week) auto update."
msgstr "启用每天(每周)自动更新。"

msgid "Enable DOH DNS Server"
msgstr "启用DOH服务器。"

msgid "Enable DOT DNS Server"
msgstr "启用DOT服务器。"

msgid "Update Time (Every Week)"
msgstr "更新时间(每周)"

msgid "Every Day"
msgstr "每天"

msgid "Every Monday"
msgstr "每周一"

msgid "Every Tuesday"
msgstr "每周二"

msgid "Every Wednesday"
msgstr "每周三"

msgid "Every Thursday"
msgstr "每周四"

msgid "Every Friday"
msgstr "每周五"

msgid "Every Saturday"
msgstr "每周六"

msgid "Every Sunday"
msgstr "每周日"

msgid "Update Time (Every Day)"
msgstr "更新时间(每天)"

msgid "Enable Audit Log"
msgstr "启用审计日志"

msgid "Enable domain prefetch, accelerate domain response speed."
msgstr "启用域名预加载,加速域名响应速度。"

msgid "Enable or disable second DNS server."
msgstr "是否启用第二DNS服务器。"

msgid "Enable or disable smartdns server"
msgstr "启用或禁用SmartDNS服务"

msgid "Exclude DNS Server from default group."
msgstr "从default默认服务器组中排除。"

msgid "Exclude Default Group"
msgstr "从默认组中排除"

msgid "file"
msgstr "文件"

msgid "Fastest IP"
msgstr "最快IP"

msgid "Fastest Response"
msgstr "最快响应"

msgid "File Name"
msgstr "文件名"

msgid "File Type"
msgstr "文件类型"

msgid "Filtering IP with blacklist"
msgstr "使用IP黑名单过滤"

msgid "First Ping"
msgstr "最快PING"

msgid "Force AAAA SOA"
msgstr "停用IPV6地址解析"

msgid "Force AAAA SOA."
msgstr "停用IPV6地址解析。"

msgid "Force HTTPS SOA"
msgstr "停用HTTPS记录解析"

msgid "Force HTTPS SOA."
msgstr "停用HTTPS记录解析。"

msgid "General Settings"
msgstr "常规设置"

msgid "Generate Coredump"
msgstr "生成coredump"

msgid ""
"Generate Coredump file when smartdns crash, coredump file is located at /tmp/"
"smartdns.xxx.core."
msgstr ""
"当smartdns异常时生成coredump文件,coredump文件在/tmp/smartdns.xxx.core."

msgid "Grant access to LuCI app smartdns"
msgstr "授予访问 LuCI 应用 smartdns 的权限"

msgid "Hosts File"
msgstr "Hosts文件"

msgid "HTTP Host"
msgstr "HTTP主机"

msgid "IP alias"
msgstr "IP别名"

msgid "IP Alias Setting"
msgstr "IP别名设置"

msgid "IP Blacklist"
msgstr "IP黑名单"

msgid "IP Blacklist Filtering"
msgstr "IP黑名单过滤"

msgid "IP Addresses"
msgstr "IP地址"

msgid "IP Address Mapping, Can be used for CDN acceleration with Anycast IP, such as Cloudflare's CDN."
msgstr "IP地址映射,可用于支持AnyCast IP的CDN加速,比如Cloudflare的CDN。"

msgid "Ignore IP"
msgstr "忽略IP"

msgid "IP Rules"
msgstr "IP规则"

msgid "IP Rules Settings"
msgstr "IP规则设置"

msgid "IP Rule Name"
msgstr "IP规则名称"

msgid "IP Set File"
msgstr "IP集合列表文件"

msgid "IP addresses, CIDR format."
msgstr "IP地址,CIDR格式。"

msgid "IPV6 Server"
msgstr "IPV6服务器"

msgid "IPset Name"
msgstr "IPset名称"

msgid "IPset name."
msgstr "IPset名称。"

msgid ""
"If a client address is specified, only that client will apply this "
"rule. You can enter an IP address, such as 1.2.3.4, or a MAC address, "
"such as aa:bb:cc:dd:ee:ff."
msgstr ""
"如果指定了客户端,那么对应的客户端会应用相应的规则,可以输入IP地址,如:1.2.3.4,或MAC地址,如:aa:bb:cc:dd:ee:ff。"

msgid "If you like this software, please buy me a cup of coffee."
msgstr "如果本软件对你有帮助,请给作者加个蛋。"

msgid "Include Config Files<br>/etc/smartdns/conf.d"
msgstr "包含配置文件<br>/etc/smartdns/conf.d"

msgid "Include hosts file."
msgstr "包含hosts文件。"

msgid ""
"Include other config files from /etc/smartdns/conf.d or custom path, can be "
"downloaded from the download page."
msgstr ""
"包含配置文件,路径为/etc/smartdns/conf.d,或自定义配置文件路径,可以从下载页"
"配置自动下载。面配置自动下载。"

msgid "Ipset name, Add domain result to ipset when speed check fails."
msgstr "IPset名称,当测速失败时,将查询到的结果添加到对应的IPSet集合中。"

msgid "List of files to download."
msgstr "下载文件列表。"

msgid "Listen only on the specified interfaces."
msgstr "监听在指定的设备上,避免非本地网络的DNS查询请求。"

msgid "Local Port"
msgstr "本地端口"

msgid "Log Output Mode"
msgstr "日志输出模式"

msgid "Log Size"
msgstr "日志大小"

msgid "Log Level"
msgstr "日志级别"

msgid "Log Number"
msgstr "日志数量"

msgid "Log File"
msgstr "日志文件路径"

msgid "mDNS Lookup"
msgstr "mDNS查询"

msgid "Marking Packets"
msgstr "数据包标记"

msgid "Maximum TTL for all domain result."
msgstr "所有域名的最大 TTL 值。"

msgid "Minimum TTL for all domain result."
msgstr "所有域名的最小 TTL 值。"

msgid "NFTset Name"
msgstr "NFTSet名称"

msgid "NFTset name format error, format: [#[4|6]:[family#table#set]]"
msgstr "NFTSet名称格式错误,格式:[#[4|6]:[family#table#set]]"

msgid "NFTset name, format: [#[4|6]:[family#table#set]]"
msgstr "NFTSet名称,格式:[#[4|6]:[family#table#set]]"

msgid "NOT RUNNING"
msgstr "未运行"

msgid "Name of device name listen on."
msgstr "绑定的设备名称。"

msgid ""
"Nftset name, Add domain result to nftset when speed check fails, format: "
"[#[4|6]:[family#table#set]]"
msgstr "NFTset名称,当测速失败时,将查询到的结果添加到对应的NFTSet集合中。"

msgid "No"
msgstr "否"

msgid "No Speed IPset Name"
msgstr "无速度时IPSet名称"

msgid "No Speed NFTset Name"
msgstr "无速度时NFTSet名称"

msgid "No check certificate"
msgstr "停用证书校验"

msgid "None"
msgstr "无"

msgid "Only socks5 proxy support udp server."
msgstr "仅SOCKS5代理支持UDP服务器。"

msgid "Please set proxy server first."
msgstr "请先设置代理服务器。"

msgid "Proxy Server"
msgstr "代理服务器"

msgid "Proxy Server Settings"
msgstr "代理服务器设置"

msgid "Proxy Server URL, format: [socks5|http]://user:pass@ip:port."
msgstr "代理服务器地址,格式:[socks5|http]://user:pass@ip:port。"

msgid ""
"Proxy server URL format error, format: [socks5|http]://user:pass@ip:port."
msgstr "代理服务器地址格式错误,格式:[socks5|http]://user:pass@ip:port。"

msgid "Query DNS through specific dns server group, such as office, home."
msgstr "使用指定服务器组查询,比如office, home。"

msgid "RUNNING"
msgstr "运行中"

msgid "Reply Domain TTL Max"
msgstr "回应的域名TTL最大值"

msgid "Reply maximum TTL for all domain result."
msgstr "设置返回给客户端的域名TTL最大值。"

msgid "Report bugs"
msgstr "报告BUG"

msgid "Return SOA when the requested result contains a specified IP address."
msgstr "当结果包含对应范围的IP时,返回SOA。"

msgid "Resolve Local Hostnames"
msgstr "解析本地主机名"

msgid "Resolve local hostnames by reading Dnsmasq lease file."
msgstr "读取Dnsmasq的租约文件解析本地主机名。"

msgid "Resolve local network hostname via mDNS protocol."
msgstr "使用mDNS协议解析本地网络主机名。"

msgid "Response Mode"
msgstr "响应模式"

msgid "Restart"
msgstr "重启"

msgid "Restart Service"
msgstr "重启服务"

msgid "syslog"
msgstr "系统日志"

msgid "Second Server Settings"
msgstr "第二DNS服务器"

msgid "Server certificate file path."
msgstr "服务器证书文件路径。"

msgid "Server certificate key file path."
msgstr "服务器证书私钥文件路径。"

msgid "Server certificate key file password."
msgstr "服务器证书私钥文件密码。"

msgid "Serve expired"
msgstr "缓存过期服务"

msgid "Server Group"
msgstr "服务器组"

msgid "Server Group %s not exists"
msgstr "服务器组%s不存在"

msgid "Server Name"
msgstr "服务器名称"

msgid "Server Cert"
msgstr "服务器证书"

msgid "Server Cert Key"
msgstr "服务器证书私钥"

msgid "Server Cert Key Pass"
msgstr "服务器证书私钥密码"

msgid "Set Specific domain ip address."
msgstr "设置指定域名的IP地址。"

msgid "Set Specific domain rule list."
msgstr "设置指定域名的规则列表。"

msgid "Set Specific ip blacklist."
msgstr "设置指定的 IP 黑名单列表。"

msgid "Set TLS hostname to verify."
msgstr "设置校验TLS主机名。"

msgid "Set mark on packets."
msgstr "设置数据包标记。"

msgid ""
"Set the HTTP host used for the query. Use this parameter when the host of "
"the URL address is an IP address."
msgstr "设置查询时使用的HTTP主机,当URL地址的host是IP地址时,使用此参数。"

msgid "Sets the server name indication for query. '-' for disable SNI name."
msgstr "设置服务器SNI名称,‘-’表示禁用SNI名称。"

msgid "Settings"
msgstr "设置"

msgid "Skip Address Rules"
msgstr "跳过address规则"

msgid "Skip Cache"
msgstr "跳过cache"

msgid "Skip Cache."
msgstr "跳过cache。"

msgid "Skip Dualstack Selection"
msgstr "跳过双栈优选"

msgid "Skip Dualstack Selection."
msgstr "跳过双栈优选。"

msgid "Skip IP Alias"
msgstr "跳过IP别名"

msgid "Skip Ipset Rule"
msgstr "跳过ipset规则"

msgid "Skip Nameserver Rule"
msgstr "跳过Nameserver规则"

msgid "Skip SOA Address Rule"
msgstr "跳过address SOA(#)规则"

msgid "Skip SOA address rules."
msgstr "跳过address SOA(#)规则。"

msgid "Skip Speed Check"
msgstr "跳过测速"

msgid "Skip address rules."
msgstr "跳过address规则。"

msgid "Skip ipset rules."
msgstr "跳过ipset规则。"

msgid "Skip nameserver rules."
msgstr "跳过Nameserver规则。"

msgid "SmartDNS"
msgstr "SmartDNS"

msgid "Smartdns DOH server port."
msgstr "Smartdns DOH服务器端口号。

msgid "Smartdns DOT server port."
msgstr "Smartdns DOT服务器端口号。"

msgid "SmartDNS Server"
msgstr "SmartDNS 服务器"

msgid ""
"SmartDNS is a local high-performance DNS server, supports finding fastest "
"IP, supports ad filtering, and supports avoiding DNS poisoning."
msgstr "SmartDNS是一个本地高性能DNS服务器,支持返回最快IP,支持广告过滤。"

msgid "SmartDNS official website"
msgstr "SmartDNS官方网站"

msgid "Smartdns local server port"
msgstr "SmartDNS本地服务端口"

msgid ""
"Smartdns local server port, smartdns will be automatically set as main dns "
"when the port is 53."
msgstr ""
"SmartDNS本地服务端口,当端口号设置为53时,smartdns将会自动配置为主dns。"

msgid ""
"Smartdns response mode, First Ping: return the first ping IP, Fastest IP: "
"return the fastest IP, Fastest Response: return the fastest DNS response."
msgstr ""
"SmartDNS响应模式,最快PING: 返回最早有ping结果的IP,速度适中;最快IP: 返回"
"最快IP,查询请求可能延长; 最快响应:返回最快响应的结果,查询请求时间短。"

msgid "Smartdns server name"
msgstr "SmartDNS的服务器名称,默认为smartdns,留空为主机名"

msgid "Smartdns speed check mode."
msgstr "SmartDNS测速模式。"

msgid ""
"Specify an IP address to return for any host in the given domains, Queries "
"in the domains are never forwarded and always replied to with the specified "
"IP address which may be IPv4 or IPv6."
msgstr ""
"配置特定域名返回特定的IP地址,域名查询将不到上游服务器请求,直接返回配置的IP"
"地址,可用于广告屏蔽。"

msgid "Speed Check Mode"
msgstr "测速模式"

msgid "Speed check mode is invalid."
msgstr "测速模式无效。"

msgid "TCP Server"
msgstr "TCP服务器"

msgid "TCP port is empty"
msgstr "TCP端口号为空"

msgid "TLS Hostname Verify"
msgstr "校验TLS主机名"

msgid "TLS SNI name"
msgstr "TLS SNI名称"

msgid "TLS SPKI Pinning"
msgstr "TLS SPKI 指纹"

msgid "TTL for all domain result."
msgstr "设置所有域名的 TTL 值。"

msgid "Technical Support"
msgstr "技术支持"

msgid "URL"
msgstr "URL"

msgid "URL format error, format: http:// or https://"
msgstr "URL格式错误,格式:http://或https://"

msgid "Update"
msgstr "更新"

msgid "Update Files"
msgstr "更新文件"

msgid "Upload client address file, same as Client Address function."
msgstr "上传客户端地址文件,与客户端地址功能相同。"

msgid "Upload Config File"
msgstr "上传配置文件"

msgid "Upload Domain List File"
msgstr "上传域名列表文件"

msgid "Upload domain list file to /etc/smartdns/domain-set"
msgstr "上传域名列表文件到/etc/smartdns/domain-set"

msgid ""
"Upload domain list file, or configure auto download from Download File "
"Setting page."
msgstr "上传域名列表文件,或在下载文件设置页面设置自动下载。"

msgid "Upload domain list file."
msgstr "上传域名列表文件"

msgid "Upload File"
msgstr "上传文件"

msgid "Upload IP set file."
msgstr "上传IP集合列表文件。"

msgid "Upload smartdns config file to /etc/smartdns/conf.d"
msgstr "上传配置文件到/etc/smartdns/conf.d"

msgid "Upstream DNS Server Configuration"
msgstr "上游DNS服务器配置"

msgid "Upstream Servers"
msgstr "上游服务器"

msgid ""
"Upstream Servers, support UDP, TCP protocol. Please configure multiple DNS "
"servers, including multiple foreign DNS servers."
msgstr ""
"上游 DNS 服务器,支持 UDP,TCP 协议。请配置多个上游 DNS 服务器
Download .txt
gitextract_d_s45j8t/

├── .clang-format
├── .clang-tidy
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── feature.md
│   │   └── issue.md
│   └── workflows/
│       ├── c-cpp.yml
│       ├── docker.yml
│       └── webui.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── Makefile
├── ReadMe.md
├── ReadMe_en.md
├── doc/
│   └── architecture.vsdx
├── etc/
│   ├── default/
│   │   └── smartdns
│   ├── init.d/
│   │   └── smartdns
│   └── smartdns/
│       └── smartdns.conf
├── package/
│   ├── build-pkg.sh
│   ├── copy-smartdns.sh
│   ├── debian/
│   │   ├── DEBIAN/
│   │   │   ├── changelog
│   │   │   ├── compat
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── copyright
│   │   │   ├── prerm
│   │   │   └── rules
│   │   └── make.sh
│   ├── linux/
│   │   ├── install
│   │   └── make.sh
│   ├── luci/
│   │   ├── control/
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── debian-binary
│   │   ├── files/
│   │   │   ├── luci/
│   │   │   │   └── i18n/
│   │   │   │       └── smartdns.zh-cn.po
│   │   │   └── root/
│   │   │       ├── usr/
│   │   │       │   └── share/
│   │   │       │       ├── luci/
│   │   │       │       │   └── menu.d/
│   │   │       │       │       └── luci-app-smartdns.json
│   │   │       │       └── rpcd/
│   │   │       │           └── acl.d/
│   │   │       │               └── luci-app-smartdns.json
│   │   │       └── www/
│   │   │           └── luci-static/
│   │   │               └── resources/
│   │   │                   └── view/
│   │   │                       └── smartdns/
│   │   │                           └── smartdns.js
│   │   └── make.sh
│   ├── luci-compat/
│   │   ├── control/
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── debian-binary
│   │   ├── files/
│   │   │   ├── etc/
│   │   │   │   └── uci-defaults/
│   │   │   │       └── 50_luci-smartdns
│   │   │   ├── luci/
│   │   │   │   ├── controller/
│   │   │   │   │   └── smartdns.lua
│   │   │   │   ├── i18n/
│   │   │   │   │   └── smartdns.zh-cn.po
│   │   │   │   ├── model/
│   │   │   │   │   ├── cbi/
│   │   │   │   │   │   └── smartdns/
│   │   │   │   │   │       ├── smartdns.lua
│   │   │   │   │   │       └── upstream.lua
│   │   │   │   │   └── smartdns.lua
│   │   │   │   └── view/
│   │   │   │       └── smartdns/
│   │   │   │           └── smartdns_status.htm
│   │   │   └── usr/
│   │   │       └── share/
│   │   │           └── rpcd/
│   │   │               └── acl.d/
│   │   │                   └── luci-app-smartdns.json
│   │   └── make.sh
│   ├── luci-lite/
│   │   ├── control/
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── debian-binary
│   │   ├── files/
│   │   │   ├── luci/
│   │   │   │   └── i18n/
│   │   │   │       └── smartdns-lite.zh-cn.po
│   │   │   └── root/
│   │   │       ├── etc/
│   │   │       │   ├── config/
│   │   │       │   │   └── smartdns-lite
│   │   │       │   └── init.d/
│   │   │       │       └── smartdns-lite
│   │   │       ├── usr/
│   │   │       │   └── share/
│   │   │       │       ├── luci/
│   │   │       │       │   └── menu.d/
│   │   │       │       │       └── luci-app-smartdns-lite.json
│   │   │       │       └── rpcd/
│   │   │       │           └── acl.d/
│   │   │       │               └── luci-app-smartdns-lite.json
│   │   │       └── www/
│   │   │           └── luci-static/
│   │   │               └── resources/
│   │   │                   └── view/
│   │   │                       └── smartdns-lite/
│   │   │                           └── smartdns-lite.js
│   │   └── make.sh
│   ├── openwrt/
│   │   ├── Makefile
│   │   ├── address.conf
│   │   ├── blacklist-ip.conf
│   │   ├── control/
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── custom.conf
│   │   ├── debian-binary
│   │   ├── domain-block.list
│   │   ├── domain-forwarding.list
│   │   ├── files/
│   │   │   └── etc/
│   │   │       ├── config/
│   │   │       │   └── smartdns
│   │   │       └── init.d/
│   │   │           └── smartdns
│   │   └── make.sh
│   ├── optware/
│   │   ├── S50smartdns
│   │   ├── control/
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   ├── debian-binary
│   │   ├── make.sh
│   │   └── smartdns-opt.conf
│   ├── redhat/
│   │   └── smartdns.spec
│   ├── run-smartdns
│   ├── tool/
│   │   └── po2lmo/
│   │       ├── Makefile
│   │       └── src/
│   │           ├── po2lmo.c
│   │           ├── template_lmo.c
│   │           └── template_lmo.h
│   └── windows/
│       ├── install.bat
│       ├── reload.bat
│       ├── uninstall.bat
│       └── wsl-run.vbs
├── plugin/
│   ├── demo/
│   │   ├── .gitignore
│   │   ├── Makefile
│   │   ├── demo.c
│   │   └── demo.h
│   └── smartdns-ui/
│       ├── .gitignore
│       ├── Cargo.toml
│       ├── Makefile
│       ├── build.rs
│       ├── src/
│       │   ├── data_server.rs
│       │   ├── data_stats.rs
│       │   ├── data_upstream_server.rs
│       │   ├── db.rs
│       │   ├── http_api_msg.rs
│       │   ├── http_error.rs
│       │   ├── http_jwt.rs
│       │   ├── http_server.rs
│       │   ├── http_server_api.rs
│       │   ├── http_server_stream.rs
│       │   ├── lib.rs
│       │   ├── plugin.rs
│       │   ├── server_log.rs
│       │   ├── smartdns.rs
│       │   ├── utils.rs
│       │   └── whois.rs
│       └── tests/
│           ├── common/
│           │   ├── client.rs
│           │   ├── mod.rs
│           │   └── server.rs
│           ├── httpserver_test.rs
│           └── restapi_test.rs
├── src/
│   ├── .gitignore
│   ├── Makefile
│   ├── dns.c
│   ├── dns_cache.c
│   ├── dns_client/
│   │   ├── client_http2.c
│   │   ├── client_http2.h
│   │   ├── client_http3.c
│   │   ├── client_http3.h
│   │   ├── client_https.c
│   │   ├── client_https.h
│   │   ├── client_mdns.c
│   │   ├── client_mdns.h
│   │   ├── client_quic.c
│   │   ├── client_quic.h
│   │   ├── client_socket.c
│   │   ├── client_socket.h
│   │   ├── client_tcp.c
│   │   ├── client_tcp.h
│   │   ├── client_tls.c
│   │   ├── client_tls.h
│   │   ├── client_udp.c
│   │   ├── client_udp.h
│   │   ├── conn_stream.c
│   │   ├── conn_stream.h
│   │   ├── dns_client.c
│   │   ├── dns_client.h
│   │   ├── ecs.c
│   │   ├── ecs.h
│   │   ├── group.c
│   │   ├── group.h
│   │   ├── packet.c
│   │   ├── packet.h
│   │   ├── pending_server.c
│   │   ├── pending_server.h
│   │   ├── proxy.c
│   │   ├── proxy.h
│   │   ├── query.c
│   │   ├── query.h
│   │   ├── server_info.c
│   │   ├── server_info.h
│   │   ├── wake_event.c
│   │   └── wake_event.h
│   ├── dns_conf/
│   │   ├── address.c
│   │   ├── address.h
│   │   ├── bind.c
│   │   ├── bind.h
│   │   ├── bootstrap_dns.c
│   │   ├── bootstrap_dns.h
│   │   ├── client_rule.c
│   │   ├── client_rule.h
│   │   ├── client_subnet.c
│   │   ├── client_subnet.h
│   │   ├── cname.c
│   │   ├── cname.h
│   │   ├── conf_file.c
│   │   ├── conf_file.h
│   │   ├── ddns_domain.c
│   │   ├── ddns_domain.h
│   │   ├── dhcp_lease_dnsmasq.c
│   │   ├── dhcp_lease_dnsmasq.h
│   │   ├── dns64.c
│   │   ├── dns64.h
│   │   ├── dns_conf.c
│   │   ├── dns_conf.h
│   │   ├── dns_conf_group.c
│   │   ├── dns_conf_group.h
│   │   ├── domain_rule.c
│   │   ├── domain_rule.h
│   │   ├── domain_set.c
│   │   ├── domain_set.h
│   │   ├── get_domain.c
│   │   ├── get_domain.h
│   │   ├── group.c
│   │   ├── group.h
│   │   ├── host_file.c
│   │   ├── host_file.h
│   │   ├── https_record.c
│   │   ├── https_record.h
│   │   ├── ip_alias.c
│   │   ├── ip_alias.h
│   │   ├── ip_rule.c
│   │   ├── ip_rule.h
│   │   ├── ip_set.c
│   │   ├── ip_set.h
│   │   ├── ipset.c
│   │   ├── ipset.h
│   │   ├── local_domain.c
│   │   ├── local_domain.h
│   │   ├── nameserver.c
│   │   ├── nameserver.h
│   │   ├── nftset.c
│   │   ├── nftset.h
│   │   ├── plugin.c
│   │   ├── plugin.h
│   │   ├── proxy_names.c
│   │   ├── proxy_names.h
│   │   ├── proxy_server.c
│   │   ├── proxy_server.h
│   │   ├── ptr.c
│   │   ├── ptr.h
│   │   ├── qtype_soa.c
│   │   ├── qtype_soa.h
│   │   ├── server.c
│   │   ├── server.h
│   │   ├── server_group.c
│   │   ├── server_group.h
│   │   ├── set_file.c
│   │   ├── set_file.h
│   │   ├── smartdns_domain.c
│   │   ├── smartdns_domain.h
│   │   ├── speed_check_mode.c
│   │   ├── speed_check_mode.h
│   │   ├── srv_record.c
│   │   └── srv_record.h
│   ├── dns_plugin.c
│   ├── dns_server/
│   │   ├── address.c
│   │   ├── address.h
│   │   ├── answer.c
│   │   ├── answer.h
│   │   ├── audit.c
│   │   ├── audit.h
│   │   ├── cache.c
│   │   ├── cache.h
│   │   ├── client_rule.c
│   │   ├── client_rule.h
│   │   ├── cname.c
│   │   ├── cname.h
│   │   ├── connection.c
│   │   ├── connection.h
│   │   ├── context.c
│   │   ├── context.h
│   │   ├── ddr.c
│   │   ├── ddr.h
│   │   ├── dns64.c
│   │   ├── dns64.h
│   │   ├── dns_server.c
│   │   ├── dns_server.h
│   │   ├── dualstack.c
│   │   ├── dualstack.h
│   │   ├── ip_rule.c
│   │   ├── ip_rule.h
│   │   ├── ipset_nftset.c
│   │   ├── ipset_nftset.h
│   │   ├── local_addr.c
│   │   ├── local_addr.h
│   │   ├── mdns.c
│   │   ├── mdns.h
│   │   ├── neighbor.c
│   │   ├── neighbor.h
│   │   ├── prefetch.c
│   │   ├── prefetch.h
│   │   ├── ptr.c
│   │   ├── ptr.h
│   │   ├── request.c
│   │   ├── request.h
│   │   ├── request_pending.c
│   │   ├── request_pending.h
│   │   ├── rules.c
│   │   ├── rules.h
│   │   ├── server_http2.c
│   │   ├── server_http2.h
│   │   ├── server_https.c
│   │   ├── server_https.h
│   │   ├── server_socket.c
│   │   ├── server_socket.h
│   │   ├── server_tcp.c
│   │   ├── server_tcp.h
│   │   ├── server_tls.c
│   │   ├── server_tls.h
│   │   ├── server_udp.c
│   │   ├── server_udp.h
│   │   ├── soa.c
│   │   ├── soa.h
│   │   ├── speed_check.c
│   │   └── speed_check.h
│   ├── dns_stats.c
│   ├── fast_ping/
│   │   ├── fast_ping.c
│   │   ├── fast_ping.h
│   │   ├── notify_event.c
│   │   ├── notify_event.h
│   │   ├── ping_fake.c
│   │   ├── ping_fake.h
│   │   ├── ping_host.c
│   │   ├── ping_host.h
│   │   ├── ping_icmp.c
│   │   ├── ping_icmp.h
│   │   ├── ping_icmp6.c
│   │   ├── ping_icmp6.h
│   │   ├── ping_tcp.c
│   │   ├── ping_tcp.h
│   │   ├── ping_tcp_syn.c
│   │   ├── ping_tcp_syn.h
│   │   ├── ping_udp.c
│   │   ├── ping_udp.h
│   │   ├── wakeup_event.c
│   │   └── wakeup_event.h
│   ├── http_parse/
│   │   ├── hpack.c
│   │   ├── hpack.h
│   │   ├── http1_parse.c
│   │   ├── http1_parse.h
│   │   ├── http2.c
│   │   ├── http3_parse.c
│   │   ├── http3_parse.h
│   │   ├── http_parse.c
│   │   ├── http_parse.h
│   │   ├── qpack.c
│   │   └── qpack.h
│   ├── lib/
│   │   ├── art.c
│   │   ├── bitops.c
│   │   ├── conf.c
│   │   ├── idna.c
│   │   ├── radix.c
│   │   ├── rbtree.c
│   │   ├── stringutil.c
│   │   └── timer_wheel.c
│   ├── main.c
│   ├── proxy.c
│   ├── smartdns.c
│   ├── timer.c
│   ├── tlog.c
│   └── utils/
│       ├── alpn.c
│       ├── capbility.c
│       ├── daemon.c
│       ├── dns_debug.c
│       ├── ipset.c
│       ├── misc.c
│       ├── neighbors.c
│       ├── net.c
│       ├── nftset.c
│       ├── ssl.c
│       ├── stack.c
│       ├── tls_header_parse.c
│       └── url.c
├── systemd/
│   └── smartdns.service.in
└── test/
    ├── Makefile
    ├── cases/
    │   ├── test-address.cc
    │   ├── test-audit.cc
    │   ├── test-bind.cc
    │   ├── test-bootstrap.cc
    │   ├── test-cache.cc
    │   ├── test-client-rule.cc
    │   ├── test-cname.cc
    │   ├── test-ddns.cc
    │   ├── test-ddr.cc
    │   ├── test-discard-block-ip.cc
    │   ├── test-dns64.cc
    │   ├── test-domain-rule.cc
    │   ├── test-domain-set.cc
    │   ├── test-dualstack.cc
    │   ├── test-edns.cc
    │   ├── test-group.cc
    │   ├── test-hosts.cc
    │   ├── test-http.cc
    │   ├── test-http2.cc
    │   ├── test-https.cc
    │   ├── test-idna.cc
    │   ├── test-ip-alias.cc
    │   ├── test-ip-rule.cc
    │   ├── test-lib-http2.cc
    │   ├── test-local-domain.cc
    │   ├── test-mdns.cc
    │   ├── test-mock-server.cc
    │   ├── test-nameserver.cc
    │   ├── test-perf.cc
    │   ├── test-ping.cc
    │   ├── test-ptr.cc
    │   ├── test-qtype-soa.cc
    │   ├── test-rule.cc
    │   ├── test-same-pending-query.cc
    │   ├── test-server.cc
    │   ├── test-speed-check.cc
    │   ├── test-srv.cc
    │   ├── test-stress.cc
    │   └── test-subnet.cc
    ├── client.cc
    ├── client.h
    ├── include/
    │   └── utils.h
    ├── server.cc
    ├── server.h
    ├── test.cc
    └── utils.cc
Download .txt
Showing preview only (281K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3220 symbols across 273 files)

FILE: package/luci-lite/files/root/www/luci-static/resources/view/smartdns-lite/smartdns-lite.js
  function getServiceStatus (line 38) | function getServiceStatus() {
  function smartdnsServiceStatus (line 51) | function smartdnsServiceStatus() {
  function smartdnsRenderStatus (line 57) | function smartdnsRenderStatus(res) {

FILE: package/luci/files/root/www/luci-static/resources/view/smartdns/smartdns.js
  function getServiceStatus (line 38) | function getServiceStatus() {
  function smartdnsServiceStatus (line 49) | function smartdnsServiceStatus() {
  function smartdnsRenderStatus (line 55) | function smartdnsRenderStatus(res) {

FILE: package/tool/po2lmo/src/po2lmo.c
  function die (line 21) | static void die(const char *msg)
  function usage (line 27) | static void usage(const char *name)
  function print (line 33) | static void print(const void *ptr, size_t size, size_t nmemb, FILE *stream)
  function extract_string (line 39) | static int extract_string(const char *src, char *dest, int len)
  function cmp_index (line 85) | static int cmp_index(const void *a, const void *b)
  function print_uint32 (line 98) | static void print_uint32(uint32_t x, FILE *out)
  function print_index (line 104) | static void print_index(void *array, int n, FILE *out)
  function main (line 119) | int main(int argc, char *argv[])

FILE: package/tool/po2lmo/src/template_lmo.c
  function sfh_hash (line 26) | uint32_t sfh_hash(const char *data, int len)
  function lmo_canon_hash (line 72) | uint32_t lmo_canon_hash(const char *str, int len)
  function lmo_archive_t (line 100) | lmo_archive_t * lmo_open(const char *file)
  function lmo_close (line 154) | void lmo_close(lmo_archive_t *ar)
  function lmo_load_catalog (line 172) | int lmo_load_catalog(const char *lang, const char *dir)
  function lmo_change_catalog (line 228) | int lmo_change_catalog(const char *lang)
  function lmo_entry_t (line 244) | static lmo_entry_t * lmo_find_entry(lmo_archive_t *ar, uint32_t hash)
  function lmo_translate (line 280) | int lmo_translate(const char *key, int keylen, char **out, int *outlen)
  function lmo_close_catalog (line 304) | void lmo_close_catalog(const char *lang)

FILE: package/tool/po2lmo/src/template_lmo.h
  type lmo_entry (line 45) | struct lmo_entry {
  type lmo_entry_t (line 52) | typedef struct lmo_entry lmo_entry_t;
  type lmo_archive (line 55) | struct lmo_archive {
  type lmo_archive_t (line 65) | typedef struct lmo_archive lmo_archive_t;
  type lmo_catalog (line 68) | struct lmo_catalog {
  type lmo_catalog_t (line 74) | typedef struct lmo_catalog lmo_catalog_t;

FILE: plugin/demo/demo.c
  function demo_server_recv (line 10) | static int demo_server_recv(struct dns_packet *packet, unsigned char *in...
  function demo_server_request_complete (line 19) | static void demo_server_request_complete(struct dns_request *request)
  type smartdns_operations (line 24) | struct smartdns_operations
  function dns_plugin_init (line 29) | int dns_plugin_init(struct dns_plugin *plugin)
  function dns_plugin_exit (line 44) | int dns_plugin_exit(struct dns_plugin *plugin)
  function dns_plugin_api_version (line 51) | int dns_plugin_api_version(void)

FILE: plugin/smartdns-ui/build.rs
  type IgnoreMacros (line 6) | struct IgnoreMacros(HashSet<String>);
    method will_parse_macro (line 9) | fn will_parse_macro(&self, name: &str) -> bindgen::callbacks::MacroPar...
  function get_git_commit_version (line 18) | fn get_git_commit_version() {
  function link_rename_lib (line 32) | fn link_rename_lib() {
  function link_smartdns_lib (line 52) | fn link_smartdns_lib() {
  function main (line 102) | fn main() {

FILE: plugin/smartdns-ui/src/data_server.rs
  constant DEFAULT_MAX_LOG_AGE (line 44) | pub const DEFAULT_MAX_LOG_AGE: u64 = 30 * 24 * 60 * 60;
  constant DEFAULT_MAX_LOG_AGE_MS (line 45) | pub const DEFAULT_MAX_LOG_AGE_MS: u64 = DEFAULT_MAX_LOG_AGE * 1000;
  constant MAX_LOG_AGE_VALUE_MIN (line 46) | pub const MAX_LOG_AGE_VALUE_MIN: u64 = 600;
  constant MAX_LOG_AGE_VALUE_MAX (line 47) | pub const MAX_LOG_AGE_VALUE_MAX: u64 = 365 * 24 * 60 * 60 * 10;
  constant MIN_FREE_DISK_SPACE (line 48) | pub const MIN_FREE_DISK_SPACE: u64 = 1024 * 1024 * 8;
  constant DB_FILE_NAME (line 49) | pub const DB_FILE_NAME: &str = "smartdns.db";
  type OverviewData (line 52) | pub struct OverviewData {
  type MetricsData (line 61) | pub struct MetricsData {
  type DataServerConfig (line 76) | pub struct DataServerConfig {
    method new (line 83) | pub fn new() -> Self {
    method load_config (line 91) | pub fn load_config(&mut self, data_server: Arc<DataServer>) -> Result<...
  type DataServerControl (line 116) | pub struct DataServerControl {
    method new (line 125) | pub fn new() -> Self {
    method get_data_server (line 135) | pub fn get_data_server(&self) -> Arc<DataServer> {
    method set_plugin (line 139) | pub fn set_plugin(&self, plugin: Arc<SmartdnsPlugin>) {
    method get_plugin (line 143) | pub fn get_plugin(&self) -> Result<Arc<SmartdnsPlugin>, Box<dyn Error>> {
    method init_db (line 155) | pub fn init_db(&self, conf: &DataServerConfig) -> Result<(), Box<dyn E...
    method start_data_server (line 166) | pub fn start_data_server(&self) -> Result<(), Box<dyn Error>> {
    method stop_data_server (line 192) | pub fn stop_data_server(&self) {
    method send_request (line 221) | pub fn send_request(&self, request: Box<dyn DnsRequest>) -> Result<(),...
    method server_log (line 242) | pub fn server_log(&self, level: LogLevel, msg: &str, msg_len: i32) {
    method server_audit_log (line 246) | pub fn server_audit_log(&self, msg: &str, msg_len: i32) {
  method drop (line 252) | fn drop(&mut self) {
  type DataServer (line 257) | pub struct DataServer {
    method new (line 277) | pub fn new() -> Self {
    method get_recv_in_batch (line 310) | pub fn get_recv_in_batch(&self) -> bool {
    method set_recv_in_batch (line 314) | pub fn set_recv_in_batch(&self, recv_in_batch: bool) {
    method init_server (line 318) | fn init_server(&self, conf: &DataServerConfig) -> Result<(), Box<dyn E...
    method set_plugin (line 347) | pub fn set_plugin(&self, plugin: Arc<SmartdnsPlugin>) {
    method get_plugin (line 351) | pub fn get_plugin(&self) -> Result<Arc<SmartdnsPlugin>, Box<dyn Error>> {
    method get_data_server_config (line 363) | pub fn get_data_server_config(&self) -> DataServerConfig {
    method get_config (line 368) | pub fn get_config(&self, key: &str) -> Option<String> {
    method get_server_config_from_file (line 377) | pub fn get_server_config_from_file(&self, key: &str) -> Option<String> {
    method get_server_config (line 386) | pub fn get_server_config(&self, key: &str) -> Option<String> {
    method whois (line 400) | pub async fn whois(&self, domain: &str) -> Result<WhoIsInfo, Box<dyn E...
    method get_config_list (line 404) | pub fn get_config_list(&self) -> Result<HashMap<String, String>, Box<d...
    method set_config (line 408) | pub fn set_config(&self, key: &str, value: &str) -> Result<(), Box<dyn...
    method get_upstream_server_list (line 412) | pub fn get_upstream_server_list(&self) -> Result<Vec<UpstreamServerInf...
    method get_domain_list (line 417) | pub fn get_domain_list(
    method get_domain_list_count (line 424) | pub fn get_domain_list_count(&self) -> u64 {
    method delete_domain_by_id (line 428) | pub fn delete_domain_by_id(&self, id: u64) -> Result<u64, Box<dyn Erro...
    method delete_domain_before_timestamp (line 432) | pub fn delete_domain_before_timestamp(&self, timestamp: u64) -> Result...
    method delete_client_by_id (line 436) | pub fn delete_client_by_id(&self, id: u64) -> Result<u64, Box<dyn Erro...
    method get_client_list (line 440) | pub fn get_client_list(
    method get_top_client_top_list (line 447) | pub fn get_top_client_top_list(
    method get_top_domain_top_list (line 454) | pub fn get_top_domain_top_list(
    method get_hourly_query_count (line 461) | pub fn get_hourly_query_count(
    method get_daily_query_count (line 468) | pub fn get_daily_query_count(
    method get_stat (line 475) | pub fn get_stat(&self) -> Arc<DataStats> {
    method get_metrics (line 479) | pub fn get_metrics(&self) -> Result<MetricsData, Box<dyn Error + Send>> {
    method is_handle_request_disabled (line 497) | pub fn is_handle_request_disabled(&self) -> bool {
    method get_free_disk_space (line 502) | pub fn get_free_disk_space(&self) -> u64 {
    method get_overview (line 506) | pub fn get_overview(&self) -> Result<OverviewData, Box<dyn Error + Sen...
    method insert_client_by_list (line 518) | pub fn insert_client_by_list(&self, data: &Vec<ClientData>) -> Result<...
    method insert_domain_by_list (line 522) | pub fn insert_domain_by_list(&self, data: &Vec<DomainData>) -> Result<...
    method insert_domain (line 526) | pub fn insert_domain(&self, data: &DomainData) -> Result<(), Box<dyn E...
    method data_server_handle_dns_request (line 540) | async fn data_server_handle_dns_request(
    method get_log_stream (line 693) | pub async fn get_log_stream(&self) -> mpsc::Receiver<ServerLogMsg> {
    method server_log (line 697) | pub fn server_log(&self, level: LogLevel, msg: &str, msg_len: i32) {
    method get_audit_log_stream (line 701) | pub async fn get_audit_log_stream(&self) -> mpsc::Receiver<ServerAudit...
    method server_audit_log (line 705) | pub fn server_audit_log(&self, msg: &str, msg_len: i32) {
    method server_check (line 709) | fn server_check(&self) {
    method data_server_loop (line 742) | async fn data_server_loop(this: Arc<DataServer>) -> Result<(), Box<dyn...
    method stop_data_server (line 876) | fn stop_data_server(&self) {
    method call_blocking (line 895) | async fn call_blocking<F, R>(

FILE: plugin/smartdns-ui/src/data_stats.rs
  type DataStatsItem (line 39) | struct DataStatsItem {
    method new (line 59) | pub fn new() -> Self {
    method get_qps (line 82) | pub fn get_qps(&self) -> u32 {
    method add_qps_count (line 86) | pub fn add_qps_count(&self, count: u32) {
    method update_qps (line 90) | pub fn update_qps(&self) {
    method add_request_drop (line 95) | pub fn add_request_drop(&self, count: u64) {
    method get_request_drop (line 108) | pub fn get_request_drop(&self) -> u64 {
    method get_total_request (line 121) | pub fn get_total_request(&self) -> u64 {
    method add_total_request (line 134) | pub fn add_total_request(&self, total: u64) {
    method get_total_blocked_request (line 147) | pub fn get_total_blocked_request(&self) -> u64 {
    method add_total_blocked_request (line 160) | pub fn add_total_blocked_request(&self, total: u64) {
    method add_total_failed_request (line 174) | pub fn add_total_failed_request(&self, total: u64) {
    method get_total_failed_request (line 188) | pub fn get_total_failed_request(&self) -> u64 {
    method get_current_hour_total (line 202) | pub fn get_current_hour_total(&self) -> u64 {
  type DataStatsItem (line 49) | struct DataStatsItem {
    method new (line 59) | pub fn new() -> Self {
    method get_qps (line 82) | pub fn get_qps(&self) -> u32 {
    method add_qps_count (line 86) | pub fn add_qps_count(&self, count: u32) {
    method update_qps (line 90) | pub fn update_qps(&self) {
    method add_request_drop (line 95) | pub fn add_request_drop(&self, count: u64) {
    method get_request_drop (line 108) | pub fn get_request_drop(&self) -> u64 {
    method get_total_request (line 121) | pub fn get_total_request(&self) -> u64 {
    method add_total_request (line 134) | pub fn add_total_request(&self, total: u64) {
    method get_total_blocked_request (line 147) | pub fn get_total_blocked_request(&self) -> u64 {
    method add_total_blocked_request (line 160) | pub fn add_total_blocked_request(&self, total: u64) {
    method add_total_failed_request (line 174) | pub fn add_total_failed_request(&self, total: u64) {
    method get_total_failed_request (line 188) | pub fn get_total_failed_request(&self) -> u64 {
    method get_current_hour_total (line 202) | pub fn get_current_hour_total(&self) -> u64 {
  type DataStats (line 207) | pub struct DataStats {
    method new (line 219) | pub fn new(db: Arc<crate::db::DB>, conf: Arc<RwLock<DataServerConfig>>...
    method get_qps (line 234) | pub fn get_qps(&self) -> u32 {
    method add_qps_count (line 238) | pub fn add_qps_count(&self, count: u32) {
    method update_qps (line 242) | pub fn update_qps(&self) {
    method add_request_drop (line 246) | pub fn add_request_drop(&self, count: u64) {
    method get_request_drop (line 250) | pub fn get_request_drop(&self) -> u64 {
    method get_total_blocked_request (line 254) | pub fn get_total_blocked_request(&self) -> u64 {
    method add_total_blocked_request (line 258) | pub fn add_total_blocked_request(&self, total: u64) {
    method get_total_failed_request (line 262) | pub fn get_total_failed_request(&self) -> u64 {
    method add_total_failed_request (line 266) | pub fn add_total_failed_request(&self, total: u64) {
    method get_total_request (line 270) | pub fn get_total_request(&self) -> u64 {
    method get_current_hour_total (line 274) | pub fn get_current_hour_total(&self) -> u64 {
    method add_total_request (line 278) | pub fn add_total_request(&self, total: u64) {
    method get_memory_usage (line 282) | pub fn get_memory_usage(&self) -> u64 {
    method init (line 305) | pub fn init(self: &Arc<Self>) -> Result<(), Box<dyn Error>> {
    method load_status_data (line 311) | pub fn load_status_data(self: &Arc<Self>) -> Result<(), Box<dyn Error>> {
    method save_status_data (line 385) | pub fn save_status_data(self: &Arc<Self>) -> Result<(), Box<dyn Error>> {
    method start_worker (line 406) | pub fn start_worker(self: &Arc<Self>) -> Result<(), Box<dyn Error>> {
    method refresh (line 417) | pub fn refresh(self: &Arc<Self>) {
    method update_stats (line 452) | async fn update_stats(self: &Arc<Self>) {
    method worker_loop (line 467) | async fn worker_loop(this: &Arc<Self>) {
    method stop_worker (line 501) | pub fn stop_worker(&self) {
  method drop (line 522) | fn drop(&mut self) {

FILE: plugin/smartdns-ui/src/data_upstream_server.rs
  type UpstreamServerInfo (line 22) | pub struct UpstreamServerInfo {
    method get_all (line 37) | pub fn get_all() -> Result<Vec<UpstreamServerInfo>, Box<dyn std::error...

FILE: plugin/smartdns-ui/src/db.rs
  type DB (line 33) | pub struct DB {
    method new (line 204) | pub fn new() -> Self {
    method create_table (line 212) | fn create_table(&self, conn: &Connection) -> Result<()> {
    method migrate_db (line 318) | fn migrate_db(&self, _conn: &Connection) -> Result<(), Box<dyn Error>> {
    method init_db (line 325) | fn init_db(&self, conn: &Connection) -> Result<(), Box<dyn Error>> {
    method open (line 350) | pub fn open(&self, path: &str) -> Result<(), Box<dyn Error>> {
    method run_vacuum (line 411) | pub fn run_vacuum(&self, pages: Option<u32>) -> Result<(), Box<dyn Err...
    method set_config (line 439) | pub fn set_config(&self, key: &str, value: &str) -> Result<(), Box<dyn...
    method get_config_list (line 457) | pub fn get_config_list(&self) -> Result<HashMap<String, String>, Box<d...
    method set_status_data (line 484) | pub fn set_status_data(&self, key: &str, value: &str) -> Result<(), Bo...
    method get_status_data_list (line 502) | pub fn get_status_data_list(&self) -> Result<HashMap<String, String>, ...
    method debug_query_plan (line 533) | pub fn debug_query_plan(&self, conn: &Connection, sql: String, sql_par...
    method get_config (line 564) | pub fn get_config(&self, key: &str) -> Result<Option<String>, Box<dyn ...
    method update_domain_hourly_count (line 587) | pub fn update_domain_hourly_count(
    method update_domain_daily_count (line 608) | pub fn update_domain_daily_count(
    method insert_domain (line 629) | pub fn insert_domain(&self, data: &Vec<DomainData>) -> Result<(), Box<...
    method get_db_file_path (line 694) | pub fn get_db_file_path(&self) -> Option<String> {
    method get_readonly_conn (line 704) | pub fn get_readonly_conn(&self) -> Option<Connection> {
    method get_domain_sql_where (line 730) | pub fn get_domain_sql_where(
    method get_domain_list_count (line 935) | pub fn get_domain_list_count(&self, param: Option<&DomainListGetParam>...
    method delete_domain_by_id (line 965) | pub fn delete_domain_by_id(&self, id: u64) -> Result<u64, Box<dyn Erro...
    method delete_domain_before_timestamp (line 982) | pub fn delete_domain_before_timestamp(&self, timestamp: u64) -> Result...
    method refresh_client_top_list (line 1005) | pub fn refresh_client_top_list(&self, timestamp: u64) -> Result<(), Bo...
    method get_client_top_list (line 1068) | pub fn get_client_top_list(&self, count: u32) -> Result<Vec<ClientQuer...
    method delete_daily_query_count_before_timestamp (line 1098) | pub fn delete_daily_query_count_before_timestamp(
    method get_daily_query_count (line 1121) | pub fn get_daily_query_count(&self, past_days: u32) -> Result<DailyQue...
    method delete_hourly_query_count_before_timestamp (line 1163) | pub fn delete_hourly_query_count_before_timestamp(
    method get_hourly_query_count (line 1186) | pub fn get_hourly_query_count(
    method refresh_domain_top_list (line 1239) | pub fn refresh_domain_top_list(&self, timestamp: u64) -> Result<(), Bo...
    method get_domain_top_list (line 1293) | pub fn get_domain_top_list(&self, count: u32) -> Result<Vec<DomainQuer...
    method get_domain_list (line 1327) | pub fn get_domain_list(
    method insert_client (line 1436) | pub fn insert_client(&self, client_data: &Vec<ClientData>) -> Result<(...
    method get_client_list_count (line 1469) | pub fn get_client_list_count(&self, param: Option<&ClientListGetParam>...
    method get_client_sql_where (line 1499) | fn get_client_sql_where(
    method get_client_list (line 1645) | pub fn get_client_list(
    method delete_client_by_id (line 1746) | pub fn delete_client_by_id(&self, id: u64) -> Result<u64, Box<dyn Erro...
    method get_db_size (line 1763) | pub fn get_db_size(&self) -> u64 {
    method close (line 1788) | pub fn close(&self) {
  type ClientData (line 40) | pub struct ClientData {
  type ClientQueryCount (line 49) | pub struct ClientQueryCount {
  type DomainQueryCount (line 57) | pub struct DomainQueryCount {
  type HourlyQueryCountItem (line 65) | pub struct HourlyQueryCountItem {
  type HourlyQueryCount (line 71) | pub struct HourlyQueryCount {
  type DailyQueryCountItem (line 77) | pub struct DailyQueryCountItem {
  type DailyQueryCount (line 83) | pub struct DailyQueryCount {
  type DomainData (line 89) | pub struct DomainData {
  type QueryDomainListResult (line 104) | pub struct QueryDomainListResult {
  type DomainListGetParamCursor (line 111) | pub struct DomainListGetParamCursor {
  type QueryClientListResult (line 118) | pub struct QueryClientListResult {
  type ClientListGetParamCursor (line 125) | pub struct ClientListGetParamCursor {
  type ClientListGetParam (line 132) | pub struct ClientListGetParam {
    method new (line 146) | pub fn new() -> Self {
  type DomainListGetParam (line 163) | pub struct DomainListGetParam {
    method new (line 182) | pub fn new() -> Self {
  method drop (line 1801) | fn drop(&mut self) {

FILE: plugin/smartdns-ui/src/http_api_msg.rs
  type AuthUser (line 29) | pub struct AuthUser {
  type TokenResponse (line 35) | pub struct TokenResponse {
  function api_msg_parse_auth (line 40) | pub fn api_msg_parse_auth(data: &str) -> Result<AuthUser, Box<dyn Error>> {
  function api_msg_parse_auth_password_change (line 57) | pub fn api_msg_parse_auth_password_change(data: &str) -> Result<(String,...
  function api_msg_gen_auth_password_change (line 74) | pub fn api_msg_gen_auth_password_change(old_password: &str, password: &s...
  function api_msg_gen_auth_login (line 83) | pub fn api_msg_gen_auth_login(auth: &AuthUser) -> String {
  function api_msg_parse_count (line 92) | pub fn api_msg_parse_count(data: &str) -> Result<i64, Box<dyn Error>> {
  function api_msg_gen_count (line 102) | pub fn api_msg_gen_count(count: i64) -> String {
  function api_msg_parse_json_object_domain_value (line 110) | pub fn api_msg_parse_json_object_domain_value(
  function api_msg_parse_domain (line 183) | pub fn api_msg_parse_domain(data: &str) -> Result<DomainData, Box<dyn Er...
  function api_msg_gen_json_object_domain (line 188) | pub fn api_msg_gen_json_object_domain(domain: &DomainData) -> serde_json...
  function api_msg_gen_domain (line 204) | pub fn api_msg_gen_domain(domain: &DomainData) -> String {
  function api_msg_parse_domain_list (line 209) | pub fn api_msg_parse_domain_list(data: &str) -> Result<Vec<DomainData>, ...
  function api_msg_gen_domain_list (line 226) | pub fn api_msg_gen_domain_list(
  function api_msg_parse_client_list (line 249) | pub fn api_msg_parse_client_list(data: &str) -> Result<Vec<ClientData>, ...
  function api_msg_gen_json_object_client (line 297) | pub fn api_msg_gen_json_object_client(client: &ClientData) -> serde_json...
  function api_msg_gen_client_list (line 307) | pub fn api_msg_gen_client_list(
  function api_msg_auth_token (line 330) | pub fn api_msg_auth_token(token: &str, expired: &str) -> String {
  function api_msg_parse_auth_token (line 340) | pub fn api_msg_parse_auth_token(data: &str) -> Result<TokenResponse, Box...
  function api_msg_gen_cache_number (line 357) | pub fn api_msg_gen_cache_number(cache_number: i32) -> String {
  function api_msg_parse_cache_number (line 365) | pub fn api_msg_parse_cache_number(data: &str) -> Result<i32, Box<dyn Err...
  function api_msg_error (line 375) | pub fn api_msg_error(msg: &str) -> String {
  function api_msg_parse_error (line 383) | pub fn api_msg_parse_error(data: &str) -> Result<String, Box<dyn Error>> {
  function api_msg_parse_loglevel (line 393) | pub fn api_msg_parse_loglevel(data: &str) -> Result<LogLevel, Box<dyn Er...
  function api_msg_gen_loglevel (line 408) | pub fn api_msg_gen_loglevel(loglevel: LogLevel) -> String {
  function api_msg_gen_version (line 417) | pub fn api_msg_gen_version(smartdns_version: &str, ui_version: &str) -> ...
  function api_msg_gen_upstream_server_list (line 426) | pub fn api_msg_gen_upstream_server_list(upstream_server_list: &Vec<Upstr...
  function api_msg_parse_upstream_server_list (line 453) | pub fn api_msg_parse_upstream_server_list(
  function api_msg_parse_version (line 537) | pub fn api_msg_parse_version(data: &str) -> Result<(String, String), Box...
  function api_msg_gen_key_value (line 551) | pub fn api_msg_gen_key_value(data: &HashMap<String, String>) -> String {
  function api_msg_parse_key_value (line 561) | pub fn api_msg_parse_key_value(data: &str) -> Result<HashMap<String, Str...
  function api_msg_gen_top_client_list (line 576) | pub fn api_msg_gen_top_client_list(client_list: &Vec<ClientQueryCount>) ...
  function api_msg_parse_top_client_list (line 596) | pub fn api_msg_parse_top_client_list(data: &str) -> Result<Vec<ClientQue...
  function api_msg_gen_top_domain_list (line 636) | pub fn api_msg_gen_top_domain_list(domain_list: &Vec<DomainQueryCount>) ...
  function api_msg_parse_top_domain_list (line 656) | pub fn api_msg_parse_top_domain_list(data: &str) -> Result<Vec<DomainQue...
  function api_msg_gen_metrics_data (line 696) | pub fn api_msg_gen_metrics_data(data: &MetricsData) -> String {
  function api_msg_parse_metrics_data (line 714) | pub fn api_msg_parse_metrics_data(data: &str) -> Result<MetricsData, Box...
  function api_msg_gen_stats_overview (line 783) | pub fn api_msg_gen_stats_overview(data: &OverviewData) -> String {
  function api_msg_parse_stats_overview (line 795) | pub fn api_msg_parse_stats_overview(data: &str) -> Result<OverviewData, ...
  function api_msg_gen_hourly_query_count (line 832) | pub fn api_msg_gen_hourly_query_count(hourly_count: &HourlyQueryCount) -...
  function api_msg_parse_hourly_query_count (line 850) | pub fn api_msg_parse_hourly_query_count(data: &str) -> Result<HourlyQuer...
  function api_msg_gen_request_qps (line 886) | pub fn api_msg_gen_request_qps(qps: u32) -> String {
  function api_msg_gen_daily_query_count (line 894) | pub fn api_msg_gen_daily_query_count(daily_count: &DailyQueryCount) -> S...
  function api_msg_parse_daily_query_count (line 912) | pub fn api_msg_parse_daily_query_count(data: &str) -> Result<DailyQueryC...
  function api_msg_gen_whois_info (line 948) | pub fn api_msg_gen_whois_info(data: &WhoIsInfo) -> String {
  function api_msg_parse_whois_info (line 961) | pub fn api_msg_parse_whois_info(data: &str) -> Result<WhoIsInfo, Box<dyn...

FILE: plugin/smartdns-ui/src/http_error.rs
  type HttpError (line 27) | pub struct HttpError {
    method new (line 33) | pub fn new(code: StatusCode, msg: String) -> Self {
    method to_response (line 40) | pub fn to_response(&self) -> Response<Full<Bytes>> {
    method from (line 52) | fn from(err: hyper::Error) -> HttpError {
    method from (line 61) | fn from(err: FromUtf8Error) -> HttpError {
    method from (line 70) | fn from(err: std::io::Error) -> HttpError {
    method from (line 79) | fn from(err: Box<dyn std::error::Error>) -> HttpError {
    method from (line 88) | fn from(err: Box<dyn std::error::Error + Send>) -> HttpError {

FILE: plugin/smartdns-ui/src/http_jwt.rs
  type JwtClaims (line 23) | pub struct JwtClaims {
  type Jwt (line 29) | pub struct Jwt {
    method new (line 42) | pub fn new(user: &str, secret: &str, ip: &str, expired_in: u32) -> Self {
    method refresh_token (line 51) | pub fn refresh_token(&self, token: &str) -> Result<TokenInfo, String> {
    method encode_token (line 59) | pub fn encode_token(&self) -> TokenInfo {
    method is_token_valid (line 78) | pub fn is_token_valid(&self, token: &str) -> bool {
    method decode_token (line 93) | pub fn decode_token(&self, token: &str) -> Result<JwtClaims, String> {
  type TokenInfo (line 36) | pub struct TokenInfo {

FILE: plugin/smartdns-ui/src/http_server.rs
  constant HTTP_SERVER_DEFAULT_PASSWORD (line 62) | const HTTP_SERVER_DEFAULT_PASSWORD: &str = "password";
  constant HTTP_SERVER_DEFAULT_USERNAME (line 63) | const HTTP_SERVER_DEFAULT_USERNAME: &str = "admin";
  constant HTTP_SERVER_DEFAULT_WWW_ROOT (line 64) | const HTTP_SERVER_DEFAULT_WWW_ROOT: &str = "/usr/share/smartdns/wwwroot";
  constant HTTP_SERVER_DEFAULT_IPV6 (line 65) | const HTTP_SERVER_DEFAULT_IPV6: &str = "http://[::]:6080";
  constant HTTP_SERVER_DEFAULT_IP (line 66) | const HTTP_SERVER_DEFAULT_IP: &str = "http://0.0.0.0:6080";
  type HttpServerConfig (line 69) | pub struct HttpServerConfig {
    method new (line 80) | pub fn new() -> Self {
    method settings_map (line 98) | pub fn settings_map(&self) -> std::collections::HashMap<String, String> {
    method load_config (line 114) | pub fn load_config(&mut self, data_server: Arc<DataServer>) -> Result<...
  type HttpServerControl (line 153) | pub struct HttpServerControl {
    method new (line 161) | pub fn new() -> Self {
    method set_plugin (line 169) | pub fn set_plugin(&self, plugin: Arc<SmartdnsPlugin>) {
    method get_plugin (line 173) | pub fn get_plugin(&self) -> Result<Arc<SmartdnsPlugin>, Box<dyn Error>> {
    method get_http_server (line 185) | pub fn get_http_server(&self) -> Arc<HttpServer> {
    method start_http_server (line 189) | pub fn start_http_server(&self, conf: &HttpServerConfig) -> Result<(),...
    method stop_http_server (line 220) | pub fn stop_http_server(&self) {
  method drop (line 250) | fn drop(&mut self) {
  type TokioExecutor (line 256) | pub struct TokioExecutor;
    method execute (line 263) | fn execute(&self, fut: F) {
  type HttpServer (line 268) | pub struct HttpServer {
    method new (line 281) | fn new() -> Self {
    method get_conf (line 338) | pub fn get_conf(&self) -> HttpServerConfig {
    method get_conf_mut (line 343) | pub fn get_conf_mut(&'_ self) -> MutexGuard<'_, HttpServerConfig> {
    method login_attempts_reset (line 347) | pub fn login_attempts_reset(&self) {
    method login_attempts_check (line 353) | pub fn login_attempts_check(&self) -> bool {
    method get_local_addr (line 379) | pub fn get_local_addr(&self) -> Option<SocketAddr> {
    method set_conf (line 384) | fn set_conf(&self, conf: &HttpServerConfig) -> Result<(), Box<dyn Erro...
    method set_plugin (line 396) | fn set_plugin(&self, plugin: Arc<SmartdnsPlugin>) {
    method get_plugin (line 401) | fn get_plugin(&self) -> Result<Arc<SmartdnsPlugin>, Box<dyn Error>> {
    method is_https_server (line 413) | pub fn is_https_server(&self) -> bool {
    method get_data_server (line 428) | pub fn get_data_server(&self) -> Arc<DataServer> {
    method get_token_from_header (line 432) | pub fn get_token_from_header(
    method auth_token_is_valid (line 485) | pub fn auth_token_is_valid(
    method server_add_cors_header (line 504) | fn server_add_cors_header(
    method server_handle_http_api_request (line 540) | async fn server_handle_http_api_request(
    method get_mime_type (line 622) | pub fn get_mime_type(&self, file: &str) -> String {
    method server_handle_http_request (line 631) | async fn server_handle_http_request(
    method http_server_handle_conn (line 759) | async fn http_server_handle_conn(this: Arc<HttpServer>, stream: TcpStr...
    method https_server_handle_conn (line 776) | async fn https_server_handle_conn(
    method handle_tls_accept (line 796) | async fn handle_tls_accept(this: Arc<HttpServer>, acceptor: TlsAccepto...
    method http_server_loop (line 817) | async fn http_server_loop(
    method stop_http_server (line 933) | fn stop_http_server(&self) {
  function normalize_path (line 952) | pub fn normalize_path(path: &Path) -> PathBuf {

FILE: plugin/smartdns-ui/src/http_server_api.rs
  constant PASSWORD_CONFIG_KEY (line 42) | const PASSWORD_CONFIG_KEY: &str = "smartdns-ui.password";
  constant REST_API_PATH (line 43) | const REST_API_PATH: &str = "/api";
  type APIRouteFuture (line 45) | type APIRouteFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
  type APIRouterFun (line 46) | type APIRouterFun = fn(
  type APIRouteParam (line 51) | type APIRouteParam = HashMap<String, String>;
  type APIRouter (line 53) | pub struct APIRouter {
  type API (line 59) | pub struct API {
    method new (line 72) | pub fn new() -> Self {
    method register (line 112) | pub fn register(&mut self, method: Method, path: &str, auth: bool, han...
    method get_router (line 134) | pub fn get_router(&self, method: &Method, path: &str) -> Option<(&APIR...
    method get_params (line 157) | fn get_params(req: &Request<body::Incoming>) -> HashMap<String, String> {
    method params_parser_value (line 164) | fn params_parser_value<T: std::str::FromStr>(v: Option<&String>) -> Op...
    method params_get_value (line 176) | fn params_get_value<T: std::str::FromStr>(
    method params_get_value_default (line 189) | fn params_get_value_default<T: std::str::FromStr>(
    method response_error (line 210) | pub fn response_error(code: StatusCode, msg: &str) -> Result<Response<...
    method response_build (line 220) | pub fn response_build(
    method api_auth_refresh (line 232) | async fn api_auth_refresh(
    method api_auth_login (line 297) | async fn api_auth_login(
    method api_auth_logout (line 361) | async fn api_auth_logout(
    method api_auth_check (line 377) | async fn api_auth_check(
    method api_auth_change_password (line 385) | async fn api_auth_change_password(
    method api_service_restart (line 441) | async fn api_service_restart(
    method api_cache_count (line 458) | async fn api_cache_count(
    method api_cache_flush (line 472) | async fn api_cache_flush(
    method api_domain_get_list_count (line 487) | async fn api_domain_get_list_count(
    method api_domain_get_by_id (line 501) | async fn api_domain_get_by_id(
    method api_client_delete_by_id (line 528) | async fn api_client_delete_by_id(
    method api_domain_delete_by_id (line 559) | async fn api_domain_delete_by_id(
    method api_domain_get_list (line 599) | async fn api_domain_get_list(
    method api_domain_delete_list (line 706) | async fn api_domain_delete_list(
    method api_client_get_list (line 732) | async fn api_client_get_list(
    method api_log_stream (line 826) | async fn api_log_stream(
    method api_audit_log_stream (line 847) | async fn api_audit_log_stream(
    method api_log_set_level (line 868) | async fn api_log_set_level(
    method api_log_get_level (line 886) | async fn api_log_get_level(
    method api_server_version (line 896) | async fn api_server_version(
    method api_upstream_server_get_list (line 907) | async fn api_upstream_server_get_list(
    method api_config_get_settings (line 919) | async fn api_config_get_settings(
    method api_config_set_settings (line 961) | async fn api_config_set_settings(
    method api_stats_get_top_client (line 990) | async fn api_stats_get_top_client(
    method api_stats_get_top_domain (line 1024) | async fn api_stats_get_top_domain(
    method api_stats_get_metrics (line 1058) | async fn api_stats_get_metrics(
    method api_stats_get_overview (line 1082) | async fn api_stats_get_overview(
    method api_stats_refresh (line 1093) | async fn api_stats_refresh(
    method api_stats_get_daily_query_count (line 1112) | async fn api_stats_get_daily_query_count(
    method api_stats_get_hourly_query_count (line 1144) | async fn api_stats_get_hourly_query_count(
    method api_whois (line 1177) | async fn api_whois(
    method api_tool_term (line 1200) | async fn api_tool_term(
    method call_blocking (line 1225) | async fn call_blocking<F, R>(

FILE: plugin/smartdns-ui/src/http_server_stream.rs
  type Error (line 42) | type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
  constant LOG_CONTROL_MESSAGE_TYPE (line 44) | const LOG_CONTROL_MESSAGE_TYPE: u8 = 1;
  constant LOG_CONTROL_PAUSE (line 45) | const LOG_CONTROL_PAUSE: u8 = 1;
  constant LOG_CONTROL_RESUME (line 46) | const LOG_CONTROL_RESUME: u8 = 2;
  constant LOG_CONTROL_LOGLEVEL (line 47) | const LOG_CONTROL_LOGLEVEL: u8 = 3;
  type LogLevelGuard (line 49) | struct LogLevelGuard {
    method new (line 59) | fn new() -> Self {
  method drop (line 54) | fn drop(&mut self) {
  function serve_log_stream (line 65) | pub async fn serve_log_stream(
  function serve_audit_log_stream (line 177) | pub async fn serve_audit_log_stream(
  function serve_metrics (line 271) | pub async fn serve_metrics(
  type TermMessageType (line 315) | enum TermMessageType {
    type Error (line 324) | type Error = ();
    method try_from (line 326) | fn try_from(value: u8) -> Result<Self, Self::Error> {
  function serve_term (line 339) | pub async fn serve_term(websocket: HyperWebsocket) -> Result<(), Error> {

FILE: plugin/smartdns-ui/src/lib.rs
  function lib_init_ops (line 42) | fn lib_init_ops() {
  function lib_deinit_ops (line 51) | fn lib_deinit_ops() {
  function lib_init_smartdns_lib (line 59) | fn lib_init_smartdns_lib() {
  function lib_init (line 64) | fn lib_init() {
  function lib_deinit (line 73) | fn lib_deinit() {

FILE: plugin/smartdns-ui/src/plugin.rs
  type SmartdnsPlugin (line 31) | pub struct SmartdnsPlugin {
    method new (line 44) | pub fn new() -> Arc<Self> {
    method get_runtime (line 68) | pub fn get_runtime(&self) -> Arc<Runtime> {
    method get_http_server (line 72) | pub fn get_http_server(&self) -> Arc<HttpServer> {
    method get_data_server (line 76) | pub fn get_data_server(&self) -> Arc<DataServer> {
    method parser_args (line 80) | fn parser_args(&self, args: &Vec<String>) -> Result<(), Box<dyn Error>> {
    method load_config (line 142) | pub fn load_config(&self) -> Result<(), Box<dyn Error>> {
    method start (line 155) | pub fn start(&self, args: &Vec<String>) -> Result<(), Box<dyn Error>> {
    method stop (line 172) | pub fn stop(&self) {
    method query_complete (line 184) | pub fn query_complete(&self, request: Box<dyn DnsRequest>) -> Result<(...
    method server_log (line 194) | pub fn server_log(&self, level: LogLevel, msg: &str, msg_len: i32) {
    method server_audit_log (line 198) | pub fn server_audit_log(&self, msg: &str, msg_len: i32) {
  method drop (line 204) | fn drop(&mut self) {
  type SmartdnsPluginImpl (line 209) | pub struct SmartdnsPluginImpl {
    method new (line 214) | pub fn new() -> Self {
  method drop (line 222) | fn drop(&mut self) {
  method server_query_complete (line 228) | fn server_query_complete(&self, request: Box<dyn DnsRequest>) {
  method server_log (line 232) | fn server_log(&self, level: LogLevel, msg: &str, msg_len: i32) {
  method server_audit_log (line 236) | fn server_audit_log(&self, msg: &str, msg_len: i32) {
  method server_init (line 240) | fn server_init(&mut self, args: &Vec<String>) -> Result<(), Box<dyn Erro...
  method server_exit (line 244) | fn server_exit(&mut self) {

FILE: plugin/smartdns-ui/src/server_log.rs
  type ServerLogMsg (line 24) | pub struct ServerLogMsg {
  type ServerLog (line 30) | pub struct ServerLog {
    method new (line 35) | pub fn new() -> Self {
    method get_log_stream (line 41) | pub async fn get_log_stream(&self) -> mpsc::Receiver<ServerLogMsg> {
    method dispatch_log (line 47) | pub fn dispatch_log(&self, level: LogLevel, msg: &str, len: i32) {
  type ServerAuditLogMsg (line 86) | pub struct ServerAuditLogMsg {
  type ServerAuditLog (line 91) | pub struct ServerAuditLog {
    method new (line 96) | pub fn new() -> Self {
    method get_audit_log_stream (line 102) | pub async fn get_audit_log_stream(&self) -> mpsc::Receiver<ServerAudit...
    method dispatch_audit_log (line 108) | pub fn dispatch_audit_log(&self, msg: &str, len: i32) {

FILE: plugin/smartdns-ui/src/smartdns.rs
  type LogLevel (line 37) | pub enum LogLevel {
    type Error (line 66) | type Error = ();
    method try_from (line 68) | fn try_from(value: u32) -> Result<Self, Self::Error> {
    type Error (line 82) | type Error = ();
    method try_from (line 84) | fn try_from(value: &str) -> Result<Self, Self::Error> {
    type Error (line 98) | type Error = ();
    method try_from (line 99) | fn try_from(value: String) -> Result<Self, Self::Error> {
  function from (line 47) | fn from(level: LogLevel) -> u32 {
  method to_string (line 53) | fn to_string(&self) -> String {
  type DnsServerType (line 105) | pub enum DnsServerType {
    method from (line 117) | fn from(t: u32) -> DnsServerType {
    type Err (line 132) | type Err = String;
    method from_str (line 134) | fn from_str(t: &str) -> Result<DnsServerType, String> {
  method to_string (line 149) | fn to_string(&self) -> String {
  type DnsServerTrustStatus (line 164) | pub enum DnsServerTrustStatus {
    method from (line 173) | fn from(t: u32) -> DnsServerTrustStatus {
  method to_string (line 186) | fn to_string(&self) -> String {
  function dns_can_log (line 205) | pub fn dns_can_log(level: LogLevel) -> bool {
  function dns_log_set_level (line 209) | pub fn dns_log_set_level(level: LogLevel) {
  function dns_log_get_level (line 215) | pub fn dns_log_get_level() -> LogLevel {
  function dns_audit_log_enabled (line 222) | pub fn dns_audit_log_enabled() -> bool {
  function dns_log_out (line 226) | pub fn dns_log_out(level: LogLevel, file: &str, line: u32, message: &str) {
  function smartdns_version (line 245) | pub fn smartdns_version() -> String {
  function smartdns_ui_version (line 254) | pub fn smartdns_ui_version() -> String {
  function smartdns_get_server_name (line 268) | pub fn smartdns_get_server_name() -> String {
  function smartdns_server_run (line 283) | pub fn smartdns_server_run(file: &str) -> Result<(), Box<dyn Error>> {
  function smartdns_enable_update_neighbour (line 297) | pub fn smartdns_enable_update_neighbour(enable: bool) {
  function smartdns_conf_get_conf_fullpath (line 307) | pub fn smartdns_conf_get_conf_fullpath(path: &str) -> String {
  function smartdns_server_stop (line 324) | pub fn smartdns_server_stop() {
  function get_utc_time_ms (line 330) | pub fn get_utc_time_ms() -> u64 {
  function dns_request_complete (line 342) | extern "C" fn dns_request_complete(request: *mut smartdns_c::dns_request) {
  function dns_server_log (line 357) | extern "C" fn dns_server_log(
  function dns_server_audit_log (line 381) | extern "C" fn dns_server_audit_log(msg: *const c_char, msg_len: i32) {
  function dns_plugin_init (line 400) | extern "C" fn dns_plugin_init(plugin: *mut smartdns_c::dns_plugin) -> i32 {
  function dns_plugin_exit (line 421) | extern "C" fn dns_plugin_exit(_plugin: *mut smartdns_c::dns_plugin) -> i...
  function dns_plugin_api_version (line 431) | extern "C" fn dns_plugin_api_version() -> u32 {
  type DnsRequest (line 435) | pub trait DnsRequest: Send + Sync {
    method get_group_name (line 436) | fn get_group_name(&self) -> String;
    method get_domain (line 437) | fn get_domain(&self) -> String;
    method get_qtype (line 438) | fn get_qtype(&self) -> u32;
    method get_qclass (line 439) | fn get_qclass(&self) -> i32;
    method get_id (line 440) | fn get_id(&self) -> u16;
    method get_rcode (line 441) | fn get_rcode(&self) -> u16;
    method get_query_time (line 442) | fn get_query_time(&self) -> i32;
    method get_query_timestamp (line 443) | fn get_query_timestamp(&self) -> u64;
    method get_ping_time (line 444) | fn get_ping_time(&self) -> f64;
    method get_is_blocked (line 445) | fn get_is_blocked(&self) -> bool;
    method get_is_cached (line 446) | fn get_is_cached(&self) -> bool;
    method get_remote_mac (line 447) | fn get_remote_mac(&self) -> [u8; 6];
    method get_remote_addr (line 448) | fn get_remote_addr(&self) -> String;
    method get_local_addr (line 449) | fn get_local_addr(&self) -> String;
    method is_prefetch_request (line 450) | fn is_prefetch_request(&self) -> bool;
    method is_dualstack_request (line 451) | fn is_dualstack_request(&self) -> bool;
    method get_group_name (line 478) | fn get_group_name(&self) -> String {
    method get_domain (line 487) | fn get_domain(&self) -> String {
    method get_qtype (line 496) | fn get_qtype(&self) -> u32 {
    method get_qclass (line 500) | fn get_qclass(&self) -> i32 {
    method get_id (line 504) | fn get_id(&self) -> u16 {
    method get_rcode (line 508) | fn get_rcode(&self) -> u16 {
    method get_query_time (line 512) | fn get_query_time(&self) -> i32 {
    method get_query_timestamp (line 516) | fn get_query_timestamp(&self) -> u64 {
    method get_ping_time (line 520) | fn get_ping_time(&self) -> f64 {
    method get_is_blocked (line 527) | fn get_is_blocked(&self) -> bool {
    method get_is_cached (line 531) | fn get_is_cached(&self) -> bool {
    method get_remote_mac (line 535) | fn get_remote_mac(&self) -> [u8; 6] {
    method get_remote_addr (line 547) | fn get_remote_addr(&self) -> String {
    method get_local_addr (line 570) | fn get_local_addr(&self) -> String {
    method is_prefetch_request (line 590) | fn is_prefetch_request(&self) -> bool {
    method is_dualstack_request (line 594) | fn is_dualstack_request(&self) -> bool {
  type DnsRequest_C (line 454) | pub struct DnsRequest_C {
    method new (line 460) | fn new(request: *mut smartdns_c::dns_request) -> DnsRequest_C {
    method put_ref (line 468) | fn put_ref(&mut self) {
  method drop (line 600) | fn drop(&mut self) {
  method clone (line 606) | fn clone(&self) -> Self {
  type DnsServerStats (line 620) | pub struct DnsServerStats {
    method new (line 626) | fn new(
    method get_query_total (line 634) | pub fn get_query_total(&self) -> u64 {
    method get_query_success (line 638) | pub fn get_query_success(&self) -> u64 {
    method get_query_recv (line 642) | pub fn get_query_recv(&self) -> u64 {
    method get_success_rate (line 646) | pub fn get_success_rate(&self) -> f64 {
    method get_query_avg_time (line 659) | pub fn get_query_avg_time(&self) -> f64 {
  method drop (line 668) | fn drop(&mut self) {
  type DnsUpstreamServer (line 677) | pub struct DnsUpstreamServer {
    method new (line 682) | fn new(server_info: *mut smartdns_c::dns_server_info) -> Self {
    method get_server_num (line 690) | pub fn get_server_num() -> i32 {
    method dns_server_alive_num (line 694) | pub fn dns_server_alive_num() -> i32 {
    method get_server_stats (line 698) | pub fn get_server_stats(&self) -> DnsServerStats {
    method is_server_alive (line 703) | pub fn is_server_alive(&self) -> bool {
    method get_server_list (line 707) | pub fn get_server_list() -> Result<Vec<DnsUpstreamServer>, String> {
    method get_ip (line 735) | pub fn get_ip(&self) -> String {
    method get_host (line 742) | pub fn get_host(&self) -> String {
    method get_port (line 751) | pub fn get_port(&self) -> u16 {
    method get_type (line 755) | pub fn get_type(&self) -> DnsServerType {
    method get_server_security_status (line 763) | pub fn get_server_security_status(&self) -> DnsServerTrustStatus {
    method get_groups (line 771) | pub fn get_groups(&self) -> Vec<String> {
  method drop (line 778) | fn drop(&mut self) {
  method clone (line 786) | fn clone(&self) -> Self {
  type SmartdnsOperations (line 799) | pub trait SmartdnsOperations {
    method server_query_complete (line 800) | fn server_query_complete(&self, request: Box<dyn DnsRequest>);
    method server_log (line 801) | fn server_log(&self, level: LogLevel, msg: &str, msg_len: i32);
    method server_audit_log (line 802) | fn server_audit_log(&self, msg: &str, msg_len: i32);
    method server_init (line 803) | fn server_init(&mut self, args: &Vec<String>) -> Result<(), Box<dyn Er...
    method server_exit (line 804) | fn server_exit(&mut self);
  type Plugin (line 812) | pub struct Plugin {
    method get_args (line 825) | pub fn get_args(&self) -> &Vec<String> {
    method set_operation (line 829) | pub fn set_operation(&mut self, ops: Box<dyn SmartdnsOperations>) {
    method clear_operation (line 833) | pub fn clear_operation(&mut self) {
    method smartdns_exit (line 837) | pub fn smartdns_exit(status: i32) {
    method smartdns_restart (line 843) | pub fn smartdns_restart() {
    method smartdns_get_cert (line 849) | pub fn smartdns_get_cert() -> Result<SmartdnsCert, String> {
    method dns_cache_flush (line 875) | pub fn dns_cache_flush() {
    method dns_cache_total_num (line 881) | pub fn dns_cache_total_num() -> i32 {
    method dns_conf_cache_dir (line 886) | pub fn dns_conf_cache_dir() -> String {
    method dns_conf_data_dir (line 896) | pub fn dns_conf_data_dir() -> String {
    method dns_conf_plugin_config (line 906) | pub fn dns_conf_plugin_config(key: &str) -> Option<String> {
    method dns_conf_plugin_config_default (line 923) | pub fn dns_conf_plugin_config_default(key: &str, default_val: &String)...
    method dns_conf_plugin_clear_all_config (line 933) | pub fn dns_conf_plugin_clear_all_config() {
    method parser_args (line 939) | fn parser_args(&mut self, plugin: *mut smartdns_c::dns_plugin) -> Resu...
  type SmartdnsCert (line 817) | pub struct SmartdnsCert {
  type Stats (line 958) | pub struct Stats {}
    method get_avg_process_time (line 961) | pub fn get_avg_process_time() -> f64 {
    method get_request_total (line 970) | pub fn get_request_total() -> u64 {
    method get_request_success (line 974) | pub fn get_request_success() -> u64 {
    method get_request_from_client (line 978) | pub fn get_request_from_client() -> u64 {
    method get_request_blocked (line 982) | pub fn get_request_blocked() -> u64 {
    method get_cache_hit (line 986) | pub fn get_cache_hit() -> u64 {
    method get_cache_memsize (line 990) | pub fn get_cache_memsize() -> u64 {
    method get_cache_hit_rate (line 994) | pub fn get_cache_hit_rate() -> f64 {
    method get_cache_memory_size (line 1003) | pub fn get_cache_memory_size() -> u64 {
    method fmt (line 1009) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function test_dns_log (line 1019) | fn test_dns_log() {

FILE: plugin/smartdns-ui/src/utils.rs
  function parse_value (line 25) | pub fn parse_value<T>(value: Option<String>, min: T, max: T, default: T)...
  function seconds_until_next_hour (line 51) | pub fn seconds_until_next_hour() -> u64 {
  function get_free_disk_space (line 59) | pub fn get_free_disk_space(path: &str) -> u64 {
  function hash_password (line 69) | pub fn hash_password(password: &str, round: Option<u32>) -> Result<Strin...
  function verify_password (line 80) | pub fn verify_password(password: &str, password_hash: &str) -> bool {
  function get_page_size (line 91) | pub fn get_page_size() -> usize {
  function is_dir_writable (line 96) | pub fn is_dir_writable(path: &str) -> bool {
  function is_ipv6_supported (line 101) | pub fn is_ipv6_supported() -> bool {

FILE: plugin/smartdns-ui/src/whois.rs
  type WhoIsInfo (line 29) | pub struct WhoIsInfo {
  type WhoIs (line 39) | pub struct WhoIs {
    method new (line 45) | pub fn new() -> Self {
    method parser_whois (line 52) | pub fn parser_whois(&self, whois: &str, whois_domain: &mut String) -> ...
    method query_from_server (line 96) | pub async fn query_from_server(domain: &str, server: &str) -> Result<S...
    method add_server (line 121) | pub fn add_server(&self, domain: &str, server: &str) {
    method get_server (line 126) | pub fn get_server(&self, domain: &str) -> Option<String> {
    method get_server_by_domain (line 134) | pub fn get_server_by_domain(&self, domain: &str) -> String {
    method query (line 150) | pub async fn query(&self, domain: &str) -> Result<WhoIsInfo, Box<dyn E...

FILE: plugin/smartdns-ui/tests/common/client.rs
  type TestClient (line 25) | pub struct TestClient {
    method new (line 33) | pub fn new(url: &String) -> Self {
    method set_with_auth_header (line 48) | pub fn set_with_auth_header(&mut self, with_auth_header: bool) {
    method login (line 53) | pub fn login(&mut self, username: &str, password: &str) -> Result<Stri...
    method logout (line 73) | pub fn logout(&mut self) -> Result<String, Box<dyn Error>> {
    method prep_request (line 81) | fn prep_request(
    method get (line 96) | pub fn get(&self, path: &str) -> Result<(i32, String), Box<dyn Error>> {
    method delete (line 105) | pub fn delete(&self, path: &str) -> Result<(i32, String), Box<dyn Erro...
    method put (line 114) | pub fn put(&self, path: &str, body: &str) -> Result<(i32, String), Box...
    method post (line 123) | pub fn post(&self, path: &str, body: &str) -> Result<(i32, String), Bo...
    method websocket (line 132) | pub fn websocket(
  method drop (line 166) | fn drop(&mut self) {}

FILE: plugin/smartdns-ui/tests/common/server.rs
  type InstanceLockGuard (line 30) | pub struct InstanceLockGuard<'a> {
  function new_read_guard (line 36) | pub fn new_read_guard() -> Self {
  function new_write_guard (line 43) | pub fn new_write_guard() -> Self {
  type TestDnsRequest (line 51) | pub struct TestDnsRequest {
    method new (line 73) | pub fn new() -> Self {
  method get_group_name (line 98) | fn get_group_name(&self) -> String {
  method get_domain (line 102) | fn get_domain(&self) -> String {
  method get_qtype (line 106) | fn get_qtype(&self) -> u32 {
  method get_qclass (line 110) | fn get_qclass(&self) -> i32 {
  method get_id (line 114) | fn get_id(&self) -> u16 {
  method get_rcode (line 118) | fn get_rcode(&self) -> u16 {
  method get_query_time (line 122) | fn get_query_time(&self) -> i32 {
  method get_query_timestamp (line 126) | fn get_query_timestamp(&self) -> u64 {
  method get_ping_time (line 130) | fn get_ping_time(&self) -> f64 {
  method get_is_blocked (line 134) | fn get_is_blocked(&self) -> bool {
  method get_is_cached (line 138) | fn get_is_cached(&self) -> bool {
  method get_remote_mac (line 142) | fn get_remote_mac(&self) -> [u8; 6] {
  method get_remote_addr (line 146) | fn get_remote_addr(&self) -> String {
  method get_local_addr (line 150) | fn get_local_addr(&self) -> String {
  method is_prefetch_request (line 154) | fn is_prefetch_request(&self) -> bool {
  method is_dualstack_request (line 158) | fn is_dualstack_request(&self) -> bool {
  method drop (line 164) | fn drop(&mut self) {
  type TestSmartDnsConfigItem (line 175) | struct TestSmartDnsConfigItem {
  type TestSmartDnsServer (line 180) | pub struct TestSmartDnsServer {
    method new (line 188) | pub fn new() -> Self {
    method set_workdir (line 204) | pub fn set_workdir(&mut self, workdir: &str) {
    method add_conf (line 208) | pub fn add_conf(&mut self, key: &str, value: &str) {
    method gen_conf_file (line 215) | fn gen_conf_file(&self) -> std::io::Result<String> {
    method start (line 224) | pub fn start(&mut self) -> Result<(), Box<dyn std::error::Error>> {
    method stop (line 237) | pub fn stop(&mut self) {
  method drop (line 251) | fn drop(&mut self) {
  type TestServer (line 256) | pub struct TestServer {
    method new (line 274) | pub fn new() -> Self {
    method setup_default_args (line 298) | fn setup_default_args(&mut self) {
    method get_url (line 314) | pub fn get_url(&self, path: &str) -> String {
    method get_host (line 318) | pub fn get_host(&self) -> String {
    method get_www_root (line 323) | pub fn get_www_root(&self) -> &String {
    method create_workdir (line 327) | fn create_workdir(&self) -> std::io::Result<()> {
    method remove_workdir (line 333) | fn remove_workdir(&self) -> std::io::Result<()> {
    method add_mock_server_conf (line 339) | pub fn add_mock_server_conf(&mut self, key: &str, value: &str) {
    method enable_mock_server (line 344) | pub fn enable_mock_server(&mut self) {
    method add_args (line 350) | pub fn add_args(&mut self, args: Vec<String>) {
    method send_test_dnsrequest (line 357) | pub fn send_test_dnsrequest(
    method new_mock_domain_record (line 384) | pub fn new_mock_domain_record(&self) -> DomainData {
    method get_data_server (line 401) | pub fn get_data_server(&self) -> Arc<DataServer> {
    method add_domain_record (line 406) | pub fn add_domain_record(
    method set_log_level (line 413) | pub fn set_log_level(&mut self, level: LogLevel) {
    method init_server (line 417) | fn init_server(&mut self) -> Result<(), Box<dyn std::error::Error>> {
    method set_https (line 427) | pub fn set_https(&mut self, enable: bool) {
    method set_one_instance (line 436) | pub fn set_one_instance(&mut self, one_instance: bool) {
    method start (line 440) | pub fn start(&mut self) -> Result<(), Box<dyn std::error::Error>> {
    method stop (line 487) | pub fn stop(&mut self) {
  method drop (line 502) | fn drop(&mut self) {

FILE: plugin/smartdns-ui/tests/httpserver_test.rs
  function test_http_server_indexhtml (line 25) | fn test_http_server_indexhtml() {
  function test_http_server_somehtml (line 44) | fn test_http_server_somehtml() {
  function test_http_server_redirect_indexhtml (line 67) | fn test_http_server_redirect_indexhtml() {
  function test_http_server_404 (line 86) | fn test_http_server_404() {

FILE: plugin/smartdns-ui/tests/restapi_test.rs
  function test_rest_api_login (line 27) | fn test_rest_api_login() {
  function test_rest_api_logout (line 52) | fn test_rest_api_logout() {
  function test_rest_api_login_incorrect (line 77) | fn test_rest_api_login_incorrect() {
  function test_rest_api_change_password (line 94) | fn test_rest_api_change_password() {
  function test_rest_api_cache_count (line 120) | fn test_rest_api_cache_count() {
  function test_rest_api_auth_refresh (line 138) | fn test_rest_api_auth_refresh() {
  function test_rest_api_auth_check (line 159) | fn test_rest_api_auth_check() {
  function test_rest_api_no_permission (line 179) | fn test_rest_api_no_permission() {
  function test_rest_api_404 (line 196) | fn test_rest_api_404() {
  function test_rest_api_log_stream (line 214) | fn test_rest_api_log_stream() {
  function test_rest_api_log_level (line 231) | fn test_rest_api_log_level() {
  function test_rest_api_get_domain (line 260) | fn test_rest_api_get_domain() {
  function test_rest_api_audit_log_stream (line 297) | fn test_rest_api_audit_log_stream() {
  function test_rest_api_get_by_id (line 315) | fn test_rest_api_get_by_id() {
  function test_rest_api_delete_domain_by_id (line 343) | fn test_rest_api_delete_domain_by_id() {
  function test_rest_api_server_version (line 379) | fn test_rest_api_server_version() {
  function test_rest_api_https_server (line 403) | fn test_rest_api_https_server() {
  function test_rest_api_settings (line 429) | fn test_rest_api_settings() {
  function test_rest_api_get_client (line 467) | fn test_rest_api_get_client() {
  function test_rest_api_stats_top (line 496) | fn test_rest_api_stats_top() {
  function test_rest_api_stats_overview (line 550) | fn test_rest_api_stats_overview() {
  function test_rest_api_stats_metrics (line 585) | fn test_rest_api_stats_metrics() {
  function test_rest_api_get_hourly_query_count (line 627) | fn test_rest_api_get_hourly_query_count() {
  function test_rest_api_server_status (line 655) | fn test_rest_api_server_status() {

FILE: src/dns.c
  function is_aligned (line 49) | static int is_aligned(void *ptr, int aligment)
  function _dns_read_short (line 55) | static unsigned short _dns_read_short(unsigned char **buffer)
  function _dns_write_char (line 70) | static __attribute__((unused)) void _dns_write_char(unsigned char **buff...
  function _dns_read_char (line 77) | static unsigned char _dns_read_char(unsigned char **buffer)
  function _dns_write_short (line 85) | static void _dns_write_short(unsigned char **buffer, unsigned short value)
  function _dns_write_shortptr (line 99) | static void _dns_write_shortptr(unsigned char **buffer, void *ptrvalue)
  function _dns_write_int (line 121) | static void _dns_write_int(unsigned char **buffer, unsigned int value)
  function _dns_write_intptr (line 133) | static void _dns_write_intptr(unsigned char **buffer, void *ptrvalue)
  function _dns_read_int (line 153) | static unsigned int _dns_read_int(unsigned char **buffer)
  function _dns_left_len (line 167) | static inline int _dns_left_len(struct dns_context *context)
  function _dns_get_domain_from_packet (line 172) | static int _dns_get_domain_from_packet(unsigned char *packet, int packet...
  function _dns_decode_domain (line 262) | static int _dns_decode_domain(struct dns_context *context, char *output,...
  function dict_hash (line 267) | static unsigned int dict_hash(const char *s)
  function _dns_add_domain_dict (line 276) | static int _dns_add_domain_dict(struct dns_context *context, unsigned in...
  function _dns_get_domain_offset (line 300) | static int _dns_get_domain_offset(struct dns_context *context, const cha...
  function _dns_encode_domain (line 330) | static int _dns_encode_domain(struct dns_context *context, const char *d...
  type dns_rrs (line 391) | struct dns_rrs
  type dns_packet (line 391) | struct dns_packet
  type dns_head (line 394) | struct dns_head
  type dns_rrs (line 429) | struct dns_rrs
  type dns_rrs (line 433) | struct dns_rrs
  type dns_packet (line 433) | struct dns_packet
  type dns_rrs (line 433) | struct dns_rrs
  type dns_rrs (line 439) | struct dns_rrs
  function _dns_init_context_by_rrs (line 442) | static void _dns_init_context_by_rrs(struct dns_rrs *rrs, struct dns_con...
  function _dns_add_rrs_start (line 452) | static int _dns_add_rrs_start(struct dns_packet *packet, struct dns_cont...
  function _dns_rr_add_end (line 472) | static int _dns_rr_add_end(struct dns_packet *packet, int type, dns_type...
  function _dns_add_qr_head (line 535) | static int _dns_add_qr_head(struct dns_context *context, const char *dom...
  function _dns_get_qr_head (line 552) | static int _dns_get_qr_head(struct dns_context *context, char *domain, i...
  function _dns_add_rr_head (line 575) | static int _dns_add_rr_head(struct dns_context *context, const char *dom...
  function _dns_get_rr_head (line 600) | static int _dns_get_rr_head(struct dns_context *context, char *domain, i...
  type dns_rr_nested (line 623) | struct dns_rr_nested
  type dns_rr_nested (line 623) | struct dns_rr_nested
  type dns_packet (line 623) | struct dns_packet
  function dns_add_rr_nested_memcpy (line 655) | int dns_add_rr_nested_memcpy(struct dns_rr_nested *rr_nested, const void...
  function dns_add_rr_nested_end (line 682) | int dns_add_rr_nested_end(struct dns_rr_nested *rr_nested)
  type dns_rrs (line 705) | struct dns_rrs
  type dns_context (line 707) | struct dns_context
  type dns_rrs (line 728) | struct dns_rrs
  function _dns_add_RAW (line 746) | static int _dns_add_RAW(struct dns_packet *packet, dns_rr_type rrtype, d...
  function _dns_get_RAW (line 786) | static int _dns_get_RAW(struct dns_rrs *rrs, char *domain, int maxsize, ...
  function _dns_add_opt_RAW (line 820) | static int _dns_add_opt_RAW(struct dns_packet *packet, dns_opt_code_t op...
  function _dns_get_opt_RAW (line 836) | static int _dns_get_opt_RAW(struct dns_rrs *rrs, char *domain, int maxsi...
  function _dns_add_OPT (line 844) | static int __attribute__((unused)) _dns_add_OPT(struct dns_packet *packe...
  function _dns_get_OPT (line 889) | static int __attribute__((unused)) _dns_get_OPT(struct dns_rrs *rrs, uns...
  function dns_add_CNAME (line 923) | int dns_add_CNAME(struct dns_packet *packet, dns_rr_type type, const cha...
  function dns_get_CNAME (line 929) | int dns_get_CNAME(struct dns_rrs *rrs, char *domain, int maxsize, int *t...
  function dns_add_A (line 935) | int dns_add_A(struct dns_packet *packet, dns_rr_type type, const char *d...
  function dns_get_A (line 941) | int dns_get_A(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, ...
  function dns_add_PTR (line 947) | int dns_add_PTR(struct dns_packet *packet, dns_rr_type type, const char ...
  function dns_get_PTR (line 953) | int dns_get_PTR(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl...
  function dns_add_TXT (line 959) | int dns_add_TXT(struct dns_packet *packet, dns_rr_type type, const char ...
  function dns_get_TXT (line 975) | int dns_get_TXT(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl...
  function dns_add_NS (line 980) | int dns_add_NS(struct dns_packet *packet, dns_rr_type type, const char *...
  function dns_get_NS (line 986) | int dns_get_NS(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl,...
  function dns_add_AAAA (line 992) | int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, const char...
  function dns_get_AAAA (line 998) | int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *tt...
  function dns_add_SOA (line 1004) | int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, const char ...
  function dns_get_SOA (line 1042) | int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl...
  function dns_set_OPT_payload_size (line 1084) | int dns_set_OPT_payload_size(struct dns_packet *packet, int payload_size)
  function dns_get_OPT_payload_size (line 1094) | int dns_get_OPT_payload_size(struct dns_packet *packet)
  function dns_set_OPT_option (line 1099) | int dns_set_OPT_option(struct dns_packet *packet, unsigned int option)
  function dns_get_OPT_option (line 1105) | unsigned int dns_get_OPT_option(struct dns_packet *packet)
  function dns_add_OPT_ECS (line 1110) | int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
  function dns_get_OPT_ECS (line 1129) | int dns_get_OPT_ECS(struct dns_rrs *rrs, struct dns_opt_ecs *ecs)
  function dns_add_OPT_TCP_KEEPALIVE (line 1154) | int dns_add_OPT_TCP_KEEPALIVE(struct dns_packet *packet, unsigned short ...
  function dns_get_OPT_TCP_KEEPALIVE (line 1166) | int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *timeout)
  function dns_add_SRV (line 1203) | int dns_add_SRV(struct dns_packet *packet, dns_rr_type type, const char ...
  function dns_get_SRV (line 1231) | int dns_get_SRV(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl...
  function _dns_add_SVCB_HTTPS_start (line 1257) | static int _dns_add_SVCB_HTTPS_start(struct dns_rr_nested *svcparam_buff...
  function dns_add_HTTPS_start (line 1291) | int dns_add_HTTPS_start(struct dns_rr_nested *svcparam_buffer, struct dn...
  function dns_add_SVCB_start (line 1297) | int dns_add_SVCB_start(struct dns_rr_nested *svcparam_buffer, struct dns...
  function dns_SVCB_add_raw (line 1303) | int dns_SVCB_add_raw(struct dns_rr_nested *svcparam, unsigned short key,...
  function dns_SVCB_add_port (line 1323) | int dns_SVCB_add_port(struct dns_rr_nested *svcparam, unsigned short port)
  function dns_SVCB_add_alpn (line 1347) | int dns_SVCB_add_alpn(struct dns_rr_nested *svcparam, const unsigned cha...
  function dns_SVCB_add_no_default_alpn (line 1370) | int dns_SVCB_add_no_default_alpn(struct dns_rr_nested *svcparam)
  function dns_SVCB_add_ech (line 1389) | int dns_SVCB_add_ech(struct dns_rr_nested *svcparam, void *ech, int ech_...
  function dns_SVCB_add_ipv4hint (line 1412) | int dns_SVCB_add_ipv4hint(struct dns_rr_nested *svcparam, unsigned char ...
  function dns_SVCB_add_ipv6hint (line 1437) | int dns_SVCB_add_ipv6hint(struct dns_rr_nested *svcparam, unsigned char ...
  function dns_add_SVCB_end (line 1462) | int dns_add_SVCB_end(struct dns_rr_nested *svcparam)
  function dns_add_HTTPS_end (line 1468) | int dns_add_HTTPS_end(struct dns_rr_nested *svcparam)
  function dns_HTTPS_add_raw (line 1474) | int dns_HTTPS_add_raw(struct dns_rr_nested *svcparam, unsigned short key...
  function dns_HTTPS_add_alpn (line 1479) | int dns_HTTPS_add_alpn(struct dns_rr_nested *svcparam, const char *alpn,...
  function dns_HTTPS_add_no_default_alpn (line 1484) | int dns_HTTPS_add_no_default_alpn(struct dns_rr_nested *svcparam)
  function dns_HTTPS_add_port (line 1489) | int dns_HTTPS_add_port(struct dns_rr_nested *svcparam, unsigned short port)
  function dns_HTTPS_add_ipv4hint (line 1494) | int dns_HTTPS_add_ipv4hint(struct dns_rr_nested *svcparam, unsigned char...
  function dns_HTTPS_add_ech (line 1499) | int dns_HTTPS_add_ech(struct dns_rr_nested *svcparam, void *ech, int ech...
  function dns_HTTPS_add_ipv6hint (line 1504) | int dns_HTTPS_add_ipv6hint(struct dns_rr_nested *svcparam, unsigned char...
  function dns_svcparm_start (line 1509) | int dns_svcparm_start(struct dns_rrs *rrs, struct dns_svcparam **https_p...
  type dns_svcparam (line 1559) | struct dns_svcparam
  type dns_rrs (line 1559) | struct dns_rrs
  type dns_svcparam (line 1559) | struct dns_svcparam
  type dns_svcparam (line 1561) | struct dns_svcparam
  function dns_add_domain (line 1568) | int dns_add_domain(struct dns_packet *packet, const char *domain, int qt...
  function dns_get_domain (line 1587) | int dns_get_domain(struct dns_rrs *rrs, char *domain, int maxsize, int *...
  function _dns_decode_head (line 1595) | static int _dns_decode_head(struct dns_context *context)
  function _dns_encode_head (line 1642) | static int _dns_encode_head(struct dns_context *context)
  function _dns_encode_head_count (line 1673) | static int _dns_encode_head_count(struct dns_context *context)
  function _dns_decode_qr_head (line 1687) | static int _dns_decode_qr_head(struct dns_context *context, char *domain...
  function _dns_encode_qr_head (line 1720) | static int _dns_encode_qr_head(struct dns_context *context, char *domain...
  function _dns_decode_rr_head (line 1738) | static int _dns_decode_rr_head(struct dns_context *context, char *domain...
  function _dns_encode_rr_head (line 1770) | static int _dns_encode_rr_head(struct dns_context *context, char *domain...
  function _dns_encode_raw (line 1792) | static int _dns_encode_raw(struct dns_context *context, struct dns_rrs *...
  function _dns_decode_raw (line 1845) | static int _dns_decode_raw(struct dns_context *context, unsigned char *r...
  function _dns_decode_CNAME (line 1856) | static int _dns_decode_CNAME(struct dns_context *context, char *cname, i...
  function _dns_encode_CNAME (line 1867) | static int _dns_encode_CNAME(struct dns_context *context, struct dns_rrs...
  function _dns_decode_SRV (line 1906) | static int _dns_decode_SRV(struct dns_context *context, unsigned short *...
  function _dns_decode_SOA (line 1926) | static int _dns_decode_SOA(struct dns_context *context, struct dns_soa *...
  function _dns_encode_SOA (line 1952) | static int _dns_encode_SOA(struct dns_context *context, struct dns_rrs *...
  function _dns_encode_SRV (line 2015) | static int _dns_encode_SRV(struct dns_context *context, struct dns_rrs *...
  function _dns_decode_opt_ecs (line 2063) | static int _dns_decode_opt_ecs(struct dns_context *context, struct dns_o...
  function _dns_decode_opt_cookie (line 2090) | static int _dns_decode_opt_cookie(struct dns_context *context, struct dn...
  function _dns_decode_opt_tcp_keepalive (line 2118) | static int _dns_decode_opt_tcp_keepalive(struct dns_context *context, un...
  function _dns_encode_OPT (line 2135) | static int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *...
  function _dns_get_opts_data_len (line 2185) | static int _dns_get_opts_data_len(struct dns_packet *packet, struct dns_...
  function _dns_encode_opts (line 2210) | static int _dns_encode_opts(struct dns_packet *packet, struct dns_contex...
  function _dns_decode_opt (line 2248) | static int _dns_decode_opt(struct dns_context *context, dns_rr_type type...
  function _dns_encode_svcparam (line 2366) | static int _dns_encode_svcparam(struct dns_context *context, struct dns_...
  function _dns_decode_SVCB_HTTPS (line 2446) | static int _dns_decode_SVCB_HTTPS(struct dns_context *context, const cha...
  function _dns_decode_qd (line 2518) | static int _dns_decode_qd(struct dns_context *context)
  function _dns_decode_an (line 2539) | static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
  function _dns_encode_qd (line 2725) | static int _dns_encode_qd(struct dns_context *context, struct dns_rrs *rrs)
  function _dns_encode_an (line 2757) | static int _dns_encode_an(struct dns_context *context, struct dns_rrs *rrs)
  function _dns_decode_body (line 2805) | static int _dns_decode_body(struct dns_context *context)
  function _dns_encode_body (line 2856) | static int _dns_encode_body(struct dns_context *context)
  function dns_packet_init (line 2913) | int dns_packet_init(struct dns_packet *packet, int size, struct dns_head...
  function dns_decode_head_only (line 2944) | int dns_decode_head_only(struct dns_packet *packet, int maxsize, unsigne...
  function dns_decode (line 2974) | int dns_decode(struct dns_packet *packet, int maxsize, unsigned char *da...
  function dns_encode (line 3010) | int dns_encode(unsigned char *data, int size, struct dns_packet *packet)
  function _dns_update_domain (line 3042) | static int _dns_update_domain(struct dns_context *context, const char *d...
  function _dns_update_rr_domain (line 3109) | static int _dns_update_rr_domain(struct dns_context *context, unsigned c...
  function _dns_update_qd (line 3135) | static int _dns_update_qd(struct dns_context *context, dns_rr_type type,...
  function _dns_update_an (line 3158) | static int _dns_update_an(struct dns_context *context, dns_rr_type type,...
  function _dns_update_body (line 3203) | static int _dns_update_body(struct dns_context *context, struct dns_upda...
  function _dns_update_id (line 3254) | static int _dns_update_id(unsigned char *data, int size, struct dns_upda...
  function dns_packet_update (line 3261) | int dns_packet_update(unsigned char *data, int size, struct dns_update_p...

FILE: src/dns_cache.c
  type dns_cache_head (line 41) | struct dns_cache_head {
  type dns_cache_record (line 52) | struct dns_cache_record
  type dns_cache_data (line 52) | struct dns_cache_data
  type dns_cache_head (line 55) | struct dns_cache_head
  function dns_cache_init (line 57) | int dns_cache_init(int size, int mem_size, dns_cache_callback timeout_ca...
  type dns_cache (line 92) | struct dns_cache
  function _dns_cache_delete (line 97) | static void _dns_cache_delete(struct dns_cache *dns_cache)
  function dns_cache_get (line 116) | void dns_cache_get(struct dns_cache *dns_cache)
  function dns_cache_release (line 124) | void dns_cache_release(struct dns_cache *dns_cache)
  function _dns_cache_remove (line 142) | static void _dns_cache_remove(struct dns_cache *dns_cache)
  function dns_cache_get_query_flag (line 161) | uint32_t dns_cache_get_query_flag(struct dns_cache *dns_cache)
  type dns_cache (line 166) | struct dns_cache
  type dns_cache_data (line 171) | struct dns_cache_data
  type dns_cache_packet (line 173) | struct dns_cache_packet
  type dns_cache_data (line 192) | struct dns_cache_data
  function dns_cache_expired (line 195) | static void dns_cache_expired(struct tw_base *base, struct tw_timer_list...
  type dns_cache (line 227) | struct dns_cache
  type dns_cache_key (line 227) | struct dns_cache_key
  type dns_cache (line 230) | struct dns_cache
  type dns_cache (line 231) | struct dns_cache
  type dns_cache (line 273) | struct dns_cache
  type dns_cache_key (line 273) | struct dns_cache_key
  type dns_cache (line 275) | struct dns_cache
  function _dns_cache_replace (line 291) | static int _dns_cache_replace(struct dns_cache_key *cache_key, int rcode...
  function dns_cache_replace (line 345) | int dns_cache_replace(struct dns_cache_key *cache_key, int rcode, int tt...
  function _dns_cache_remove_by_domain (line 351) | static void _dns_cache_remove_by_domain(struct dns_cache_key *cache_key)
  function _dns_cache_insert (line 387) | static int _dns_cache_insert(struct dns_cache_info *info, struct dns_cac...
  function dns_cache_insert (line 466) | int dns_cache_insert(struct dns_cache_key *cache_key, int rcode, int ttl...
  function dns_cache_update_timer (line 502) | int dns_cache_update_timer(struct dns_cache_key *key, int timeout)
  function dns_cache_get_ttl (line 522) | int dns_cache_get_ttl(struct dns_cache *dns_cache)
  type dns_cache_data (line 536) | struct dns_cache_data
  type dns_cache (line 536) | struct dns_cache
  type dns_cache_data (line 538) | struct dns_cache_data
  function dns_cache_data_get (line 551) | void dns_cache_data_get(struct dns_cache_data *cache_data)
  function dns_cache_flush (line 561) | void dns_cache_flush(void)
  function dns_cache_data_put (line 574) | void dns_cache_data_put(struct dns_cache_data *cache_data)
  function dns_cache_is_visited (line 588) | int dns_cache_is_visited(struct dns_cache *dns_cache)
  function dns_cache_total_num (line 593) | int dns_cache_total_num(void)
  function dns_cache_total_memsize (line 598) | long dns_cache_total_memsize(void)
  function dns_cache_delete (line 603) | void dns_cache_delete(struct dns_cache *dns_cache)
  function dns_cache_hitnum_dec_get (line 610) | int dns_cache_hitnum_dec_get(struct dns_cache *dns_cache)
  function dns_cache_update (line 622) | void dns_cache_update(struct dns_cache *dns_cache)
  function _dns_cache_read_to_cache (line 641) | static int _dns_cache_read_to_cache(struct dns_cache_record *cache_recor...
  function _dns_cache_read_record (line 695) | static int _dns_cache_read_record(int fd, uint32_t cache_number, dns_cac...
  function _dns_cache_file_read (line 768) | static int _dns_cache_file_read(const char *file, dns_cache_read_callbac...
  function dns_cache_load (line 815) | int dns_cache_load(const char *file)
  function _dns_cache_write_record (line 820) | static int _dns_cache_write_record(int fd, uint32_t *cache_number, struc...
  function _dns_cache_write_records (line 861) | static int _dns_cache_write_records(int fd, uint32_t *cache_number)
  function dns_cache_save (line 870) | int dns_cache_save(const char *file, int check_lock)
  function _dns_cache_print (line 929) | static int _dns_cache_print(struct dns_cache_record *cache_record, struc...
  function dns_cache_print (line 1013) | int dns_cache_print(const char *file)
  function dns_cache_destroy (line 1023) | void dns_cache_destroy(void)

FILE: src/dns_client/client_http2.c
  function _http2_bio_read (line 32) | static int _http2_bio_read(void *private_data, uint8_t *buf, int len)
  function _http2_bio_write (line 39) | static int _http2_bio_write(void *private_data, const uint8_t *buf, int ...
  function _dns_client_send_http2_stream (line 46) | static int _dns_client_send_http2_stream(struct dns_server_info *server_...
  function _dns_client_release_stream_on_error (line 104) | static void _dns_client_release_stream_on_error(struct dns_server_info *...
  function _dns_client_flush_http2_writes (line 126) | static void _dns_client_flush_http2_writes(struct http2_ctx *http2_ctx)
  function _dns_client_send_buffered_http2_requests (line 138) | static void _dns_client_send_buffered_http2_requests(struct dns_server_i...
  function _dns_client_http2_pending_data (line 176) | static int _dns_client_http2_pending_data(struct dns_conn_stream *stream...
  function _dns_client_send_http2 (line 254) | int _dns_client_send_http2(struct dns_server_info *server_info, struct d...
  function _dns_client_http2_init_ctx (line 340) | static int _dns_client_http2_init_ctx(struct dns_server_info *server_info)
  function _dns_client_http2_process_write (line 375) | static int _dns_client_http2_process_write(struct dns_server_info *serve...
  function _dns_client_http2_process_stream_one (line 415) | static int _dns_client_http2_process_stream_one(struct dns_server_info *...
  function _dns_client_http2_process_read (line 462) | static int _dns_client_http2_process_read(struct dns_server_info *server...
  function _dns_client_process_http2 (line 556) | int _dns_client_process_http2(struct dns_server_info *server_info, struc...

FILE: src/dns_client/client_http2.h
  type dns_server_info (line 39) | struct dns_server_info
  type dns_query_struct (line 39) | struct dns_query_struct
  type dns_server_info (line 49) | struct dns_server_info
  type epoll_event (line 49) | struct epoll_event

FILE: src/dns_client/client_http3.c
  function _dns_client_send_http3 (line 27) | int _dns_client_send_http3(struct dns_query_struct *query, struct dns_se...
  function _dns_client_process_recv_http3 (line 81) | int _dns_client_process_recv_http3(struct dns_server_info *server_info, ...

FILE: src/dns_client/client_http3.h
  type dns_query_struct (line 28) | struct dns_query_struct
  type dns_server_info (line 28) | struct dns_server_info
  type dns_server_info (line 31) | struct dns_server_info
  type dns_conn_stream (line 31) | struct dns_conn_stream

FILE: src/dns_client/client_https.c
  function _dns_client_format_https_packet (line 27) | int _dns_client_format_https_packet(struct dns_server_info *server_info,...
  function _dns_client_send_http1 (line 60) | int _dns_client_send_http1(struct dns_server_info *server_info, void *pa...

FILE: src/dns_client/client_https.h
  type dns_server_info (line 28) | struct dns_server_info
  type dns_server_info (line 30) | struct dns_server_info

FILE: src/dns_client/client_mdns.c
  function _dns_client_create_socket_udp_mdns (line 34) | int _dns_client_create_socket_udp_mdns(struct dns_server_info *server_info)
  function _dns_client_send_udp_mdns (line 100) | int _dns_client_send_udp_mdns(struct dns_server_info *server_info, void ...
  function _dns_client_add_mdns_server (line 121) | int _dns_client_add_mdns_server(void)

FILE: src/dns_client/client_mdns.h
  type dns_server_info (line 28) | struct dns_server_info
  type dns_server_info (line 30) | struct dns_server_info

FILE: src/dns_client/client_quic.c
  function _dns_client_quic_bio_recvmmsg (line 39) | static int _dns_client_quic_bio_recvmmsg(BIO *bio, BIO_MSG *msg, size_t ...
  function _dns_client_quic_bio_sendmmsg (line 86) | static int _dns_client_quic_bio_sendmmsg(BIO *bio, BIO_MSG *msg, size_t ...
  function _dns_client_quic_bio_ctrl (line 133) | static long _dns_client_quic_bio_ctrl(BIO *bio, int cmd, long num, void ...
  function _dns_client_setup_quic_ssl_bio (line 154) | static int _dns_client_setup_quic_ssl_bio(struct dns_server_info *server...
  function _dns_client_create_socket_quic (line 215) | int _dns_client_create_socket_quic(struct dns_server_info *server_info, ...
  function _dns_client_process_quic_poll (line 367) | static int _dns_client_process_quic_poll(struct dns_server_info *server_...
  function _dns_client_process_quic (line 494) | int _dns_client_process_quic(struct dns_server_info *server_info, struct...
  function _dns_client_quic_pending_data (line 581) | static int _dns_client_quic_pending_data(struct dns_conn_stream *stream,...
  function _dns_client_send_quic_data (line 653) | int _dns_client_send_quic_data(struct dns_query_struct *query, struct dn...
  function _dns_client_send_quic (line 746) | int _dns_client_send_quic(struct dns_query_struct *query, struct dns_ser...

FILE: src/dns_client/client_quic.h
  type dns_server_info (line 30) | struct dns_server_info
  type dns_query_struct (line 32) | struct dns_query_struct
  type dns_server_info (line 32) | struct dns_server_info
  type dns_query_struct (line 35) | struct dns_query_struct
  type dns_server_info (line 35) | struct dns_server_info
  type dns_server_info (line 38) | struct dns_server_info
  type epoll_event (line 38) | struct epoll_event

FILE: src/dns_client/client_socket.c
  function _dns_client_create_socket (line 32) | int _dns_client_create_socket(struct dns_server_info *server_info)
  function _dns_client_close_socket_ext (line 88) | void _dns_client_close_socket_ext(struct dns_server_info *server_info, i...
  function _dns_client_close_socket (line 182) | void _dns_client_close_socket(struct dns_server_info *server_info)
  function _dns_client_shutdown_socket (line 187) | void _dns_client_shutdown_socket(struct dns_server_info *server_info)
  function _dns_client_socket_send (line 224) | int _dns_client_socket_send(struct dns_server_info *server_info)
  function _dns_client_socket_recv (line 254) | int _dns_client_socket_recv(struct dns_server_info *server_info)
  function _dns_client_copy_data_to_buffer (line 280) | int _dns_client_copy_data_to_buffer(struct dns_server_info *server_info,...
  function _dns_client_send_data_to_buffer (line 293) | int _dns_client_send_data_to_buffer(struct dns_server_info *server_info,...

FILE: src/dns_client/client_socket.h
  type dns_server_info (line 28) | struct dns_server_info
  type dns_server_info (line 30) | struct dns_server_info
  type dns_server_info (line 32) | struct dns_server_info
  type dns_server_info (line 34) | struct dns_server_info
  type dns_server_info (line 36) | struct dns_server_info
  type dns_server_info (line 38) | struct dns_server_info
  type dns_server_info (line 40) | struct dns_server_info
  type dns_server_info (line 42) | struct dns_server_info

FILE: src/dns_client/client_tcp.c
  function _dns_client_create_socket_tcp (line 38) | int _dns_client_create_socket_tcp(struct dns_server_info *server_info)
  function _dns_client_process_tcp_buff (line 153) | static int _dns_client_process_tcp_buff(struct dns_server_info *server_i...
  function _dns_client_process_https_streams (line 256) | static int _dns_client_process_https_streams(struct dns_server_info *ser...
  function _dns_client_process_tcp (line 316) | int _dns_client_process_tcp(struct dns_server_info *server_info, struct ...
  function _dns_client_send_tcp (line 440) | int _dns_client_send_tcp(struct dns_server_info *server_info, void *pack...
  function _dns_client_check_tcp (line 483) | void _dns_client_check_tcp(void)

FILE: src/dns_client/client_tcp.h
  type dns_server_info (line 30) | struct dns_server_info
  type dns_server_info (line 32) | struct dns_server_info
  type epoll_event (line 32) | struct epoll_event
  type dns_server_info (line 34) | struct dns_server_info

FILE: src/dns_client/client_tls.c
  function _ssl_read_ext (line 42) | static ssize_t _ssl_read_ext(struct dns_server_info *server, SSL *ssl, v...
  function _ssl_write_ext2 (line 55) | static ssize_t _ssl_write_ext2(struct dns_server_info *server, SSL *ssl,...
  function _ssl_shutdown (line 82) | int _ssl_shutdown(struct dns_server_info *server)
  function _ssl_get_error_ext (line 96) | static int _ssl_get_error_ext(struct dns_server_info *server, SSL *ssl, ...
  function _ssl_get_error (line 110) | static int _ssl_get_error(struct dns_server_info *server, int ret)
  function _ssl_do_handshake (line 115) | static int _ssl_do_handshake(struct dns_server_info *server)
  function _ssl_do_handevent (line 129) | int _ssl_do_handevent(struct dns_server_info *server)
  function _ssl_session_reused (line 146) | static int _ssl_session_reused(struct dns_server_info *server)
  function SSL_SESSION (line 160) | static SSL_SESSION *_ssl_get1_session(struct dns_server_info *server)
  function dns_client_spki_decode (line 174) | int dns_client_spki_decode(const char *spki, unsigned char *spki_data_ou...
  type dns_server_info (line 187) | struct dns_server_info
  type client_dns_server_flag_https (line 196) | struct client_dns_server_flag_https
  type client_dns_server_flag_tls (line 201) | struct client_dns_server_flag_tls
  type dns_server_info (line 222) | struct dns_server_info
  type client_dns_server_flag_https (line 231) | struct client_dns_server_flag_https
  type client_dns_server_flag_tls (line 237) | struct client_dns_server_flag_tls
  function _dns_client_set_trusted_cert (line 257) | static int _dns_client_set_trusted_cert(SSL_CTX *ssl_ctx)
  function SSL_CTX (line 298) | SSL_CTX *_ssl_ctx_get(int is_quic)
  function _dns_client_create_socket_tls (line 356) | int _dns_client_create_socket_tls(struct dns_server_info *server_info, c...
  function _dns_client_socket_ssl_send_ext (line 525) | int _dns_client_socket_ssl_send_ext(struct dns_server_info *server, SSL ...
  function _dns_client_socket_ssl_recv_ext (line 587) | int _dns_client_socket_ssl_recv_ext(struct dns_server_info *server, SSL ...
  function _dns_client_socket_ssl_send (line 660) | int _dns_client_socket_ssl_send(struct dns_server_info *server, const vo...
  function _dns_client_socket_ssl_recv (line 665) | int _dns_client_socket_ssl_recv(struct dns_server_info *server, void *bu...
  function _dns_client_ssl_poll_event (line 670) | int _dns_client_ssl_poll_event(struct dns_server_info *server_info, int ...
  function _dns_client_to_hex (line 700) | static inline int _dns_client_to_hex(int c)
  function _dns_client_tls_matchName (line 709) | static int _dns_client_tls_matchName(const char *host, const char *patte...
  function _dns_client_tls_get_cert_CN (line 738) | static int _dns_client_tls_get_cert_CN(X509 *cert, char *cn, int max_cn_...
  function _dns_client_verify_SAN (line 765) | static int _dns_client_verify_SAN(struct dns_server_info *server_info, X...
  function _dns_client_verify_common_name (line 827) | static int _dns_client_verify_common_name(struct dns_server_info *server...
  function _dns_client_tls_verify (line 864) | static int _dns_client_tls_verify(struct dns_server_info *server_info)
  function _dns_client_process_tls (line 999) | int _dns_client_process_tls(struct dns_server_info *server_info, struct ...
  function _dns_client_send_tls (line 1114) | int _dns_client_send_tls(struct dns_server_info *server_info, void *pack...

FILE: src/dns_client/client_tls.h
  type dns_server_info (line 30) | struct dns_server_info
  type dns_server_info (line 32) | struct dns_server_info
  type dns_server_info (line 34) | struct dns_server_info
  type dns_server_info (line 36) | struct dns_server_info
  type dns_server_info (line 38) | struct dns_server_info
  type dns_server_info (line 40) | struct dns_server_info
  type dns_server_info (line 42) | struct dns_server_info
  type dns_server_info (line 44) | struct dns_server_info
  type epoll_event (line 44) | struct epoll_event
  type dns_server_info (line 48) | struct dns_server_info
  type dns_server_info (line 50) | struct dns_server_info

FILE: src/dns_client/client_udp.c
  function _dns_client_create_socket_udp_proxy (line 32) | static int _dns_client_create_socket_udp_proxy(struct dns_server_info *s...
  function _dns_client_create_socket_udp (line 105) | int _dns_client_create_socket_udp(struct dns_server_info *server_info)
  function _dns_client_process_send_udp_buffer (line 196) | static int _dns_client_process_send_udp_buffer(struct dns_server_info *s...
  function _dns_client_process_udp_proxy (line 237) | static int _dns_client_process_udp_proxy(struct dns_server_info *server_...
  function _dns_client_process_udp (line 312) | int _dns_client_process_udp(struct dns_server_info *server_info, struct ...
  function _dns_client_send_udp (line 406) | int _dns_client_send_udp(struct dns_server_info *server_info, void *pack...
  function _dns_client_check_udp_nat (line 457) | void _dns_client_check_udp_nat(struct dns_query_struct *query)

FILE: src/dns_client/client_udp.h
  type dns_server_info (line 30) | struct dns_server_info
  type dns_server_info (line 32) | struct dns_server_info
  type dns_query_struct (line 34) | struct dns_query_struct
  type dns_server_info (line 36) | struct dns_server_info
  type epoll_event (line 36) | struct epoll_event

FILE: src/dns_client/conn_stream.c
  type dns_conn_stream (line 23) | struct dns_conn_stream
  type dns_conn_stream (line 25) | struct dns_conn_stream
  function _dns_client_conn_stream_get (line 43) | void _dns_client_conn_stream_get(struct dns_conn_stream *stream)
  function _dns_client_conn_stream_put (line 50) | void _dns_client_conn_stream_put(struct dns_conn_stream *stream)
  function _dns_client_conn_server_streams_free (line 88) | void _dns_client_conn_server_streams_free(struct dns_server_info *server...

FILE: src/dns_client/conn_stream.h
  type dns_conn_stream (line 28) | struct dns_conn_stream
  type dns_conn_stream (line 30) | struct dns_conn_stream
  type dns_conn_stream (line 32) | struct dns_conn_stream
  type dns_server_info (line 34) | struct dns_server_info
  type dns_query_struct (line 34) | struct dns_query_struct

FILE: src/dns_client/dns_client.c
  type dns_client (line 44) | struct dns_client
  function dns_client_flags_init (line 46) | void dns_client_flags_init(struct client_dns_server_flags *flags)
  function _dns_client_server_package_address_match (line 51) | static int _dns_client_server_package_address_match(struct dns_server_in...
  function _dns_client_recv (line 69) | int _dns_client_recv(struct dns_server_info *server_info, unsigned char ...
  function _dns_client_process (line 200) | static int _dns_client_process(struct dns_server_info *server_info, stru...
  function _dns_client_send_http (line 226) | static int _dns_client_send_http(struct dns_server_info *server_info, st...
  function _dns_client_check_server_prohibit (line 239) | static int _dns_client_check_server_prohibit(struct dns_server_info *ser...
  function _dns_client_send_one_packet (line 268) | static int _dns_client_send_one_packet(struct dns_server_info *server_in...
  function _dns_client_send_packet (line 368) | int _dns_client_send_packet(struct dns_query_struct *query, void *packet...
  function dns_client_query (line 461) | int dns_client_query(const char *domain, int qtype, dns_client_callback ...
  function _dns_client_period_run_second (line 553) | static void _dns_client_period_run_second(void)
  function _dns_client_period_run (line 560) | static void _dns_client_period_run(unsigned int msec)
  type epoll_event (line 599) | struct epoll_event
  type epoll_event (line 651) | struct epoll_event
  type dns_server_info (line 652) | struct dns_server_info
  type dns_server_info (line 652) | struct dns_server_info
  function dns_client_init (line 673) | int dns_client_init(void)
  function dns_client_exit (line 761) | void dns_client_exit(void)

FILE: src/dns_client/dns_client.h
  type dns_client_ecs (line 53) | struct dns_client_ecs {
  type dns_server_buff (line 59) | struct dns_server_buff {
  type dns_server_status (line 64) | typedef enum dns_server_status {
  type dns_server_info (line 73) | struct dns_server_info {
  type dns_server_pending_group (line 142) | struct dns_server_pending_group {
  type dns_server_pending (line 147) | struct dns_server_pending {
  type dns_server_group_member (line 176) | struct dns_server_group_member {
  type dns_server_group (line 182) | struct dns_server_group {
  type dns_client (line 189) | struct dns_client {
  type dns_query_replied (line 218) | struct dns_query_replied {
  type dns_conn_stream (line 223) | struct dns_conn_stream {
  type dns_query_struct (line 239) | struct dns_query_struct {
  type dns_client (line 284) | struct dns_client
  type dns_server_info (line 286) | struct dns_server_info
  type sockaddr (line 287) | struct sockaddr
  type dns_query_struct (line 289) | struct dns_query_struct

FILE: src/dns_client/ecs.c
  function _dns_client_setup_ecs (line 23) | static int _dns_client_setup_ecs(char *ip, int subnet, struct dns_client...
  function _dns_client_server_add_ecs (line 63) | int _dns_client_server_add_ecs(struct dns_server_info *server_info, stru...
  function _dns_client_dns_add_ecs (line 82) | int _dns_client_dns_add_ecs(struct dns_query_struct *query, struct dns_p...
  function _dns_client_query_setup_default_ecs (line 91) | int _dns_client_query_setup_default_ecs(struct dns_query_struct *query)

FILE: src/dns_client/ecs.h
  type dns_query_struct (line 28) | struct dns_query_struct
  type dns_query_struct (line 30) | struct dns_query_struct
  type dns_packet (line 30) | struct dns_packet
  type dns_server_info (line 32) | struct dns_server_info
  type client_dns_server_flags (line 32) | struct client_dns_server_flags

FILE: src/dns_client/group.c
  type dns_server_group (line 26) | struct dns_server_group
  type dns_server_group (line 29) | struct dns_server_group
  type hlist_node (line 30) | struct hlist_node
  type dns_server_group (line 50) | struct dns_server_group
  type dns_server_group (line 52) | struct dns_server_group
  function _dns_client_add_to_group (line 70) | int _dns_client_add_to_group(const char *group_name, struct dns_server_i...
  function dns_client_add_to_group (line 99) | int dns_client_add_to_group(const char *group_name, const char *server_i...
  function _dns_client_remove_member (line 106) | static int _dns_client_remove_member(struct dns_server_group_member *gro...
  function _dns_client_remove_from_group (line 122) | static int _dns_client_remove_from_group(struct dns_server_group *group,...
  function _dns_client_remove_server_from_groups (line 139) | int _dns_client_remove_server_from_groups(struct dns_server_info *server...
  function dns_client_remove_from_group (line 153) | int dns_client_remove_from_group(const char *group_name, const char *ser...
  function dns_client_add_group (line 172) | int dns_client_add_group(const char *group_name)
  function _dns_client_remove_group (line 204) | static int _dns_client_remove_group(struct dns_server_group *group)
  function dns_client_remove_group (line 224) | int dns_client_remove_group(const char *group_name)
  function _dns_client_group_remove_all (line 249) | void _dns_client_group_remove_all(void)

FILE: src/dns_client/group.h
  type dns_server_info (line 28) | struct dns_server_info
  type dns_server_group (line 32) | struct dns_server_group
  type dns_server_info (line 34) | struct dns_server_info
  type dns_server_group (line 36) | struct dns_server_group

FILE: src/dns_client/packet.c
  function _dns_client_setup_server_packet (line 23) | int _dns_client_setup_server_packet(struct dns_server_info *server_info,...

FILE: src/dns_client/packet.h
  type dns_server_info (line 28) | struct dns_server_info
  type dns_query_struct (line 28) | struct dns_query_struct

FILE: src/dns_client/pending_server.c
  type addrinfo (line 37) | struct addrinfo
  type addrinfo (line 39) | struct addrinfo
  type addrinfo (line 40) | struct addrinfo
  function _dns_client_resolv_ip_by_host (line 63) | static int _dns_client_resolv_ip_by_host(const char *host, char *ip, int...
  function _dns_client_add_to_pending_group (line 80) | int _dns_client_add_to_pending_group(const char *group_name, const char ...
  function _dns_client_server_pending_get (line 130) | static void _dns_client_server_pending_get(struct dns_server_pending *pe...
  function _dns_client_server_pending_release (line 137) | static void _dns_client_server_pending_release(struct dns_server_pending...
  function _dns_client_server_pending_remove (line 163) | static void _dns_client_server_pending_remove(struct dns_server_pending ...
  function _dns_client_server_pending (line 171) | static int _dns_client_server_pending(const char *server_ip, int port, d...
  function _dns_client_add_server_pending (line 212) | int _dns_client_add_server_pending(const char *server_ip, const char *se...
  function _dns_client_pending_server_resolve (line 254) | static int _dns_client_pending_server_resolve(const struct dns_result *r...
  function _dns_client_add_to_group_pending (line 298) | int _dns_client_add_to_group_pending(const char *group_name, const char ...
  function _dns_client_add_pendings (line 320) | static int _dns_client_add_pendings(struct dns_server_pending *pending, ...
  function _dns_client_remove_all_pending_servers (line 355) | void _dns_client_remove_all_pending_servers(void)
  function _dns_client_add_pending_servers (line 378) | void _dns_client_add_pending_servers(void)

FILE: src/dns_client/pending_server.h
  type addrinfo (line 28) | struct addrinfo
  type client_dns_server_flags (line 31) | struct client_dns_server_flags
  type client_dns_server_flags (line 35) | struct client_dns_server_flags
  type client_dns_server_flags (line 38) | struct client_dns_server_flags

FILE: src/dns_client/proxy.c
  function _dns_proxy_handshake (line 30) | int _dns_proxy_handshake(struct dns_server_info *server_info, struct epo...

FILE: src/dns_client/proxy.h
  type dns_server_info (line 30) | struct dns_server_info
  type epoll_event (line 30) | struct epoll_event

FILE: src/dns_client/query.c
  function _dns_client_query_get (line 25) | void _dns_client_query_get(struct dns_query_struct *query)
  function _dns_client_query_release (line 32) | void _dns_client_query_release(struct dns_query_struct *query)
  function _dns_client_query_remove (line 81) | void _dns_client_query_remove(struct dns_query_struct *query)
  function _dns_client_query_remove_all (line 92) | void _dns_client_query_remove_all(void)
  function _dns_client_send_query (line 112) | int _dns_client_send_query(struct dns_query_struct *query)
  type dns_query_struct (line 168) | struct dns_query_struct
  type dns_query_struct (line 170) | struct dns_query_struct
  type dns_query_struct (line 171) | struct dns_query_struct
  type hlist_node (line 172) | struct hlist_node
  function _dns_replied_check_add (line 203) | int _dns_replied_check_add(struct dns_query_struct *dns_query, struct dn...
  function _dns_replied_check_remove (line 230) | void _dns_replied_check_remove(struct dns_query_struct *dns_query, struc...
  function _dns_client_query_parser_options (line 246) | int _dns_client_query_parser_options(struct dns_query_struct *query, str...
  function _dns_client_retry_dns_query (line 313) | void _dns_client_retry_dns_query(struct dns_query_struct *query)
  function _dns_client_add_hashmap (line 326) | int _dns_client_add_hashmap(struct dns_query_struct *query)

FILE: src/dns_client/query.h
  type dns_query_struct (line 28) | struct dns_query_struct
  type dns_query_struct (line 30) | struct dns_query_struct
  type dns_query_struct (line 32) | struct dns_query_struct
  type dns_query_struct (line 34) | struct dns_query_struct
  type dns_query_struct (line 38) | struct dns_query_struct
  type dns_query_struct (line 40) | struct dns_query_struct
  type dns_query_struct (line 42) | struct dns_query_struct
  type dns_server_info (line 42) | struct dns_server_info
  type dns_query_struct (line 43) | struct dns_query_struct
  type dns_server_info (line 43) | struct dns_server_info
  type dns_query_struct (line 45) | struct dns_query_struct
  type dns_query_options (line 45) | struct dns_query_options
  type dns_query_struct (line 47) | struct dns_query_struct
  type dns_query_struct (line 49) | struct dns_query_struct

FILE: src/dns_client/server_info.c
  function dns_client_server_result_flag (line 37) | unsigned int dns_client_server_result_flag(struct dns_server_info *serve...
  type dns_server_info (line 46) | struct dns_server_info
  function dns_server_security_status (line 55) | dns_server_security_status dns_client_get_server_security_status(struct ...
  type dns_server_info (line 64) | struct dns_server_info
  function dns_client_get_server_port (line 73) | int dns_client_get_server_port(struct dns_server_info *server_info)
  function _dns_server_inc_server_num (line 82) | static inline void _dns_server_inc_server_num(struct dns_server_info *se...
  function _dns_server_dec_server_num (line 91) | static inline void _dns_server_dec_server_num(struct dns_server_info *se...
  function _dns_server_inc_prohibit_server_num (line 100) | void _dns_server_inc_prohibit_server_num(struct dns_server_info *server_...
  function _dns_server_dec_prohibit_server_num (line 109) | void _dns_server_dec_prohibit_server_num(struct dns_server_info *server_...
  function dns_server_type_t (line 118) | dns_server_type_t dns_client_get_server_type(struct dns_server_info *ser...
  type dns_server_stats (line 127) | struct dns_server_stats
  type dns_server_info (line 127) | struct dns_server_info
  function dns_client_server_is_alive (line 136) | int dns_client_server_is_alive(struct dns_server_info *server_info)
  function _dns_client_server_free (line 145) | static void _dns_client_server_free(struct dns_server_info *server_info)
  function dns_client_server_info_get (line 160) | void dns_client_server_info_get(struct dns_server_info *server_info)
  function dns_client_server_info_release (line 169) | void dns_client_server_info_release(struct dns_server_info *server_info)
  function _dns_client_server_info_remove (line 183) | static void _dns_client_server_info_remove(struct dns_server_info *serve...
  function dns_client_get_server_info_lists (line 200) | int dns_client_get_server_info_lists(struct dns_server_info **server_inf...
  function _dns_client_server_exist (line 227) | static int _dns_client_server_exist(const char *server_ip, int port, dns...
  function _dns_client_server_update_ttl (line 255) | static void _dns_client_server_update_ttl(struct ping_host_struct *ping_...
  type dns_server_info (line 270) | struct dns_server_info
  type client_dns_server_flags (line 271) | struct client_dns_server_flags
  type dns_server_info (line 273) | struct dns_server_info
  type dns_server_info (line 274) | struct dns_server_info
  type dns_server_info (line 275) | struct dns_server_info
  function _dns_client_server_add (line 306) | int _dns_client_server_add(const char *server_ip, const char *server_hos...
  function _dns_client_server_close (line 569) | void _dns_client_server_close(struct dns_server_info *server_info)
  function _dns_client_server_remove_all (line 591) | void _dns_client_server_remove_all(void)
  function _dns_client_server_remove (line 614) | static int _dns_client_server_remove(const char *server_ip, int port, dn...
  function _dns_client_check_servers (line 649) | void _dns_client_check_servers(void)
  function dns_client_add_server (line 678) | int dns_client_add_server(const char *server_ip, int port, dns_server_ty...
  function dns_client_remove_server (line 684) | int dns_client_remove_server(const char *server_ip, int port, dns_server...
  function dns_server_num (line 689) | int dns_server_num(void)
  function dns_server_alive_num (line 694) | int dns_server_alive_num(void)

FILE: src/dns_client/server_info.h
  type dns_server_info (line 28) | struct dns_server_info
  type dns_server_info (line 30) | struct dns_server_info
  type dns_server_info (line 32) | struct dns_server_info
  type dns_server_info (line 38) | struct dns_server_info
  type client_dns_server_flags (line 39) | struct client_dns_server_flags
  type client_dns_server_flags (line 42) | struct client_dns_server_flags

FILE: src/dns_client/wake_event.c
  function _dns_client_close_wakeup_event (line 24) | void _dns_client_close_wakeup_event(void)
  function _dns_client_clear_wakeup_event (line 32) | void _dns_client_clear_wakeup_event(void)
  function _dns_client_do_wakeup_event (line 44) | void _dns_client_do_wakeup_event(void)
  function _dns_client_create_wakeup_event (line 55) | int _dns_client_create_wakeup_event(void)

FILE: src/dns_conf/address.c
  function _conf_domain_rule_address (line 27) | int _conf_domain_rule_address(char *domain, const char *domain_address)
  function _config_address (line 191) | int _config_address(void *data, int argc, char *argv[])

FILE: src/dns_conf/bind.c
  function _config_bind_ip_parser_nftset (line 29) | static int _config_bind_ip_parser_nftset(struct dns_bind_ip *bind_ip, un...
  function _config_bind_ip_parser_ipset (line 103) | static int _config_bind_ip_parser_ipset(struct dns_bind_ip *bind_ip, uns...
  function _bind_is_ip_valid (line 166) | static int _bind_is_ip_valid(const char *ip)
  function _config_bind_ip (line 187) | static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
  function dns_server_bind_destroy (line 386) | void dns_server_bind_destroy(void)
  function _config_add_default_server_if_needed (line 415) | int _config_add_default_server_if_needed(void)
  function _config_bind_ip_udp (line 427) | int _config_bind_ip_udp(void *data, int argc, char *argv[])
  function _config_bind_ip_tcp (line 432) | int _config_bind_ip_tcp(void *data, int argc, char *argv[])
  function _config_bind_ip_tls (line 437) | int _config_bind_ip_tls(void *data, int argc, char *argv[])
  function _config_bind_ip_https (line 442) | int _config_bind_ip_https(void *data, int argc, char *argv[])

FILE: src/dns_conf/bootstrap_dns.c
  function _config_update_bootstrap_dns_rule (line 26) | int _config_update_bootstrap_dns_rule(void)

FILE: src/dns_conf/client_rule.c
  function radix_node_t (line 28) | static radix_node_t *_create_client_rules_node(const char *addr)
  type client_rule (line 44) | enum client_rule
  type dns_client_rule (line 46) | struct dns_client_rule
  type client_rule_flags (line 55) | struct client_rule_flags
  type client_rule_group (line 58) | struct client_rule_group
  type client_rule (line 74) | enum client_rule
  function _dns_client_rule_get (line 79) | static void _dns_client_rule_get(struct dns_client_rule *rule)
  function _dns_client_rule_put (line 84) | static void _dns_client_rule_put(struct dns_client_rule *rule)
  function _config_client_rules_free (line 94) | static int _config_client_rules_free(struct dns_client_rules *client_rules)
  type client_roue_group_mac (line 115) | struct client_roue_group_mac
  type client_roue_group_mac (line 117) | struct client_roue_group_mac
  type client_roue_group_mac (line 133) | struct client_roue_group_mac
  type client_roue_group_mac (line 135) | struct client_roue_group_mac
  type client_roue_group_mac (line 149) | struct client_roue_group_mac
  type client_roue_group_mac (line 151) | struct client_roue_group_mac
  type client_rule (line 159) | enum client_rule
  function _config_client_rule_add_callback (line 160) | static int _config_client_rule_add_callback(const char *ip_cidr, void *p...
  function _config_client_rule_add (line 166) | static int _config_client_rule_add(const char *ip_cidr, enum client_rule...
  function _config_client_rule_flag_callback (line 243) | static int _config_client_rule_flag_callback(const char *ip_cidr, void *...
  function _config_client_rule_flag_set (line 249) | int _config_client_rule_flag_set(const char *ip_cidr, unsigned int flag,...
  function _config_client_rule_iter_free_cb (line 325) | static void _config_client_rule_iter_free_cb(radix_node_t *node, void *c...
  function _config_client_rules (line 341) | int _config_client_rules(void *data, int argc, char *argv[])
  function _config_client_rule_destroy_mac (line 478) | static void _config_client_rule_destroy_mac(void)
  function _config_client_rule_destroy (line 492) | void _config_client_rule_destroy(void)
  function _config_client_rule_group_add (line 498) | int _config_client_rule_group_add(const char *client, const char *group_...

FILE: src/dns_conf/client_subnet.c
  function _conf_client_subnet (line 25) | int _conf_client_subnet(char *subnet, struct dns_edns_client_subnet *ipv...
  function _conf_edns_client_subnet (line 89) | int _conf_edns_client_subnet(void *data, int argc, char *argv[])

FILE: src/dns_conf/client_subnet.h
  type dns_edns_client_subnet (line 31) | struct dns_edns_client_subnet
  type dns_edns_client_subnet (line 31) | struct dns_edns_client_subnet

FILE: src/dns_conf/cname.c
  function _conf_domain_rule_cname (line 25) | int _conf_domain_rule_cname(const char *domain, const char *cname)
  function _config_cname (line 64) | int _config_cname(void *data, int argc, char *argv[])

FILE: src/dns_conf/conf_file.c
  type conf_file_path (line 34) | struct conf_file_path {
  type hash_table (line 39) | struct hash_table
  function conf_file_table_init (line 41) | int conf_file_table_init(void)
  function conf_file_check_duplicate (line 48) | static int conf_file_check_duplicate(const char *conf_file)
  function conf_additional_file (line 73) | static int conf_additional_file(const char *conf_file)
  function _config_additional_file_callback (line 110) | static int _config_additional_file_callback(const char *file, void *priv)
  function config_additional_file (line 115) | int config_additional_file(void *data, int argc, char *argv[])
  function _config_file_hash_table_destroy (line 174) | void _config_file_hash_table_destroy(void)

FILE: src/dns_conf/ddns_domain.c
  function _config_ddns_domain (line 30) | int _config_ddns_domain(void *data, int argc, char *argv[])

FILE: src/dns_conf/dhcp_lease_dnsmasq.c
  function _conf_dhcp_lease_dnsmasq_add (line 31) | static int _conf_dhcp_lease_dnsmasq_add(const char *file)
  function _conf_dhcp_lease_dnsmasq_file (line 75) | int _conf_dhcp_lease_dnsmasq_file(void *data, int argc, char *argv[])
  function dns_server_check_update_hosts (line 96) | int dns_server_check_update_hosts(void)

FILE: src/dns_conf/dns64.c
  function _config_dns64 (line 23) | int _config_dns64(void *data, int argc, char *argv[])
  function _dns_conf_dns64_setup_ipv4only_arpa_rule (line 66) | static void _dns_conf_dns64_setup_ipv4only_arpa_rule(void)
  function _dns_conf_dns64_post (line 73) | void _dns_conf_dns64_post(void)

FILE: src/dns_conf/dns_conf.c
  type config_enum_list (line 65) | struct config_enum_list
  type dns_config (line 71) | struct dns_config
  type config_enum_list (line 73) | struct config_enum_list
  function _config_option_parser_filepath (line 78) | static int _config_option_parser_filepath(void *data, int argc, char *ar...
  function _config_log_level (line 90) | static int _config_log_level(void *data, int argc, char *argv[])
  function _dns_conf_setup_mdns (line 116) | static int _dns_conf_setup_mdns(void)
  function _config_server_name (line 125) | static int _config_server_name(void *data, int argc, char *argv[])
  type config_item (line 137) | struct config_item
  type config_item (line 256) | struct config_item
  function _conf_value_handler (line 261) | static int _conf_value_handler(const char *key, const char *value)
  function _conf_printf (line 274) | int _conf_printf(const char *key, const char *value, const char *file, i...
  function _dns_server_load_conf_init (line 316) | static int _dns_server_load_conf_init(void)
  function dns_server_load_exit (line 343) | void dns_server_load_exit(void)
  function _dns_conf_default_value_init (line 366) | static void _dns_conf_default_value_init(void)
  function _dns_conf_load_pre (line 400) | static int _dns_conf_load_pre(void)
  function _dns_conf_auto_set_cache_size (line 418) | static void _dns_conf_auto_set_cache_size(void)
  function _dns_conf_load_post (line 448) | static int _dns_conf_load_post(void)
  function dns_server_load_conf (line 485) | int dns_server_load_conf(const char *file)

FILE: src/dns_conf/dns_conf.h
  type config_item (line 29) | struct config_item
  type config_enum_list (line 33) | struct config_enum_list

FILE: src/dns_conf/dns_conf_group.c
  type dns_conf_group_info (line 26) | struct dns_conf_group_info
  type dns_conf_group_info (line 27) | struct dns_conf_group_info
  type dns_conf_rule (line 30) | struct dns_conf_rule
  function _config_rule_group_init (line 32) | int _config_rule_group_init(void)
  function _dns_conf_group_int (line 44) | __attribute__((unused)) int _dns_conf_group_int(int value, int *data)
  function _dns_conf_group_int_base (line 57) | __attribute__((unused)) int _dns_conf_group_int_base(int value, int *data)
  function _dns_conf_group_string (line 70) | __attribute__((unused)) int _dns_conf_group_string(const char *value, ch...
  function _dns_conf_group_yesno (line 83) | __attribute__((unused)) int _dns_conf_group_yesno(int value, int *data)
  function _dns_conf_group_size (line 96) | __attribute__((unused)) int _dns_conf_group_size(size_t value, size_t *d...
  function _dns_conf_group_ssize (line 109) | __attribute__((unused)) int _dns_conf_group_ssize(ssize_t value, ssize_t...
  function _dns_conf_group_enum (line 122) | __attribute__((unused)) int _dns_conf_group_enum(int value, int *data)
  type dns_conf_group (line 135) | struct dns_conf_group
  type dns_conf_group_info (line 144) | struct dns_conf_group_info
  function _config_set_current_group (line 149) | void _config_set_current_group(struct dns_conf_group_info *group_info)
  type dns_conf_group_info (line 158) | struct dns_conf_group_info
  function _config_current_group_pop (line 163) | void _config_current_group_pop(void)
  function _config_domain_rule_iter_copy (line 189) | static int _config_domain_rule_iter_copy(void *data, const unsigned char...
  function _config_rule_group_setup_value (line 221) | static int _config_rule_group_setup_value(struct dns_conf_group_info *gr...
  function _config_current_group_push (line 280) | int _config_current_group_push(const char *group_name, const char *inher...
  function _config_current_group_push_default (line 332) | int _config_current_group_push_default(void)
  function _config_current_group_pop_to (line 337) | int _config_current_group_pop_to(struct dns_conf_group_info *group_info)
  function _config_current_group_pop_to_default (line 346) | int _config_current_group_pop_to_default(void)
  function _config_current_group_pop_all (line 351) | int _config_current_group_pop_all(void)
  type dns_conf_group (line 369) | struct dns_conf_group
  type dns_conf_group (line 372) | struct dns_conf_group
  type dns_conf_group (line 388) | struct dns_conf_group
  type dns_conf_group (line 394) | struct dns_conf_group
  type dns_conf_group (line 402) | struct dns_conf_group
  type dns_conf_group (line 407) | struct dns_conf_group
  type dns_conf_group (line 409) | struct dns_conf_group
  function _config_rule_group_remove (line 435) | static void _config_rule_group_remove(struct dns_conf_group *rule_group)
  function _config_rule_group_destroy (line 448) | void _config_rule_group_destroy(void)
  function _dns_conf_group_post (line 462) | void _dns_conf_group_post(void)

FILE: src/dns_conf/dns_conf_group.h
  type dns_conf_group_info (line 29) | struct dns_conf_group_info {
  type dns_conf_rule (line 36) | struct dns_conf_rule
  type dns_conf_group (line 51) | struct dns_conf_group
  type dns_conf_group (line 53) | struct dns_conf_group
  type dns_conf_group_info (line 54) | struct dns_conf_group_info
  type dns_conf_group_info (line 55) | struct dns_conf_group_info
  type dns_conf_group_info (line 56) | struct dns_conf_group_info
  type dns_conf_group_info (line 62) | struct dns_conf_group_info

FILE: src/dns_conf/domain_rule.c
  function _get_required_capacity (line 35) | static inline uint8_t _get_required_capacity(enum domain_rule type, uint...
  type dns_domain_rule (line 58) | struct dns_domain_rule
  type dns_domain_rule (line 60) | struct dns_domain_rule
  type dns_rule (line 60) | struct dns_rule
  type dns_domain_rule (line 61) | struct dns_domain_rule
  type dns_domain_rule (line 77) | struct dns_domain_rule
  type dns_domain_rule (line 77) | struct dns_domain_rule
  type domain_rule (line 77) | enum domain_rule
  type dns_domain_rule (line 102) | struct dns_domain_rule
  type dns_rule (line 102) | struct dns_rule
  type dns_domain_rule (line 103) | struct dns_domain_rule
  type dns_rule (line 109) | struct dns_rule
  type dns_rule_info (line 115) | struct dns_rule_info {
  function _rule_address_ipv4_get_size (line 121) | static int _rule_address_ipv4_get_size(struct dns_rule *rule)
  function _rule_address_ipv6_get_size (line 126) | static int _rule_address_ipv6_get_size(struct dns_rule *rule)
  function _rule_https_clone (line 131) | static void _rule_https_clone(struct dns_rule *new_rule, struct dns_rule...
  function _rule_srv_clone (line 150) | static void _rule_srv_clone(struct dns_rule *new_rule, struct dns_rule *...
  type dns_rule_info (line 169) | struct dns_rule_info
  type dns_rule_flags (line 170) | struct dns_rule_flags
  type dns_rule_address_IPV4 (line 171) | struct dns_rule_address_IPV4
  type dns_rule_address_IPV6 (line 172) | struct dns_rule_address_IPV6
  type dns_nameserver_rule (line 173) | struct dns_nameserver_rule
  type dns_domain_check_orders (line 174) | struct dns_domain_check_orders
  type dns_ipset_rule (line 175) | struct dns_ipset_rule
  type dns_nftset_rule (line 176) | struct dns_nftset_rule
  type dns_ipset_rule (line 177) | struct dns_ipset_rule
  type dns_group_rule (line 178) | struct dns_group_rule
  type dns_nftset_rule (line 179) | struct dns_nftset_rule
  type dns_ipset_rule (line 180) | struct dns_ipset_rule
  type dns_https_record_rule (line 181) | struct dns_https_record_rule
  type dns_srv_record_rule (line 182) | struct dns_srv_record_rule
  type dns_response_mode_rule (line 183) | struct dns_response_mode_rule
  type dns_cname_rule (line 184) | struct dns_cname_rule
  type dns_ttl_rule (line 185) | struct dns_ttl_rule
  type domain_rule (line 188) | enum domain_rule
  type dns_rule (line 190) | struct dns_rule
  type domain_rule (line 211) | enum domain_rule
  type dns_rule (line 216) | struct dns_rule
  type dns_rule (line 216) | struct dns_rule
  type dns_rule (line 219) | struct dns_rule
  function _dns_rule_get (line 250) | void _dns_rule_get(struct dns_rule *rule)
  function _dns_rule_free (line 255) | static void _dns_rule_free(struct dns_rule *rule)
  function _dns_rule_put (line 281) | void _dns_rule_put(struct dns_rule *rule)
  type dns_domain_set_name_list (line 288) | struct dns_domain_set_name_list
  type dns_domain_set_name_list (line 291) | struct dns_domain_set_name_list
  function _config_domain_rule_set_each (line 304) | static int _config_domain_rule_set_each(const char *domain_set, set_rule...
  function _config_domain_rule_add_callback (line 334) | static int _config_domain_rule_add_callback(const char *domain, void *priv)
  function _config_setup_domain_key (line 340) | static int _config_setup_domain_key(const char *domain, char *domain_key...
  type dns_domain_rule (line 408) | struct dns_domain_rule
  function _config_domain_rule_free (line 420) | int _config_domain_rule_free(struct dns_domain_rule *domain_rule)
  function _config_domain_iter_free (line 442) | int _config_domain_iter_free(void *data, const unsigned char *key, uint3...
  function _config_domain_rule_delete_callback (line 448) | static int _config_domain_rule_delete_callback(const char *domain, void ...
  function _config_domain_rule_delete (line 453) | int _config_domain_rule_delete(const char *domain)
  function _config_domain_rule_flag_callback (line 480) | static int _config_domain_rule_flag_callback(const char *domain, void *p...
  function _config_domain_rule_flag_set (line 486) | int _config_domain_rule_flag_set(const char *domain, unsigned int flag, ...
  function _config_domain_rule_remove (line 565) | int _config_domain_rule_remove(const char *domain, enum domain_rule type)
  function _config_domain_rule_add (line 604) | int _config_domain_rule_add(const char *domain, enum domain_rule type, v...
  function _conf_domain_rule_rr_ttl (line 701) | static int _conf_domain_rule_rr_ttl(const char *domain, int ttl, int ttl...
  function _conf_domain_rule_no_serve_expired (line 734) | static int _conf_domain_rule_no_serve_expired(const char *domain)
  function _conf_domain_rule_delete (line 739) | static int _conf_domain_rule_delete(const char *domain)
  function _conf_domain_rule_no_cache (line 744) | static int _conf_domain_rule_no_cache(const char *domain)
  function _conf_domain_rule_enable_cache (line 749) | static int _conf_domain_rule_enable_cache(const char *domain)
  function _conf_domain_rule_no_ipalias (line 754) | static int _conf_domain_rule_no_ipalias(const char *domain)
  function _conf_domain_rule_no_ignore_ip (line 759) | static int _conf_domain_rule_no_ignore_ip(const char *domain)
  function _conf_domain_rule_response_mode (line 764) | int _conf_domain_rule_response_mode(char *domain, const char *mode)
  function _conf_domain_rule_speed_check (line 796) | int _conf_domain_rule_speed_check(char *domain, const char *mode)
  function _conf_domain_rule_group (line 822) | int _conf_domain_rule_group(const char *domain, const char *group_name)
  function _conf_domain_rule_dualstack_selection (line 864) | static int _conf_domain_rule_dualstack_selection(char *domain, const cha...
  function _config_domain_rules (line 884) | int _config_domain_rules(void *data, int argc, char *argv[])
  type domain_rule (line 1166) | enum domain_rule
  type dns_domain_rule (line 1168) | struct dns_domain_rule

FILE: src/dns_conf/domain_rule.h
  type domain_rule (line 31) | enum domain_rule
  type domain_rule (line 32) | enum domain_rule
  type dns_rule (line 33) | struct dns_rule
  type dns_rule (line 34) | struct dns_rule
  type domain_rule (line 36) | enum domain_rule
  type domain_rule (line 37) | enum domain_rule
  type domain_rule (line 42) | enum domain_rule
  type dns_domain_rule (line 43) | struct dns_domain_rule

FILE: src/dns_conf/domain_set.c
  type dns_domain_set_name_table (line 27) | struct dns_domain_set_name_table
  function _config_domain_set (line 29) | int _config_domain_set(void *data, int argc, char *argv[])
  function _config_domain_set_name_table_init (line 128) | void _config_domain_set_name_table_init(void)
  function _config_domain_set_name_table_destroy (line 133) | void _config_domain_set_name_table_destroy(void)

FILE: src/dns_conf/get_domain.c
  function _get_domain (line 24) | int _get_domain(char *value, char *domain, int max_domain_size, char **p...

FILE: src/dns_conf/group.c
  function _config_group_begin (line 27) | int _config_group_begin(void *data, int argc, char *argv[])
  function _config_group_end (line 72) | int _config_group_end(void *data, int argc, char *argv[])
  function _config_group_match (line 78) | int _config_group_match(void *data, int argc, char *argv[])

FILE: src/dns_conf/host_file.c
  type dns_hosts_table (line 30) | struct dns_hosts_table
  function _conf_hosts_file_add (line 33) | static int _conf_hosts_file_add(const char *file, void *priv)
  function _config_hosts_file (line 106) | int _config_hosts_file(void *data, int argc, char *argv[])
  function _config_host_table_init (line 121) | void _config_host_table_init(void)
  function _config_host_table_destroy (line 126) | void _config_host_table_destroy(int only_dynamic)
  type dns_hosts (line 145) | struct dns_hosts
  type dns_hosts (line 148) | struct dns_hosts
  function _conf_host_expand_local_domain (line 183) | static int _conf_host_expand_local_domain(struct dns_hosts *host)
  function _conf_host_add (line 223) | int _conf_host_add(const char *hostname, const char *ip, dns_hosts_type ...

FILE: src/dns_conf/https_record.c
  function _conf_domain_rule_https_copy_alpn (line 25) | static int _conf_domain_rule_https_copy_alpn(char *alpn_data, int max_al...
  function _conf_domain_rule_https_record (line 63) | int _conf_domain_rule_https_record(const char *domain, const char *host)
  function _config_https_record (line 222) | int _config_https_record(void *data, int argc, char *argv[])

FILE: src/dns_conf/ip_alias.c
  function _config_ip_alias_add_ip_callback (line 22) | static int _config_ip_alias_add_ip_callback(const char *ip_cidr, void *p...
  function _conf_ip_alias (line 27) | int _conf_ip_alias(const char *ip_cidr, const char *ips)
  function _config_ip_alias (line 83) | int _config_ip_alias(void *data, int argc, char *argv[])

FILE: src/dns_conf/ip_rule.c
  function _config_ip_rule_set_each (line 27) | int _config_ip_rule_set_each(const char *ip_set, set_rule_add_func callb...
  function _dns_iplist_ip_address_add (line 64) | static void _dns_iplist_ip_address_add(struct dns_iplist_ip_addresses *i...
  function _config_ip_rules (line 77) | int _config_ip_rules(void *data, int argc, char *argv[])
  function _config_ip_rules_free (line 155) | static int _config_ip_rules_free(struct dns_ip_rules *ip_rules)
  function radix_node_t (line 176) | static radix_node_t *_create_addr_node(const char *addr)
  function _config_ip_rule_flag_callback (line 204) | static int _config_ip_rule_flag_callback(const char *ip_cidr, void *priv)
  function _config_ip_rule_flag_set (line 210) | int _config_ip_rule_flag_set(const char *ip_cidr, unsigned int flag, uns...
  function _config_ip_rule_add_callback (line 267) | static int _config_ip_rule_add_callback(const char *ip_cidr, void *priv)
  function _config_ip_rule_add (line 273) | int _config_ip_rule_add(const char *ip_cidr, enum ip_rule type, void *rule)
  type ip_rule (line 330) | enum ip_rule
  type dns_ip_rule (line 332) | struct dns_ip_rule
  type ip_rule_flags (line 341) | struct ip_rule_flags
  type ip_rule_alias (line 344) | struct ip_rule_alias
  type ip_rule (line 360) | enum ip_rule
  function _dns_ip_rule_get (line 365) | void _dns_ip_rule_get(struct dns_ip_rule *rule)
  function _dns_ip_rule_put (line 370) | void _dns_ip_rule_put(struct dns_ip_rule *rule)
  function _config_ip_rule_alias_add_ip (line 385) | int _config_ip_rule_alias_add_ip(const char *ip, struct ip_rule_alias *i...
  function _config_blacklist_ip (line 427) | int _config_blacklist_ip(void *data, int argc, char *argv[])
  function _config_bogus_nxdomain (line 436) | int _config_bogus_nxdomain(void *data, int argc, char *argv[])
  function _config_ip_ignore (line 445) | int _config_ip_ignore(void *data, int argc, char *argv[])
  function _config_whitelist_ip (line 454) | int _config_whitelist_ip(void *data, int argc, char *argv[])
  function _config_ip_iter_free (line 463) | void _config_ip_iter_free(radix_node_t *node, void *cbctx)

FILE: src/dns_conf/ip_rule.h
  type ip_rule_alias (line 41) | struct ip_rule_alias
  type ip_rule (line 42) | enum ip_rule
  type ip_rule (line 44) | enum ip_rule
  type dns_ip_rule (line 45) | struct dns_ip_rule
  type dns_ip_rule (line 46) | struct dns_ip_rule

FILE: src/dns_conf/ip_set.c
  type dns_ip_set_name_table (line 27) | struct dns_ip_set_name_table
  function _config_ip_set (line 29) | int _config_ip_set(void *data, int argc, char *argv[])
  function _config_ip_set_name_table_init (line 130) | void _config_ip_set_name_table_init(void)
  function _config_ip_set_name_table_destroy (line 135) | void _config_ip_set_name_table_destroy(void)

FILE: src/dns_conf/ipset.c
  type dns_ipset_table (line 27) | struct dns_ipset_table {
  type dns_ipset_table (line 30) | struct dns_ipset_table
  function _config_ipset_init (line 32) | int _config_ipset_init(void)
  function _config_ipset_table_destroy (line 38) | void _config_ipset_table_destroy(void)
  type dns_ipset_name (line 54) | struct dns_ipset_name
  function _conf_domain_rule_ipset (line 82) | int _conf_domain_rule_ipset(char *domain, const char *ipsetname)
  function _config_ipset_setvalue (line 157) | static int _config_ipset_setvalue(struct dns_ipset_names *ipsets, const ...
  function _config_ipset (line 221) | int _config_ipset(void *data, int argc, char *argv[])
  function _config_ipset_no_speed (line 246) | int _config_ipset_no_speed(void *data, int argc, char *argv[])

FILE: src/dns_conf/local_domain.c
  function _config_local_domain (line 31) | int _config_local_domain(void *data, int argc, char *argv[])

FILE: src/dns_conf/nameserver.c
  function _conf_domain_rule_nameserver (line 24) | int _conf_domain_rule_nameserver(const char *domain, const char *group_n...
  function _config_nameserver (line 66) | int _config_nameserver(void *data, int argc, char *argv[])

FILE: src/dns_conf/nftset.c
  type dns_nftset_table (line 26) | struct dns_nftset_table {
  type dns_nftset_table (line 29) | struct dns_nftset_table
  function _config_nftset_table_destroy (line 31) | void _config_nftset_table_destroy(void)
  type dns_nftset_name (line 44) | struct dns_nftset_name
  type dns_nftset_name (line 47) | struct dns_nftset_name
  function _conf_domain_rule_nftset (line 84) | int _conf_domain_rule_nftset(char *domain, const char *nftsetname)
  function _config_nftset_setvalue (line 182) | static int _config_nftset_setvalue(struct dns_nftset_names *nftsets, con...
  function _config_nftset (line 282) | int _config_nftset(void *data, int argc, char *argv[])
  function _config_nftset_no_speed (line 302) | int _config_nftset_no_speed(void *data, int argc, char *argv[])

FILE: src/dns_conf/nftset.h
  type dns_nftset_name (line 29) | struct dns_nftset_name

FILE: src/dns_conf/plugin.c
  type dns_conf_plugin_table (line 25) | struct dns_conf_plugin_table
  function _config_plugin_iter_free (line 27) | static int _config_plugin_iter_free(void *data, const unsigned char *key...
  type dns_conf_plugin (line 33) | struct dns_conf_plugin
  type dns_conf_plugin (line 36) | struct dns_conf_plugin
  function _config_plugin (line 60) | int _config_plugin(void *data, int argc, char *argv[])
  function _config_plugin_conf_add (line 156) | int _config_plugin_conf_add(const char *key, const char *value)
  function _config_plugin_table_init (line 184) | void _config_plugin_table_init(void)
  function _config_plugin_table_destroy (line 190) | void _config_plugin_table_destroy(void)
  function _config_plugin_table_conf_destroy (line 203) | void _config_plugin_table_conf_destroy(void)
  function dns_conf_clear_all_plugin_conf (line 209) | void dns_conf_clear_all_plugin_conf(void)

FILE: src/dns_conf/proxy_names.c
  type dns_proxy_table (line 23) | struct dns_proxy_table
  type dns_proxy_names (line 25) | struct dns_proxy_names
  type dns_proxy_names (line 28) | struct dns_proxy_names
  type dns_proxy_names (line 42) | struct dns_proxy_names
  type dns_proxy_names (line 45) | struct dns_proxy_names
  function _dns_conf_proxy_servers_add (line 72) | int _dns_conf_proxy_servers_add(const char *proxy_name, struct dns_proxy...
  type dns_proxy_names (line 88) | struct dns_proxy_names
  function _config_proxy_table_destroy (line 98) | void _config_proxy_table_destroy(void)

FILE: src/dns_conf/proxy_names.h
  type dns_proxy_servers (line 29) | struct dns_proxy_servers

FILE: src/dns_conf/proxy_server.c
  function _config_proxy_server (line 25) | int _config_proxy_server(void *data, int argc, char *argv[])

FILE: src/dns_conf/ptr.c
  type dns_ptr_table (line 25) | struct dns_ptr_table
  type dns_ptr (line 27) | struct dns_ptr
  type dns_ptr (line 30) | struct dns_ptr
  function _conf_ptr_add (line 60) | int _conf_ptr_add(const char *hostname, const char *ip, int is_dynamic)
  function _config_ptr_table_init (line 127) | void _config_ptr_table_init(void)
  function _config_ptr_table_destroy (line 132) | void _config_ptr_table_destroy(int only_dynamic)

FILE: src/dns_conf/qtype_soa.c
  function _conf_qtype_soa (line 23) | static int _conf_qtype_soa(uint8_t *soa_table, int argc, char *argv[])
  function _config_qtype_soa (line 91) | int _config_qtype_soa(void *data, int argc, char *argv[])

FILE: src/dns_conf/server.c
  function _config_server (line 28) | static int _config_server(int argc, char *argv[], dns_server_type_t type...
  function _config_server_udp (line 360) | int _config_server_udp(void *data, int argc, char *argv[])
  function _config_server_tcp (line 365) | int _config_server_tcp(void *data, int argc, char *argv[])
  function _config_server_tls (line 370) | int _config_server_tls(void *data, int argc, char *argv[])
  function _config_server_https (line 375) | int _config_server_https(void *data, int argc, char *argv[])
  function _config_server_quic (line 383) | int _config_server_quic(void *data, int argc, char *argv[])
  function _config_server_http3 (line 391) | int _config_server_http3(void *data, int argc, char *argv[])

FILE: src/dns_conf/server_group.c
  type dns_group_table (line 24) | struct dns_group_table
  type dns_server_groups (line 26) | struct dns_server_groups
  type dns_server_groups (line 29) | struct dns_server_groups
  function _dns_conf_get_group_set (line 55) | int _dns_conf_get_group_set(const char *group_name, struct dns_servers *...
  type dns_server_groups (line 84) | struct dns_server_groups
  function _config_group_table_init (line 94) | void _config_group_table_init(void)
  function _config_group_table_destroy (line 99) | void _config_group_table_destroy(void)

FILE: src/dns_conf/server_group.h
  type dns_servers (line 29) | struct dns_servers
  type dns_server_groups (line 31) | struct dns_server_groups
  type dns_conf_group (line 35) | struct dns_conf_group
  type dns_conf_group (line 37) | struct dns_conf_group
  type dns_conf_group (line 39) | struct dns_conf_group
  type dns_conf_group (line 41) | struct dns_conf_group

FILE: src/dns_conf/set_file.c
  function _config_set_rule_each_from_list (line 33) | int _config_set_rule_each_from_list(const char *file, set_rule_add_func ...
  function _config_foreach_file (line 94) | int _config_foreach_file(const char *file_pattern, int (*callback)(const...

FILE: src/dns_conf/smartdns_domain.c
  function _config_setup_smartdns_domain (line 24) | void _config_setup_smartdns_domain(void)

FILE: src/dns_conf/speed_check_mode.c
  function _config_speed_check_mode_clear (line 31) | static void _config_speed_check_mode_clear(struct dns_domain_check_order...
  function _config_speed_check_mode_parser (line 36) | int _config_speed_check_mode_parser(struct dns_domain_check_orders *chec...
  function _config_speed_check_mode (line 111) | int _config_speed_check_mode(void *data, int argc, char *argv[])
  function _dns_conf_speed_check_mode_verify (line 124) | int _dns_conf_speed_check_mode_verify(void)
  function _dns_ping_cap_check (line 188) | int _dns_ping_cap_check(void)

FILE: src/dns_conf/speed_check_mode.h
  type dns_domain_check_orders (line 35) | struct dns_domain_check_orders

FILE: src/dns_conf/srv_record.c
  function _confg_srv_record_add (line 26) | static int _confg_srv_record_add(const char *domain, const char *host, u...
  function _config_srv_record (line 73) | int _config_srv_record(void *data, int argc, char *argv[])

FILE: src/dns_plugin.c
  type dns_plugin_ops (line 36) | struct dns_plugin_ops {
  type dns_plugin (line 42) | struct dns_plugin {
  type dns_plugins (line 53) | struct dns_plugins {
  type dns_plugins (line 59) | struct dns_plugins
  function smartdns_plugin_func_server_recv (line 62) | int smartdns_plugin_func_server_recv(struct dns_packet *packet, unsigned...
  function smartdns_plugin_func_server_complete_request (line 91) | void smartdns_plugin_func_server_complete_request(struct dns_request *re...
  function smartdns_plugin_func_server_log_callback (line 113) | void smartdns_plugin_func_server_log_callback(smartdns_log_level level, ...
  function smartdns_plugin_func_server_audit_log_callback (line 135) | void smartdns_plugin_func_server_audit_log_callback(const char *msg, int...
  function smartdns_operations_register (line 157) | int smartdns_operations_register(const struct smartdns_operations *opera...
  function smartdns_operations_unregister (line 174) | int smartdns_operations_unregister(const struct smartdns_operations *ope...
  type dns_plugin (line 194) | struct dns_plugin
  type dns_plugin (line 196) | struct dns_plugin
  function _dns_plugin_load_library (line 213) | static int _dns_plugin_load_library(struct dns_plugin *plugin)
  function _dns_plugin_unload_library (line 294) | static int _dns_plugin_unload_library(struct dns_plugin *plugin)
  type dns_plugin (line 312) | struct dns_plugin
  type dns_plugin (line 314) | struct dns_plugin
  type dns_plugin (line 321) | struct dns_plugin
  type dns_plugin (line 321) | struct dns_plugin
  function _dns_plugin_remove (line 330) | static int _dns_plugin_remove(struct dns_plugin *plugin)
  function dns_plugin_get_argc (line 341) | int dns_plugin_get_argc(struct dns_plugin *plugin)
  type dns_plugin (line 346) | struct dns_plugin
  function dns_plugin_add (line 351) | int dns_plugin_add(const char *plugin_file, int argc, const char *args, ...
  function dns_plugin_remove (line 384) | int dns_plugin_remove(const char *plugin_file)
  function _dns_plugin_remove_all_ops (line 396) | static int _dns_plugin_remove_all_ops(void)
  function _dns_plugin_remove_all (line 412) | static int _dns_plugin_remove_all(void)
  function dns_server_plugin_init (line 434) | int dns_server_plugin_init(void)
  function dns_server_plugin_exit (line 450) | void dns_server_plugin_exit(void)
  function smartdns_plugin_log (line 464) | void smartdns_plugin_log(smartdns_log_level level, const char *file, int...
  function smartdns_plugin_can_log (line 469) | int smartdns_plugin_can_log(smartdns_log_level level)
  function smartdns_plugin_log_setlevel (line 474) | void smartdns_plugin_log_setlevel(smartdns_log_level level)
  function smartdns_plugin_log_getlevel (line 479) | int smartdns_plugin_log_getlevel(void)
  function smartdns_plugin_is_audit_enabled (line 484) | int smartdns_plugin_is_audit_enabled(void)
  function smartdns_plugin_clear_all_config (line 494) | void smartdns_plugin_clear_all_config(void)

FILE: src/dns_server/address.c
  function _dns_server_is_adblock_ipv6 (line 27) | int _dns_server_is_adblock_ipv6(const unsigned char addr[16])
  function _dns_server_address_generate_order (line 44) | int _dns_server_address_generate_order(int orders[], int order_num, int ...
  function _dns_server_process_address (line 70) | int _dns_server_process_address(struct dns_request *request)
  function _dns_ip_address_check_add (line 143) | int _dns_ip_address_check_add(struct dns_request *request, char *cname, ...
  function _dns_server_select_possible_ipaddress (line 209) | void _dns_server_select_possible_ipaddress(struct dns_request *request)
  type dns_ip_address (line 287) | struct dns_ip_address
  type dns_request (line 287) | struct dns_request
  type dns_ip_address (line 290) | struct dns_ip_address
  type dns_ip_address (line 291) | struct dns_ip_address

FILE: src/dns_server/address.h
  type dns_request (line 28) | struct dns_request
  type dns_request (line 30) | struct dns_request
  type dns_ip_address (line 31) | struct dns_ip_address
  type dns_ip_address (line 33) | struct dns_ip_address
  type dns_request (line 33) | struct dns_request
  type dns_request (line 35) | struct dns_request

FILE: src/dns_server/answer.c
  function _dns_server_process_answer_A_IP (line 30) | static int _dns_server_process_answer_A_IP(struct dns_request *request, ...
  function _dns_server_process_answer_AAAA_IP (line 101) | static int _dns_server_process_answer_AAAA_IP(struct dns_request *reques...
  function _dns_server_process_answer_A (line 173) | static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_...
  function _dns_server_process_answer_AAAA (line 201) | static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct d...
  function _dns_server_process_answer_HTTPS (line 233) | static int _dns_server_process_answer_HTTPS(struct dns_rrs *rrs, struct ...
  function _dns_server_process_answer (line 356) | int _dns_server_process_answer(struct dns_request *request, const char *...

FILE: src/dns_server/answer.h
  type dns_request (line 28) | struct dns_request
  type dns_packet (line 28) | struct dns_packet

FILE: src/dns_server/audit.c
  function _dns_server_audit_log (line 28) | void _dns_server_audit_log(struct dns_server_post_context *context)
  function _dns_server_audit_syslog (line 155) | static int _dns_server_audit_syslog(struct tlog_log *log, const char *bu...
  function _dns_server_audit_output_callback (line 161) | static int _dns_server_audit_output_callback(struct tlog_log *log, const...
  function _dns_server_audit_init (line 172) | int _dns_server_audit_init(void)

FILE: src/dns_server/audit.h
  type dns_server_post_context (line 28) | struct dns_server_post_context

FILE: src/dns_server/cache.c
  function _dns_server_expired_cache_ttl (line 33) | int _dns_server_expired_cache_ttl(struct dns_cache *cache, int serve_exp...
  function _dns_cache_is_specify_packet (line 38) | static int _dns_cache_is_specify_packet(int qtype)
  function _dns_server_get_cache_timeout (line 55) | static int _dns_server_get_cache_timeout(struct dns_request *request, st...
  function _dns_server_request_update_cache (line 127) | int _dns_server_request_update_cache(struct dns_request *request, int sp...
  function _dns_cache_cname_packet (line 182) | int _dns_cache_cname_packet(struct dns_server_post_context *context)
  function _dns_cache_packet (line 330) | int _dns_cache_packet(struct dns_server_post_context *context)
  function _dns_cache_specify_packet (line 378) | int _dns_cache_specify_packet(struct dns_server_post_context *context)
  function _dns_cache_try_keep_old_cache (line 387) | int _dns_cache_try_keep_old_cache(struct dns_request *request)
  function _dns_server_process_cache_packet (line 397) | static int _dns_server_process_cache_packet(struct dns_request *request,...
  function _dns_server_process_cache_data (line 456) | static int _dns_server_process_cache_data(struct dns_request *request, s...
  function _dns_server_process_cache (line 471) | int _dns_server_process_cache(struct dns_request *request)
  function _dns_server_save_cache_to_file (line 589) | void _dns_server_save_cache_to_file(void)
  function dns_cache_tmout_action_t (line 650) | static dns_cache_tmout_action_t _dns_server_cache_expired(struct dns_cac...
  function _dns_server_cache_init (line 669) | int _dns_server_cache_init(void)
  function _dns_server_cache_save (line 697) | int _dns_server_cache_save(int check_lock)

FILE: src/dns_server/cache.h
  type dns_request (line 35) | struct dns_request
  type dns_server_post_context (line 37) | struct dns_server_post_context
  type dns_request (line 39) | struct dns_request
  type dns_cache_data (line 40) | struct dns_cache_data
  type dns_server_post_context (line 42) | struct dns_server_post_context
  type dns_request (line 44) | struct dns_request
  type dns_server_post_context (line 46) | struct dns_server_post_context
  type dns_cache (line 48) | struct dns_cache

FILE: src/dns_server/client_rule.c
  function _dns_server_request_set_client_rules (line 22) | int _dns_server_request_set_client_rules(struct dns_request *request, st...

FILE: src/dns_server/client_rule.h
  type dns_request (line 28) | struct dns_request
  type dns_client_rules (line 28) | struct dns_client_rules

FILE: src/dns_server/cname.c
  function DNS_CHILD_POST_RESULT (line 23) | static DNS_CHILD_POST_RESULT _dns_server_process_cname_callback(struct d...
  function _dns_server_process_cname_pre (line 37) | int _dns_server_process_cname_pre(struct dns_request *request)
  function _dns_server_process_cname (line 76) | int _dns_server_process_cname(struct dns_request *request)

FILE: src/dns_server/cname.h
  type dns_request (line 28) | struct dns_request
  type dns_request (line 30) | struct dns_request

FILE: src/dns_server/connection.c
  function _dns_server_epoll_ctl (line 29) | int _dns_server_epoll_ctl(struct dns_server_conn_head *head, int op, uin...
  function _dns_server_conn_release (line 44) | void _dns_server_conn_release(struct dns_server_conn_head *conn)
  function _dns_server_conn_get (line 96) | void _dns_server_conn_get(struct dns_server_conn_head *conn)
  function _dns_server_close_socket (line 107) | void _dns_server_close_socket(void)
  function _dns_server_close_socket_server (line 131) | void _dns_server_close_socket_server(void)
  function _dns_server_client_touch (line 159) | void _dns_server_client_touch(struct dns_server_conn_head *conn)
  function _dns_server_client_close (line 164) | int _dns_server_client_close(struct dns_server_conn_head *conn)
  function _dns_server_update_request_connection_timeout (line 187) | int _dns_server_update_request_connection_timeout(struct dns_server_conn...
  function _dns_server_conn_head_init (line 214) | void _dns_server_conn_head_init(struct dns_server_conn_head *conn, int f...
  function _dns_server_set_flags (line 223) | int _dns_server_set_flags(struct dns_server_conn_head *head, struct dns_...

FILE: src/dns_server/connection.h
  type dns_server_conn_head (line 30) | struct dns_server_conn_head
  type dns_server_conn_head (line 32) | struct dns_server_conn_head
  type dns_server_conn_head (line 34) | struct dns_server_conn_head
  type dns_bind_ip (line 34) | struct dns_bind_ip
  type dns_server_conn_head (line 36) | struct dns_server_conn_head
  type dns_server_conn_head (line 38) | struct dns_server_conn_head
  type dns_server_conn_head (line 40) | struct dns_server_conn_head
  type dns_server_conn_head (line 42) | struct dns_server_conn_head
  type dns_server_conn_head (line 46) | struct dns_server_conn_head

FILE: src/dns_server/context.c
  function _dns_server_post_context_init (line 32) | void _dns_server_post_context_init(struct dns_server_post_context *conte...
  function _dns_server_context_add_ip (line 43) | static void _dns_server_context_add_ip(struct dns_server_post_context *c...
  function _dns_server_post_context_init_from (line 52) | void _dns_server_post_context_init_from(struct dns_server_post_context *...
  function _dns_rrs_result_log (line 65) | static void _dns_rrs_result_log(struct dns_server_post_context *context,...
  function _dns_rrs_add_all_best_ip (line 89) | static int _dns_rrs_add_all_best_ip(struct dns_server_post_context *cont...
  function _dns_server_add_srv (line 178) | static int _dns_server_add_srv(struct dns_server_post_context *context)
  function _dns_add_rrs_ip_hint (line 195) | static int _dns_add_rrs_ip_hint(struct dns_server_post_context *context,...
  function _dns_add_rrs_HTTPS (line 257) | static int _dns_add_rrs_HTTPS(struct dns_server_post_context *context)
  function _dns_add_rrs (line 323) | static int _dns_add_rrs(struct dns_server_post_context *context)
  function _dns_setup_dns_packet (line 401) | static int _dns_setup_dns_packet(struct dns_server_post_context *context)
  function _dns_setup_dns_raw_packet (line 442) | static int _dns_setup_dns_raw_packet(struct dns_server_post_context *con...
  function _dns_result_callback (line 456) | static int _dns_result_callback(struct dns_server_post_context *context)
  function _dns_server_setup_ipset_nftset_packet (line 503) | static int _dns_server_setup_ipset_nftset_packet(struct dns_server_post_...
  function _dns_result_child_post (line 692) | static int _dns_result_child_post(struct dns_server_post_context *context)
  function _dns_request_update_id_ttl_domain (line 740) | static int _dns_request_update_id_ttl_domain(struct dns_server_post_cont...
  function _dns_request_post (line 778) | int _dns_request_post(struct dns_server_post_context *context)
  function _dns_server_get_answer (line 853) | int _dns_server_get_answer(struct dns_server_post_context *context)
  function _dns_cache_reply_packet (line 985) | int _dns_cache_reply_packet(struct dns_server_post_context *context)
  function _dns_server_reply_passthrough (line 1037) | int _dns_server_reply_passthrough(struct dns_server_post_context *context)

FILE: src/dns_server/context.h
  type dns_server_post_context (line 28) | struct dns_server_post_context
  type dns_server_post_context (line 30) | struct dns_server_post_context
  type dns_request (line 30) | struct dns_request
  type dns_server_post_context (line 32) | struct dns_server_post_context
  type dns_server_post_context (line 34) | struct dns_server_post_context
  type dns_server_post_context (line 36) | struct dns_server_post_context
  type dns_server_post_context (line 38) | struct dns_server_post_context
  type dns_request (line 38) | struct dns_request
  type dns_packet (line 39) | struct dns_packet

FILE: src/dns_server/ddr.c
  type dns_bind_ip (line 28) | struct dns_bind_ip
  function _ddr_extract_local_addresses (line 44) | static void _ddr_extract_local_addresses(const struct sockaddr_storage *...
  function _ddr_build_svcb_record (line 70) | static int _ddr_build_svcb_record(struct dns_packet *packet, const char ...
  function _dns_server_process_DDR (line 110) | int _dns_server_process_DDR(struct dns_request *request)

FILE: src/dns_server/ddr.h
  type dns_request (line 28) | struct dns_request

FILE: src/dns_server/dns64.c
  function _dns_server_is_dns64_request (line 34) | int _dns_server_is_dns64_request(struct dns_request *request)
  function _dns_server_process_ipv4only_arpa (line 55) | static int _dns_server_process_ipv4only_arpa(struct dns_request *request)
  function _dns_server_process_dns64_callback (line 99) | static enum DNS_CHILD_POST_RESULT
  function _dns_server_process_dns64 (line 195) | int _dns_server_process_dns64(struct dns_request *request)

FILE: src/dns_server/dns64.h
  type dns_request (line 28) | struct dns_request

FILE: src/dns_server/dns_server.c
  type dns_server (line 70) | struct dns_server
  function _dns_server_wakeup_thread (line 72) | static void _dns_server_wakeup_thread(void)
  function _dns_server_forward_request (line 79) | static int _dns_server_forward_request(unsigned char *inpacket, int inpa...
  function _dns_reply_inpacket (line 84) | int _dns_reply_inpacket(struct dns_request *request, unsigned char *inpa...
  function _dns_server_resolve_callback_reply_passthrough (line 111) | static int _dns_server_resolve_callback_reply_passthrough(struct dns_req...
  function dns_server_resolve_callback (line 134) | static int dns_server_resolve_callback(const char *domain, dns_result_ty...
  function dns_server_get_server_name (line 202) | int dns_server_get_server_name(char *name, int name_len)
  function _dns_server_do_query (line 242) | int _dns_server_do_query(struct dns_request *request, int skip_notify_ev...
  function _dns_server_reply_format_error (line 380) | static int _dns_server_reply_format_error(struct dns_request *request, s...
  function _dns_server_recv (line 422) | int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *i...
  function dns_server_query (line 523) | int dns_server_query(const char *domain, int qtype, struct dns_server_qu...
  function _dns_server_process (line 556) | static int _dns_server_process(struct dns_server_conn_head *conn, struct...
  function _dns_server_socket (line 600) | static int _dns_server_socket(void)
  function _dns_server_check_need_exit (line 641) | static void _dns_server_check_need_exit(void)
  function _dns_server_period_run_second (line 657) | static void _dns_server_period_run_second(void)
  function _dns_server_period_run (line 680) | static void _dns_server_period_run(unsigned int msec)
  function dns_server_run (line 718) | int dns_server_run(void)
  function dns_server_start (line 809) | int dns_server_start(void)
  function _dns_server_init_wakeup_event (line 828) | static int _dns_server_init_wakeup_event(void)
  function dns_server_init (line 853) | int dns_server_init(void)
  function dns_server_stop (line 947) | void dns_server_stop(void)
  function dns_server_exit (line 953) | void dns_server_exit(void)

FILE: src/dns_server/dns_server.h
  type DNS_CONN_TYPE (line 72) | typedef enum {
  type DNS_CHILD_POST_RESULT (line 83) | typedef enum DNS_CHILD_POST_RESULT {
  type rule_walk_args (line 90) | struct rule_walk_args {
  type neighbor_enum_args (line 98) | struct neighbor_enum_args {
  type neighbor_cache_item (line 104) | struct neighbor_cache_item {
  type neighbor_cache (line 114) | struct neighbor_cache {
  type local_addr_cache_item (line 121) | struct local_addr_cache_item {
  type local_addr_cache (line 127) | struct local_addr_cache {
  type dns_conn_buf (line 132) | struct dns_conn_buf {
  type dns_server_conn_head (line 138) | struct dns_server_conn_head {
  type dns_server_post_context (line 149) | struct dns_server_post_context {
  type dns_server_client_status (line 176) | typedef enum dns_server_client_status {
  type dns_server_conn_udp (line 184) | struct dns_server_conn_udp {
  type dns_server_conn_tcp_server (line 190) | struct dns_server_conn_tcp_server {
  type dns_server_conn_tls_server (line 194) | struct dns_server_conn_tls_server {
  type dns_server_conn_tcp_client (line 199) | struct dns_server_conn_tcp_client {
  type dns_server_conn_tls_client (line 213) | struct dns_server_conn_tls_client {
  type dns_ip_address (line 223) | struct dns_ip_address {
  type dns_request_pending_list (line 233) | struct dns_request_pending_list {
  type dns_request_domain_rule (line 243) | struct dns_request_domain_rule {
  type DNS_CHILD_POST_RESULT (line 249) | typedef DNS_CHILD_POST_RESULT (*child_request_callback)(struct dns_reque...
  type dns_request_https (line 252) | struct dns_request_https {
  type dns_request_srv (line 270) | struct dns_request_srv {
  type dns_request (line 278) | struct dns_request {
  type dns_server (line 406) | struct dns_server {
  type dns_server (line 430) | struct dns_server
  type dns_server_conn_head (line 432) | struct dns_server_conn_head
  type sockaddr_storage (line 433) | struct sockaddr_storage
  type sockaddr_storage (line 433) | struct sockaddr_storage
  type dns_request (line 436) | struct dns_request
  type dns_request (line 438) | struct dns_request

FILE: src/dns_server/dualstack.c
  function dns_is_ipv6_ready (line 30) | int dns_is_ipv6_ready(void)
  function dns_server_check_ipv6_ready (line 35) | void dns_server_check_ipv6_ready(void)
  function _dns_server_set_dualstack_selection (line 109) | void _dns_server_set_dualstack_selection(struct dns_request *request)
  function _dns_server_check_complete_dualstack (line 145) | static void _dns_server_check_complete_dualstack(struct dns_request *req...
  function _dns_server_force_dualstack (line 173) | int _dns_server_force_dualstack(struct dns_request *request)
  function dns_server_dualstack_callback (line 217) | static int dns_server_dualstack_callback(const struct dns_result *result...
  function _dns_server_query_dualstack (line 237) | int _dns_server_query_dualstack(struct dns_request *request)

FILE: src/dns_server/dualstack.h
  type dns_request (line 30) | struct dns_request
  type dns_request (line 32) | struct dns_request
  type dns_request (line 34) | struct dns_request

FILE: src/dns_server/ip_rule.c
  type dns_client_rules (line 25) | struct dns_client_rules
  type sockaddr_storage (line 25) | struct sockaddr_storage
  type dns_client_rules (line 30) | struct dns_client_rules
  type dns_ip_rules (line 56) | struct dns_ip_rules
  type dns_request (line 56) | struct dns_request
  type dns_ip_rules (line 61) | struct dns_ip_rules
  function _dns_server_ip_rule_check (line 96) | static int _dns_server_ip_rule_check(struct dns_request *request, struct...
  function _dns_server_process_ip_alias (line 159) | int _dns_server_process_ip_alias(struct dns_request *request, struct dns...
  function _dns_server_process_ip_rule (line 188) | int _dns_server_process_ip_rule(struct dns_request *request, unsigned ch...

FILE: src/dns_server/ip_rule.h
  type dns_request (line 28) | struct dns_request
  type dns_iplist_ip_addresses (line 29) | struct dns_iplist_ip_addresses
  type dns_request (line 31) | struct dns_request
  type dns_iplist_ip_addresses (line 31) | struct dns_iplist_ip_addresses
  type dns_client_rules (line 34) | struct dns_client_rules
  type sockaddr_storage (line 34) | struct sockaddr_storage

FILE: src/dns_server/ipset_nftset.c
  function _dns_server_add_ipset_nftset (line 24) | void _dns_server_add_ipset_nftset(struct dns_request *request, struct dn...
  type dns_request (line 65) | struct dns_request
  type domain_rule (line 65) | enum domain_rule

FILE: src/dns_server/ipset_nftset.h
  type dns_request (line 28) | struct dns_request
  type dns_ipset_rule (line 28) | struct dns_ipset_rule
  type dns_nftset_rule (line 29) | struct dns_nftset_rule
  type dns_request (line 32) | struct dns_request
  type domain_rule (line 32) | enum domain_rule

FILE: src/dns_server/local_addr.c
  function _dns_server_local_addr_cache_add (line 29) | static void _dns_server_local_addr_cache_add(unsigned char *netaddr, int...
  function _dns_server_local_addr_cache_del (line 67) | static void _dns_server_local_addr_cache_del(unsigned char *netaddr, int...
  function _dns_server_process_local_addr_cache (line 89) | void _dns_server_process_local_addr_cache(int fd_netlink, struct epoll_e...
  function _dns_server_local_addr_cache_item_free (line 153) | static void _dns_server_local_addr_cache_item_free(radix_node_t *node, v...
  function _dns_server_local_addr_cache_destroy (line 169) | int _dns_server_local_addr_cache_destroy(void)
  function _dns_server_local_addr_cache_init (line 184) | int _dns_server_local_addr_cache_init(void)

FILE: src/dns_server/local_addr.h
  type epoll_event (line 32) | struct epoll_event

FILE: src/dns_server/mdns.c
  function _dns_server_need_append_mdns_local_cname (line 23) | void _dns_server_need_append_mdns_local_cname(struct dns_request *request)
  function _dns_server_mdns_query_setup_server_group (line 48) | void _dns_server_mdns_query_setup_server_group(struct dns_request *reque...
  function _dns_server_mdns_query_setup (line 59) | int _dns_server_mdns_query_setup(struct dns_request *request, const char...

FILE: src/dns_server/mdns.h
  type dns_request (line 28) | struct dns_request
  type dns_request (line 30) | struct dns_request
  type dns_request (line 32) | struct dns_request

FILE: src/dns_server/neighbor.c
  function dns_server_enable_update_neighbor_cache (line 29) | void dns_server_enable_update_neighbor_cache(int enable)
  function _dns_server_neighbor_cache_free_item (line 41) | static void _dns_server_neighbor_cache_free_item(struct neighbor_cache_i...
  function _dns_server_neighbor_cache_remove_all (line 49) | void _dns_server_neighbor_cache_remove_all(void)
  function _dns_server_neighbor_cache_init (line 63) | int _dns_server_neighbor_cache_init(void)
  function _dns_server_neighbor_cache_free_last_used_item (line 77) | static void _dns_server_neighbor_cache_free_last_used_item(void)
  type neighbor_cache_item (line 93) | struct neighbor_cache_item
  type neighbor_cache_item (line 95) | struct neighbor_cache_item
  function _dns_server_neighbor_cache_add (line 116) | static int _dns_server_neighbor_cache_add(const uint8_t *net_addr, int n...
  function _dns_server_neighbors_callback (line 156) | static int _dns_server_neighbors_callback(const uint8_t *net_addr, int n...
  function _dns_server_neighbor_cache_is_valid (line 175) | static int _dns_server_neighbor_cache_is_valid(struct neighbor_cache_ite...
  type dns_client_rules (line 198) | struct dns_client_rules
  type client_roue_group_mac (line 200) | struct client_roue_group_mac
  type neighbor_cache_item (line 201) | struct neighbor_cache_item
  type neighbor_enum_args (line 204) | struct neighbor_enum_args
  type sockaddr_storage (line 250) | struct sockaddr_storage
  type sockaddr_in (line 254) | struct sockaddr_in
  type sockaddr_in (line 254) | struct sockaddr_in
  type sockaddr (line 257) | struct sockaddr
  type sockaddr_in (line 257) | struct sockaddr_in
  type sockaddr_in6 (line 259) | struct sockaddr_in6
  type sockaddr_in6 (line 259) | struct sockaddr_in6
  type sockaddr (line 262) | struct sockaddr
  type sockaddr_in6 (line 262) | struct sockaddr_in6

FILE: src/dns_server/neighbor.h
  type neighbor_cache_item (line 28) | struct neighbor_cache_item
  type dns_client_rules (line 30) | struct dns_client_rules

FILE: src/dns_server/prefetch.c
  function _dns_server_prefetch_request (line 26) | int _dns_server_prefetch_request(char *domain, dns_type_t qtype, struct ...
  function dns_cache_tmout_action_t (line 59) | dns_cache_tmout_action_t _dns_server_prefetch_domain(struct dns_conf_gro...
  function dns_cache_tmout_action_t (line 83) | dns_cache_tmout_action_t _dns_server_prefetch_expired_domain(struct dns_...

FILE: src/dns_server/prefetch.h
  type dns_server_query_option (line 29) | struct dns_server_query_option
  type dns_conf_group (line 32) | struct dns_conf_group
  type dns_cache (line 32) | struct dns_cache
  type dns_conf_group (line 34) | struct dns_conf_group
  type dns_cache (line 35) | struct dns_cache

FILE: src/dns_server/ptr.c
  function _dns_server_is_private_address (line 29) | static int _dns_server_is_private_address(const unsigned char *addr, int...
  function _dns_server_get_inet_by_addr (line 44) | int _dns_server_get_inet_by_addr(struct sockaddr_storage *localaddr, str...
  function _dns_server_parser_addr_from_apra (line 141) | static int _dns_server_parser_addr_from_apra(const char *arpa, unsigned ...
  function _dns_server_process_ptr_query (line 185) | int _dns_server_process_ptr_query(struct dns_request *request)
  function _dns_server_process_ptrs (line 199) | int _dns_server_process_ptrs(struct dns_request *request)
  function _dns_server_process_ptr (line 226) | int _dns_server_process_ptr(struct dns_request *request)
  function _dns_server_process_local_ptr (line 250) | int _dns_server_process_local_ptr(struct dns_request *request)
  function _dns_server_get_local_ttl (line 326) | int _dns_server_get_local_ttl(struct dns_request *request)

FILE: src/dns_server/ptr.h
  type dns_request (line 28) | struct dns_request
  type dns_request (line 30) | struct dns_request
  type dns_request (line 32) | struct dns_request
  type dns_request (line 34) | struct dns_request
  type sockaddr_storage (line 36) | struct sockaddr_storage
  type sockaddr_storage (line 36) | struct sockaddr_storage
  type dns_request (line 38) | struct dns_request

FILE: src/dns_server/request.c
  function _dns_server_has_bind_flag (line 37) | int _dns_server_has_bind_flag(struct dns_request *request, uint32_t flag)
  function _dns_server_request_complete_with_all_IPs (line 46) | static int _dns_server_request_complete_with_all_IPs(struct dns_request ...
  function _dns_server_request_complete (line 119) | int _dns_server_request_complete(struct dns_request *request)
  function _dns_server_request_remove_all (line 124) | void _dns_server_request_remove_all(void)
  function _dns_server_delete_request (line 145) | static void _dns_server_delete_request(struct dns_request *request)
  function _dns_server_complete_with_multi_ipaddress (line 180) | static void _dns_server_complete_with_multi_ipaddress(struct dns_request...
  function _dns_server_request_release_complete (line 212) | void _dns_server_request_release_complete(struct dns_request *request, i...
  function _dns_server_request_release (line 275) | void _dns_server_request_release(struct dns_request *request)
  function _dns_server_request_get (line 280) | void _dns_server_request_get(struct dns_request *request)
  type sockaddr (line 287) | struct sockaddr
  type dns_request (line 287) | struct dns_request
  type sockaddr (line 296) | struct sockaddr
  type dns_request (line 296) | struct dns_request
  type sockaddr (line 302) | struct sockaddr
  type dns_request (line 305) | struct dns_request
  type dns_request (line 314) | struct dns_request
  type dns_request (line 323) | struct dns_request
  function dns_server_request_get_qtype (line 332) | int dns_server_request_get_qtype(struct dns_request *request)
  function dns_server_request_get_qclass (line 341) | int dns_server_request_get_qclass(struct dns_request *request)
  function dns_server_request_get_query_time (line 350) | int dns_server_request_get_query_time(struct dns_request *request)
  function dns_server_request_get_query_timestamp (line 359) | uint64_t dns_server_request_get_query_timestamp(struct dns_request *requ...
  function dns_server_request_get_ping_time (line 368) | float dns_server_request_get_ping_time(struct dns_request *request)
  function dns_server_request_is_prefetch (line 377) | int dns_server_request_is_prefetch(struct dns_request *request)
  function dns_server_request_is_dualstack (line 386) | int dns_server_request_is_dualstack(struct dns_request *request)
  function dns_server_request_is_blocked (line 395) | int dns_server_request_is_blocked(struct dns_request *request)
  function dns_server_request_is_cached (line 412) | int dns_server_request_is_cached(struct dns_request *request)
  function dns_server_request_get_id (line 421) | int dns_server_request_get_id(struct dns_request *request)
  function dns_server_request_get_rcode (line 430) | int dns_server_request_get_rcode(struct dns_request *request)
  function dns_server_request_get (line 439) | void dns_server_request_get(struct dns_request *request)
  function dns_server_request_put (line 444) | void dns_server_request_put(struct dns_request *request)
  function dns_server_request_set_private (line 449) | void dns_server_request_set_private(struct dns_request *request, void *p...
  type dns_request (line 458) | struct dns_request
  type dns_request (line 467) | struct dns_request
  type dns_request (line 469) | struct dns_request
  function _dns_server_query_end (line 511) | void _dns_server_query_end(struct dns_request *request)
  function _dns_server_passthrough_may_complete (line 554) | void _dns_server_passthrough_may_complete(struct dns_request *request)
  function _dns_server_reply_request_eth_ip (line 589) | static int _dns_server_reply_request_eth_ip(struct dns_request *request)
  function _dns_server_set_request_mdns (line 643) | void _dns_server_set_request_mdns(struct dns_request *request)
  function _dns_server_process_local_SOA (line 652) | static int _dns_server_process_local_SOA(struct dns_request *request)
  function _dns_server_process_srv (line 679) | int _dns_server_process_srv(struct dns_request *request)
  function _dns_server_process_svcb (line 716) | int _dns_server_process_svcb(struct dns_request *request)
  function _dns_server_pre_process_server_flags (line 725) | int _dns_server_pre_process_server_flags(struct dns_request *request)
  type dns_request (line 751) | struct dns_request
  type dns_request (line 751) | struct dns_request
  type dns_request (line 754) | struct dns_request
  function _dns_server_request_copy (line 790) | int _dns_server_request_copy(struct dns_request *request, struct dns_req...
  type dns_request (line 859) | struct dns_request
  type dns_nameserver_rule (line 867) | struct dns_nameserver_rule
  function _dns_server_get_expired_ttl_reply (line 874) | int _dns_server_get_expired_ttl_reply(struct dns_request *request, struc...
  function _dns_server_process_https_svcb (line 884) | int _dns_server_process_https_svcb(struct dns_request *request)
  function _dns_server_request_set_client (line 945) | void _dns_server_request_set_client(struct dns_request *request, struct ...
  function _dns_server_request_set_id (line 952) | void _dns_server_request_set_id(struct dns_request *request, unsigned sh...
  function _dns_server_request_set_mac (line 957) | void _dns_server_request_set_mac(struct dns_request *request, struct soc...
  function _dns_server_request_set_client_addr (line 974) | int _dns_server_request_set_client_addr(struct dns_request *request, str...
  function _dns_server_request_set_callback (line 993) | void _dns_server_request_set_callback(struct dns_request *request, dns_r...
  function _dns_server_process_smartdns_domain (line 999) | int _dns_server_process_smartdns_domain(struct dns_request *request)
  function _dns_server_process_special_query (line 1014) | int _dns_server_process_special_query(struct dns_request *request)
  function _dns_server_check_set_passthrough (line 1065) | void _dns_server_check_set_passthrough(struct dns_request *request)
  function _dns_server_process_host (line 1090) | int _dns_server_process_host(struct dns_request *request)
  function _dns_server_setup_query_option (line 1153) | int _dns_server_setup_query_option(struct dns_request *request, struct d...
  function _dns_server_setup_request_conf_pre (line 1169) | int _dns_server_setup_request_conf_pre(struct dns_request *request)
  function _dns_server_setup_request_conf (line 1211) | int _dns_server_setup_request_conf(struct dns_request *request)
  function _dns_server_setup_dns_group_name (line 1226) | void _dns_server_setup_dns_group_name(struct dns_request *request, const...
  function _dns_server_check_request_supported (line 1245) | int _dns_server_check_request_supported(struct dns_request *request, str...
  function _dns_server_parser_request (line 1258) | int _dns_server_parser_request(struct dns_request *request, struct dns_p...
  function _dns_server_setup_server_query_options (line 1348) | int _dns_server_setup_server_query_options(struct dns_request *request,

FILE: src/dns_server/request.h
  type dns_request (line 30) | struct dns_request
  type dns_request (line 32) | struct dns_request
  type dns_request (line 34) | struct dns_request
  type dns_request (line 36) | struct dns_request
  type dns_request (line 38) | struct dns_request
  type dns_request (line 38) | struct dns_request
  type dns_request (line 41) | struct dns_request
  type dns_request (line 43) | struct dns_request
  type dns_request (line 45) | struct dns_request
  type dns_request (line 45) | struct dns_request
  type dns_request (line 47) | struct dns_request
  type dns_request (line 49) | struct dns_request
  type dns_request (line 51) | struct dns_request
  type dns_request (line 53) | struct dns_request
  type dns_server_query_option (line 54) | struct dns_server_query_option
  type dns_request (line 56) | struct dns_request
  type sockaddr_storage (line 56) | struct sockaddr_storage
  type dns_request (line 58) | struct dns_request
  type dns_packet (line 58) | struct dns_packet
  type dns_request (line 60) | struct dns_request
  type dns_packet (line 60) | struct dns_packet
  type dns_request (line 62) | struct dns_request
  type dns_request (line 64) | struct dns_request
  type dns_request (line 66) | struct dns_request
  type dns_request (line 68) | struct dns_request
  type dns_request (line 70) | struct dns_request
  type dns_request (line 72) | struct dns_request
  type dns_request (line 74) | struct dns_request
  type dns_request (line 76) | struct dns_request
  type dns_request (line 78) | struct dns_request
  type dns_query_options (line 78) | struct dns_query_options
  type dns_request (line 80) | struct dns_request
  type dns_request (line 82) | struct dns_request
  type dns_request (line 84) | struct dns_request
  type dns_request (line 86) | struct dns_request
  type dns_cache (line 86) | struct dns_cache
  type dns_request (line 88) | struct dns_request
  type dns_request (line 90) | struct dns_request
  type dns_server_conn_head (line 90) | struct dns_server_conn_head
  type dns_request (line 92) | struct dns_request
  type dns_request (line 94) | struct dns_request
  type sockaddr_storage (line 94) | struct sockaddr_storage
  type dns_request (line 96) | struct dns_request
  type dns_request (line 98) | struct dns_request
  type dns_request (line 100) | struct dns_request
  type dns_request (line 102) | struct dns_request

FILE: src/dns_server/request_pending.c
  function _dns_server_set_to_pending_list (line 25) | int _dns_server_set_to_pending_list(struct dns_request *request)
  function _dns_server_reply_all_pending_list (line 90) | int _dns_server_reply_all_pending_list(struct dns_request *request, stru...

FILE: src/dns_server/request_pending.h
  type dns_request (line 28) | struct dns_request
  type dns_server_post_context (line 28) | struct dns_server_post_context
  type dns_request (line 30) | struct dns_request

FILE: src/dns_server/rules.c
  type dns_request_domain_rule (line 27) | struct dns_request_domain_rule
  type domain_rule (line 27) | enum domain_rule
  function _dns_server_is_dns_rule_extract_match_ext (line 36) | static int _dns_server_is_dns_rule_extract_match_ext(struct dns_request_...
  function _dns_server_log_rule (line 45) | static void _dns_server_log_rule(const char *domain, enum domain_rule ru...
  function _dns_server_update_rule_by_flags (line 58) | static void _dns_server_update_rule_by_flags(struct dns_request_domain_r...
  function _dns_server_get_rules (line 105) | static int _dns_server_get_rules(unsigned char *key, uint32_t key_len, i...
  function _dns_server_get_domain_rule_by_domain_ext (line 173) | void _dns_server_get_domain_rule_by_domain_ext(struct dns_conf_group *conf,
  function _dns_server_get_domain_rule (line 240) | void _dns_server_get_domain_rule(struct dns_request *request)
  function _dns_server_passthrough_rule_check (line 249) | int _dns_server_passthrough_rule_check(struct dns_request *request, cons...
  function _dns_server_get_conf_ttl (line 397) | int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
  function _dns_server_get_reply_ttl (line 448) | int _dns_server_get_reply_ttl(struct dns_request *request, int ttl)
  type dns_request (line 469) | struct dns_request
  type domain_rule (line 469) | enum domain_rule
  function _dns_server_get_rule_flags (line 478) | uint32_t _dns_server_get_rule_flags(struct dns_request *request)
  function _dns_server_is_dns_rule_extract_match (line 498) | int _dns_server_is_dns_rule_extract_match(struct dns_request *request, e...
  function _dns_server_pre_process_rule_flags (line 507) | int _dns_server_pre_process_rule_flags(struct dns_request *request)
  function _dns_server_process_speed_rule (line 633) | void _dns_server_process_speed_rule(struct dns_request *request)
  function _dns_server_get_domain_rule_by_domain (line 653) | void _dns_server_get_domain_rule_by_domain(struct dns_request *request, ...

FILE: src/dns_server/rules.h
  type dns_request (line 28) | struct dns_request
  type domain_rule (line 28) | enum domain_rule
  type dns_request (line 30) | struct dns_request
  type dns_request (line 32) | struct dns_request
  type dns_request_domain_rule (line 34) | struct dns_request_domain_rule
  type domain_rule (line 34) | enum domain_rule
  type dns_request (line 36) | struct dns_request
  type dns_request (line 38) | struct dns_request
  type dns_request (line 40) | struct dns_request
  type dns_request (line 42) | struct dns_request
  type domain_rule (line 42) | enum domain_rule
  type dns_conf_group (line 44) | struct dns_conf_group
  type dns_request_domain_rule (line 45) | struct dns_request_domain_rule
  type dns_request (line 48) | struct dns_request
  type dns_packet (line 48) | struct dns_packet
  type dns_request (line 51) | struct dns_request
  type dns_request (line 53) | struct dns_request

FILE: src/dns_server/server_http2.c
  function _http2_server_bio_read (line 36) | static int _http2_server_bio_read(void *private_data, uint8_t *buf, int ...
  function _http2_server_bio_write (line 42) | static int _http2_server_bio_write(void *private_data, const uint8_t *bu...
  function _dns_server_http2_send_response (line 48) | static int _dns_server_http2_send_response(struct http2_stream *stream, ...
  function _dns_server_reply_http2 (line 68) | int _dns_server_reply_http2(struct dns_request *request, struct dns_serv...
  function _dns_server_http2_process_stream (line 82) | static void _dns_server_http2_process_stream(struct dns_server_conn_tls_...
  function _dns_server_process_http2 (line 204) | int _dns_server_process_http2(struct dns_server_conn_tls_client *tls_cli...

FILE: src/dns_server/server_http2.h
  type dns_server_conn_http2_stream (line 31) | struct dns_server_conn_http2_stream {
  type dns_server_conn_tls_client (line 37) | struct dns_server_conn_tls_client
  type epoll_event (line 37) | struct epoll_event
  type dns_request (line 40) | struct dns_request
  type dns_server_conn_http2_stream (line 40) | struct dns_server_conn_http2_stream

FILE: src/dns_server/server_https.c
  function _dns_server_reply_http_error (line 31) | int _dns_server_reply_http_error(struct dns_server_conn_tcp_client *tcpc...
  function _dns_server_reply_https (line 61) | int _dns_server_reply_https(struct dns_request *request, struct dns_serv...

FILE: src/dns_server/server_https.h
  type dns_server_conn_tcp_client (line 29) | struct dns_server_conn_tcp_client
  type dns_request (line 32) | struct dns_request
  type dns_server_conn_tcp_client (line 32) | struct dns_server_conn_tcp_client

FILE: src/dns_server/server_socket.c
  type addrinfo (line 37) | struct addrinfo
  type addrinfo (line 39) | struct addrinfo
  type addrinfo (line 40) | struct addrinfo
  function _dns_create_socket (line 67) | int _dns_create_socket(const char *host_ip, int type)

FILE: src/dns_server/server_tcp.c
  function _dns_server_reply_tcp_to_buffer (line 35) | int _dns_server_reply_tcp_to_buffer(struct dns_server_conn_tcp_client *t...
  function _dns_server_reply_tcp (line 56) | int _dns_server_reply_tcp(struct dns_request *request, struct dns_server...
  function _dns_server_tcp_accept (line 90) | int _dns_server_tcp_accept(struct dns_server_conn_tcp_server *tcpserver,...
  function _dns_server_tcp_socket_send (line 147) | int _dns_server_tcp_socket_send(struct dns_server_conn_tcp_client *tcp_c...
  function _dns_server_tcp_socket_recv (line 167) | int _dns_server_tcp_socket_recv(struct dns_server_conn_tcp_client *tcp_c...
  function _dns_server_tcp_recv (line 188) | static int _dns_server_tcp_recv(struct dns_server_conn_tcp_client *tcpcl...
  function _dns_server_tcp_process_one_request (line 229) | static int _dns_server_tcp_process_one_request(struct dns_server_conn_tc...
  function _dns_server_tcp_process_requests (line 410) | int _dns_server_tcp_process_requests(struct dns_server_conn_tcp_client *...
  function _dns_server_tls_want_write (line 452) | static int _dns_server_tls_want_write(struct dns_server_conn_tcp_client ...
  function _dns_server_tcp_send (line 464) | static int _dns_server_tcp_send(struct dns_server_conn_tcp_client *tcpcl...
  function _dns_server_process_tcp (line 489) | int _dns_server_process_tcp(struct dns_server_conn_tcp_client *dnsserver...
  function _dns_server_tcp_idle_check (line 516) | void _dns_server_tcp_idle_check(void)
  function _dns_server_socket_tcp (line 546) | int _dns_server_socket_tcp(struct dns_bind_ip *bind_ip)

FILE: src/dns_server/server_tcp.h
  type dns_server_conn_tcp_client (line 30) | struct dns_server_conn_tcp_client
  type dns_server_conn_tcp_client (line 32) | struct dns_server_conn_tcp_client
  type dns_server_conn_tcp_server (line 34) | struct dns_server_conn_tcp_server
  type epoll_event (line 34) | struct epoll_event
  type dns_server_conn_tcp_client (line 36) | struct dns_server_conn_tcp_client
  type dns_server_conn_tcp_client (line 38) | struct dns_server_conn_tcp_client
  type dns_server_conn_tcp_client (line 40) | struct dns_server_conn_tcp_client
  type epoll_event (line 40) | struct epoll_event
  type dns_request (line 42) | struct dns_request
  type dns_server_conn_tcp_client (line 42) | struct dns_server_conn_tcp_client
  type dns_bind_ip (line 47) | struct dns_bind_ip

FILE: src/dns_server/server_tls.c
  function alpn_select_cb (line 38) | static int alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned ...
  function _ssl_read (line 76) | static ssize_t _ssl_read(struct dns_server_conn_tls_client *conn, void *...
  function _ssl_write (line 90) | static ssize_t _ssl_write(struct dns_server_conn_tls_client *conn, const...
  function _ssl_get_error (line 104) | static int _ssl_get_error(struct dns_server_conn_tls_client *conn, int ret)
  function _ssl_do_accept (line 118) | static int _ssl_do_accept(struct dns_server_conn_tls_client *conn)
  function _dns_server_socket_ssl_send (line 132) | int _dns_server_socket_ssl_send(struct dns_server_conn_tls_client *tls_c...
  function _dns_server_socket_ssl_recv (line 197) | int _dns_server_socket_ssl_recv(struct dns_server_conn_tls_client *tls_c...
  function _dns_server_ssl_poll_event (line 266) | int _dns_server_ssl_poll_event(struct dns_server_conn_tls_client *tls_cl...
  function _dns_server_tls_accept (line 296) | int _dns_server_tls_accept(struct dns_server_conn_tls_server *tls_server...
  function _dns_server_process_tls (line 386) | int _dns_server_process_tls(struct dns_server_conn_tls_client *tls_clien...
  function _dns_server_socket_tls_ssl_pass_callback (line 452) | static int _dns_server_socket_tls_ssl_pass_callback(char *buf, int size,...
  function _dns_server_socket_tls (line 462) | int _dns_server_socket_tls(struct dns_bind_ip *bind_ip, DNS_CONN_TYPE co...

FILE: src/dns_server/server_tls.h
  type dns_server_conn_tls_client (line 30) | struct dns_server_conn_tls_client
  type dns_server_conn_tls_server (line 32) | struct dns_server_conn_tls_server
  type epoll_event (line 32) | struct epoll_event
  type dns_server_conn_tls_client (line 34) | struct dns_server_conn_tls_client
  type dns_server_conn_tls_client (line 36) | struct dns_server_conn_tls_client
  type dns_server_conn_tls_client (line 38) | struct dns_server_conn_tls_client
  type epoll_event (line 38) | struct epoll_event
  type dns_bind_ip (line 41) | struct dns_bind_ip

FILE: src/dns_server/server_udp.c
  function _dns_server_reply_udp (line 32) | int _dns_server_reply_udp(struct dns_request *request, struct dns_server...
  function _dns_server_process_udp_one (line 96) | static int _dns_server_process_udp_one(struct dns_server_conn_udp *udpco...
  function _dns_server_process_udp (line 145) | int _dns_server_process_udp(struct dns_server_conn_udp *udpconn, struct ...
  function _dns_server_socket_udp (line 164) | int _dns_server_socket_udp(struct dns_bind_ip *bind_ip)

FILE: src/dns_server/server_udp.h
  type dns_server_conn_udp (line 30) | struct dns_server_conn_udp
  type epoll_event (line 30) | struct epoll_event
  type dns_bind_ip (line 32) | struct dns_bind_ip
  type dns_request (line 34) | struct dns_request
  type dns_server_conn_udp (line 34) | struct dns_server_conn_udp

FILE: src/dns_server/soa.c
  function _dns_server_is_return_soa_qtype (line 27) | int _dns_server_is_return_soa_qtype(struct dns_request *request, dns_typ...
  function _dns_server_reply_SOA_ext (line 107) | int _dns_server_reply_SOA_ext(int rcode, struct dns_request *request)
  function _dns_server_reply_SOA (line 126) | int _dns_server_reply_SOA(int rcode, struct dns_request *request)
  function _dns_server_qtype_soa (line 132) | int _dns_server_qtype_soa(struct dns_request *request)
  function _dns_server_is_return_soa (line 151) | int _dns_server_is_return_soa(struct dns_request *request)
  function _dns_server_setup_soa (line 156) | void _dns_server_setup_soa(struct dns_request *request)

FILE: src/dns_server/soa.h
  type dns_request (line 28) | struct dns_request
  type dns_request (line 30) | struct dns_request
  type dns_request (line 32) | struct dns_request
  type dns_request (line 34) | struct dns_request
  type dns_request (line 36) | struct dns_request
  type dns_request (line 38) | struct dns_request

FILE: src/dns_server/speed_check.c
  function _dns_server_ping_result (line 29) | static void _dns_server_ping_result(struct ping_host_struct *ping_host, ...
  function _dns_server_ping (line 186) | static int _dns_server_ping(struct dns_request *request, PING_TYPE type,...
  function _dns_server_check_speed (line 195) | int _dns_server_check_speed(struct dns_request *request, char *ip)
  function _dns_server_second_ping_check (line 263) | int _dns_server_second_ping_check(struct dns_request *request)

FILE: src/dns_server/speed_check.h
  type dns_request (line 28) | struct dns_request
  type dns_request (line 30) | struct dns_request

FILE: src/dns_stats.c
  type dns_stats (line 23) | struct dns_stats
  function dns_stats_avg_time_update_add (line 25) | void dns_stats_avg_time_update_add(struct dns_stats_avg_time *avg_time, ...
  function dns_stats_avg_time_update (line 35) | void dns_stats_avg_time_update(struct dns_stats_avg_time *avg_time)
  function dns_stats_period_run_second (line 65) | void dns_stats_period_run_second(void)
  function dns_stats_avg_time_get (line 70) | float dns_stats_avg_time_get(void)
  function dns_stats_request_total_get (line 75) | uint64_t dns_stats_request_total_get(void)
  function dns_stats_request_success_get (line 80) | uint64_t dns_stats_request_success_get(void)
  function dns_stats_request_from_client_get (line 85) | uint64_t dns_stats_request_from_client_get(void)
  function dns_stats_request_blocked_get (line 90) | uint64_t dns_stats_request_blocked_get(void)
  function dns_stats_cache_hit_get (line 95) | uint64_t dns_stats_cache_hit_get(void)
  function dns_stats_cache_hit_rate_get (line 100) | float dns_stats_cache_hit_rate_get(void)
  function dns_stats_server_stats_avg_time_add (line 112) | void dns_stats_server_stats_avg_time_add(struct dns_server_stats *server...
  function dns_stats_server_stats_avg_time_update (line 117) | void dns_stats_server_stats_avg_time_update(struct dns_server_stats *ser...
  function dns_stats_server_stats_total_get (line 122) | uint64_t dns_stats_server_stats_total_get(struct dns_server_stats *serve...
  function dns_stats_server_stats_success_get (line 131) | uint64_t dns_stats_server_stats_success_get(struct dns_server_stats *ser...
  function dns_stats_server_stats_recv_get (line 140) | uint64_t dns_stats_server_stats_recv_get(struct dns_server_stats *server...
  function dns_stats_server_stats_avg_time_get (line 149) | float dns_stats_server_stats_avg_time_get(struct dns_server_stats *serve...
  function dns_stats_init (line 158) | int dns_stats_init(void)
  function dns_stats_exit (line 164) | void dns_stats_exit(void)

FILE: src/fast_ping/fast_ping.c
  type fast_ping_struct (line 49) | struct fast_ping_struct
  function _fast_ping_hash_key (line 53) | uint32_t _fast_ping_hash_key(unsigned int sid, struct sockaddr *addr)
  type addrinfo (line 93) | struct addrinfo
  type addrinfo (line 95) | struct addrinfo
  type addrinfo (line 96) | struct addrinfo
  function _fast_ping_getdomain (line 118) | int _fast_ping_getdomain(const char *host)
  function _fast_ping_sendping (line 145) | static int _fast_ping_sendping(struct ping_host_struct *ping_host)
  function _fast_ping_print_result (line 182) | static void _fast_ping_print_result(struct ping_host_struct *ping_host, ...
  function _fast_ping_get_addr_by_type (line 198) | int _fast_ping_get_addr_by_type(PING_TYPE type, const char *ip_str, int ...
  type ping_host_struct (line 221) | struct ping_host_struct
  type ping_host_struct (line 224) | struct ping_host_struct
  type addrinfo (line 225) | struct addrinfo
  type fast_ping_fake_ip (line 231) | struct fast_ping_fake_ip
  type sockaddr_in6 (line 270) | struct sockaddr_in6
  function fast_ping_stop (line 336) | int fast_ping_stop(struct ping_host_struct *ping_host)
  function tv_sub (line 348) | void tv_sub(struct timeval *out, struct timeval *in)
  function _fast_ping_process (line 357) | static int _fast_ping_process(struct ping_host_struct *ping_host, struct...
  function _fast_ping_period_run (line 390) | static void _fast_ping_period_run(void)
  type epoll_event (line 462) | struct epoll_event
  type timeval (line 466) | struct timeval
  type epoll_event (line 517) | struct epoll_event
  type ping_host_struct (line 526) | struct ping_host_struct
  type ping_host_struct (line 526) | struct ping_host_struct
  function fast_ping_init (line 537) | int fast_ping_init(void)
  function _fast_ping_close_fds (line 631) | static void _fast_ping_close_fds(void)
  function fast_ping_exit (line 638) | void fast_ping_exit(void)

FILE: src/fast_ping/fast_ping.h
  type icmp_filter (line 47) | struct icmp_filter {
  type ping_dns_head (line 52) | struct ping_dns_head {
  type FAST_PING_TYPE (line 64) | typedef enum FAST_PING_TYPE {
  type fast_ping_packet_msg (line 74) | struct fast_ping_packet_msg {
  type fast_ping_packet (line 80) | struct fast_ping_packet {
  type fast_ping_fake_ip (line 89) | struct fast_ping_fake_ip {
  type ping_host_struct (line 101) | struct ping_host_struct {
  type fast_ping_notify_event (line 140) | struct fast_ping_notify_event {
  type fast_ping_struct (line 149) | struct fast_ping_struct {
  type fast_ping_struct (line 188) | struct fast_ping_struct
  type sockaddr (line 191) | struct sockaddr
  type addrinfo (line 193) | struct addrinfo
  type addrinfo (line 195) | struct addrinfo
  type timeval (line 198) | struct timeval
  type timeval (line 198) | struct timeval

FILE: src/fast_ping/notify_event.c
  function _fast_ping_release_notify_event (line 30) | static void _fast_ping_release_notify_event(struct fast_ping_notify_even...
  function _fast_ping_send_notify_event (line 43) | int _fast_ping_send_notify_event(struct ping_host_struct *ping_host, FAS...
  function _fast_ping_process_notify_event (line 76) | static void _fast_ping_process_notify_event(struct fast_ping_notify_even...
  type fast_ping_notify_event (line 90) | struct fast_ping_notify_event
  function _fast_ping_remove_all_notify_event (line 115) | void _fast_ping_remove_all_notify_event(void)

FILE: src/fast_ping/notify_event.h
  type ping_host_struct (line 32) | struct ping_host_struct
  type timeval (line 33) | struct timeval

FILE: src/fast_ping/ping_fake.c
  function _fast_ping_fake_put (line 33) | void _fast_ping_fake_put(struct fast_ping_fake_ip *fake)
  function _fast_ping_fake_remove (line 53) | void _fast_ping_fake_remove(struct fast_ping_fake_ip *fake)
  function _fast_ping_fake_get (line 64) | void _fast_ping_fake_get(struct fast_ping_fake_ip *fake)
  type fast_ping_fake_ip (line 69) | struct fast_ping_fake_ip
  type sockaddr (line 69) | struct sockaddr
  type fast_ping_fake_ip (line 71) | struct fast_ping_fake_ip
  type fast_ping_fake_ip (line 72) | struct fast_ping_fake_ip
  function fast_ping_fake_ip_add (line 104) | int fast_ping_fake_ip_add(PING_TYPE type, const char *host, int ttl, flo...
  function fast_ping_fake_ip_remove (line 170) | int fast_ping_fake_ip_remove(PING_TYPE type, const char *host)
  function _fast_ping_send_fake (line 205) | int _fast_ping_send_fake(struct ping_host_struct *ping_host, struct fast...
  function _fast_ping_process_fake (line 237) | int _fast_ping_process_fake(struct ping_host_struct *ping_host, struct t...
  function _fast_ping_remove_all_fake_ip (line 264) | void _fast_ping_remove_all_fake_ip(void)

FILE: src/fast_ping/ping_fake.h
  type fast_ping_fake_ip (line 28) | struct fast_ping_fake_ip
  type fast_ping_fake_ip (line 30) | struct fast_ping_fake_ip
  type fast_ping_fake_ip (line 32) | struct fast_ping_fake_ip
  type fast_ping_fake_ip (line 34) | struct fast_ping_fake_ip
  type sockaddr (line 34) | struct sockaddr
  type ping_host_struct (line 38) | struct ping_host_struct
  type timeval (line 38) | struct timeval
  type ping_host_struct (line 40) | struct ping_host_struct
  type fast_ping_fake_ip (line 40) | struct fast_ping_fake_ip

FILE: src/fast_ping/ping_host.c
  function _fast_ping_host_get (line 30) | void _fast_ping_host_get(struct ping_host_struct *ping_host)
  function _fast_ping_close_host_sock (line 38) | void _fast_ping_close_host_sock(struct ping_host_struct *ping_host)
  function _fast_ping_host_put (line 59) | void _fast_ping_host_put(struct ping_host_struct *ping_host)
  function _fast_ping_host_remove (line 93) | void _fast_ping_host_remove(struct ping_host_struct *ping_host)
  function _fast_ping_remove_all (line 117) | void _fast_ping_remove_all(void)

FILE: src/fast_ping/ping_host.h
  type ping_host_struct (line 28) | struct ping_host_struct
  type ping_host_struct (line 30) | struct ping_host_struct
  type ping_host_struct (line 32) | struct ping_host_struct
  type ping_host_struct (line 34) | struct ping_host_struct

FILE: src/fast_ping/ping_icmp.c
  function _fast_ping_install_filter_v4 (line 33) | static void _fast_ping_install_filter_v4(int sock)
  function _fast_ping_sendping_v4 (line 62) | int _fast_ping_sendping_v4(struct ping_host_struct *ping_host)
  function _fast_ping_create_icmp_sock (line 113) | static int _fast_ping_create_icmp_sock(FAST_PING_TYPE type)
  function _fast_ping_create_icmp (line 207) | static int _fast_ping_create_icmp(FAST_PING_TYPE type)
  function _fast_ping_icmp_create_socket (line 246) | int _fast_ping_icmp_create_socket(struct ping_host_struct *ping_host)
  type fast_ping_packet (line 257) | struct fast_ping_packet
  type ping_host_struct (line 257) | struct ping_host_struct
  type msghdr (line 257) | struct msghdr
  type ip (line 260) | struct ip
  type ip (line 260) | struct ip
  type fast_ping_packet (line 261) | struct fast_ping_packet
  type icmp (line 262) | struct icmp
  type icmp (line 274) | struct icmp
  type fast_ping_packet (line 279) | struct fast_ping_packet
  type fast_ping_packet (line 281) | struct fast_ping_packet
  type fast_ping_packet (line 312) | struct fast_ping_packet
  type ping_host_struct (line 312) | struct ping_host_struct
  type msghdr (line 312) | struct msghdr
  type timeval (line 313) | struct timeval
  type fast_ping_packet (line 315) | struct fast_ping_packet
  function _fast_ping_process_icmp (line 337) | int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct t...
  function _fast_ping_get_addr_by_icmp (line 429) | int _fast_ping_get_addr_by_icmp(const char *ip_str, int port, struct add...
  function _fast_ping_sockaddr_ip_cmp (line 479) | int _fast_ping_sockaddr_ip_cmp(struct sockaddr *first_addr, socklen_t fi...
  function _fast_ping_checksum (line 524) | uint16_t _fast_ping_checksum(uint16_t *header, size_t len)
  function _fast_ping_close_icmp (line 536) | void _fast_ping_close_icmp(void)

FILE: src/fast_ping/ping_icmp.h
  type ping_host_struct (line 28) | struct ping_host_struct
  type fast_ping_packet (line 30) | struct fast_ping_packet
  type ping_host_struct (line 30) | struct ping_host_struct
  type msghdr (line 30) | struct msghdr
  type sockaddr (line 33) | struct sockaddr
  type sockaddr (line 33) | struct sockaddr
  type ping_host_struct (line 38) | struct ping_host_struct
  type ping_host_struct (line 40) | struct ping_host_struct
  type timeval (line 40) | struct timeval
  type addrinfo (line 42) | struct addrinfo

FILE: src/fast_ping/ping_icmp6.c
  function _fast_ping_install_filter_v6 (line 30) | void _fast_ping_install_filter_v6(int sock)
  function _fast_ping_sendping_v6 (line 62) | int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
  type fast_ping_packet (line 130) | struct fast_ping_packet
  type ping_host_struct (line 130) | struct ping_host_struct
  type msghdr (line 130) | struct msghdr
  type fast_ping_packet (line 134) | struct fast_ping_packet
  type fast_ping_packet (line 134) | struct fast_ping_packet
  type icmp6_hdr (line 135) | struct icmp6_hdr
  type cmsghdr (line 136) | struct cmsghdr
  type icmp6_hdr (line 139) | struct icmp6_hdr
  type fast_ping_packet (line 140) | struct fast_ping_packet

FILE: src/fast_ping/ping_icmp6.h
  type fast_ping_packet (line 28) | struct fast_ping_packet
  type ping_host_struct (line 28) | struct ping_host_struct
  type msghdr (line 28) | struct msghdr
  type ping_host_struct (line 33) | struct ping_host_struct

FILE: src/fast_ping/ping_tcp.c
  function _fast_ping_sendping_tcp (line 34) | int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
  function _fast_ping_get_addr_by_tcp (line 103) | int _fast_ping_get_addr_by_tcp(const char *ip_str, int port, struct addr...
  function _fast_ping_process_tcp (line 138) | int _fast_ping_process_tcp(struct ping_host_struct *ping_host, struct ep...

FILE: src/fast_ping/ping_tcp.h
  type ping_host_struct (line 30) | struct ping_host_struct
  type epoll_event (line 30) | struct epoll_event
  type timeval (line 30) | struct timeval
  type addrinfo (line 32) | struct addrinfo
  type ping_host_struct (line 34) | struct ping_host_struct

FILE: src/fast_ping/ping_tcp_syn.c
  type pseudo_header (line 42) | struct pseudo_header {
  type pseudo_header6 (line 50) | struct pseudo_header6 {
  function _tcp_syn_get_local_addr (line 59) | static int _tcp_syn_get_local_addr(int family, struct sockaddr *dest, st...
  function _tcp_syn_reserve_port (line 90) | static int _tcp_syn_reserve_port(int family, int *out_fd, uint16_t *out_...
  function _tcp_syn_install_bpf_ipv4 (line 148) | static int _tcp_syn_install_bpf_ipv4(int fd, uint16_t port)
  function _tcp_syn_install_bpf_ipv6 (line 173) | static int _tcp_syn_install_bpf_ipv6(int fd, uint16_t port)
  function _tcp_syn_send_rst_ipv4 (line 197) | static int _tcp_syn_send_rst_ipv4(struct ping_host_struct *ping_host, st...
  function _tcp_syn_send_rst_ipv6 (line 278) | static int _tcp_syn_send_rst_ipv6(struct ping_host_struct *ping_host, st...
  function _tcp_syn_send_rst (line 349) | __attribute__((unused)) static int _tcp_syn_send_rst(struct ping_host_st...
  function _tcp_syn_build_packet_ipv4 (line 368) | static int _tcp_syn_build_packet_ipv4(char *packet, struct ping_host_str...
  function _tcp_syn_build_packet_ipv6 (line 441) | static int _tcp_syn_build_packet_ipv6(char *packet, struct ping_host_str...
  function _fast_ping_sendping_tcp_syn (line 491) | int _fast_ping_sendping_tcp_syn(struct ping_host_struct *ping_host)
  function _fast_ping_get_addr_by_tcp_syn (line 569) | int _fast_ping_get_addr_by_tcp_syn(const char *ip_str, int port, struct ...
  function _fast_ping_process_tcp_syn (line 592) | int _fast_ping_process_tcp_syn(struct ping_host_struct *ping_host, struc...
  function _fast_ping_create_tcp_syn_sock_ipv4 (line 757) | static int _fast_ping_create_tcp_syn_sock_ipv4(void)
  function _fast_ping_create_tcp_syn_sock_ipv6 (line 810) | static int _fast_ping_create_tcp_syn_sock_ipv6(void)
  function _fast_ping_create_tcp_syn_sock (line 852) | static int _fast_ping_create_tcp_syn_sock(int is_ipv6)
  function _fast_ping_create_tcp_syn (line 897) | static int _fast_ping_create_tcp_syn(int is_ipv6)
  function _fast_ping_tcp_syn_create_socket (line 931) | int _fast_ping_tcp_syn_create_socket(struct ping_host_struct *ping_host)
  function _fast_ping_close_tcp_syn (line 973) | void _fast_ping_close_tcp_syn(void)

FILE: src/fast_ping/ping_tcp_syn.h
  type ping_host_struct (line 30) | struct ping_host_struct
  type timeval (line 30) | struct timeval
  type addrinfo (line 32) | struct addrinfo
  type ping_host_struct (line 35) | struct ping_host_struct
  type ping_host_struct (line 37) | struct ping_host_struct

FILE: src/fast_ping/ping_udp.c
  function _fast_ping_sendping_udp (line 33) | int _fast_ping_sendping_udp(struct ping_host_struct *ping_host)
  function _fast_ping_create_udp_sock (line 85) | static int _fast_ping_create_udp_sock(FAST_PING_TYPE type)
  function _fast_ping_create_udp (line 141) | static int _fast_ping_create_udp(FAST_PING_TYPE type)
  function _fast_ping_get_addr_by_dns (line 180) | int _fast_ping_get_addr_by_dns(const char *ip_str, int port, struct addr...
  function _fast_ping_process_udp (line 236) | int _fast_ping_process_udp(struct ping_host_struct *ping_host, struct ti...
  function _fast_ping_close_udp (line 330) | void _fast_ping_close_udp(void)

FILE: src/fast_ping/ping_udp.h
  type addrinfo (line 28) | struct addrinfo
  type ping_host_struct (line 30) | struct ping_host_struct
  type ping_host_struct (line 32) | struct ping_host_struct
  type timeval (line 32) | struct timeval

FILE: src/fast_ping/wakeup_event.c
  function _fast_ping_wakeup_thread
Condensed preview — 405 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,903K chars).
[
  {
    "path": ".clang-format",
    "chars": 247,
    "preview": "#http://clang.llvm.org/docs/ClangFormatStyleOptions.html\n\nBasedOnStyle: LLVM\nIndentWidth: 4\nTabWidth: 4\nUseTab: ForConti"
  },
  {
    "path": ".clang-tidy",
    "chars": 1367,
    "preview": "Checks: >\n  -*,\n  modernize-*,\n  bugprone-*,\n  concurrency-*,\n  misc-*,\n  readability-*,\n  performance-*,\n  portability-"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature.md",
    "chars": 178,
    "preview": "---\r\nname: 需求建议\r\nabout: 需求建议描述\r\ntitle: ''\r\nlabels: ''\r\nassignees: ''\r\n\r\n---\r\n\r\n**需求应用场景**\r\n请描述需求应用的场景和方式。\r\n\r\n**建议的方案**\r\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/issue.md",
    "chars": 430,
    "preview": "---\r\nname: 问题报告\r\nabout: 问题现象描述\r\ntitle: ''\r\nlabels: ''\r\nassignees: ''\r\n\r\n---\r\n\r\n**问题现象**  \r\n简要描述问题出现的现象\r\n\r\n**运行环境**\r\n1. 固"
  },
  {
    "path": ".github/workflows/c-cpp.yml",
    "chars": 415,
    "preview": "name: C/C++ CI\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n\n    runs-"
  },
  {
    "path": ".github/workflows/docker.yml",
    "chars": 977,
    "preview": "name: Publish Docker Image\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: 'new image tag(e.g."
  },
  {
    "path": ".github/workflows/webui.yml",
    "chars": 392,
    "preview": "name: WebUI CI\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n\n    runs-"
  },
  {
    "path": ".gitignore",
    "chars": 126,
    "preview": ".vscode\n*.o\n*.a\n*.pem\n.DS_Store\n*.swp.\n*.a\nsystemd/smartdns.service\ntest.bin\npackage/target\npackage/*.gz\npackage/*.ipk\nt"
  },
  {
    "path": "Dockerfile",
    "chars": 2966,
    "preview": "FROM ubuntu:latest AS smartdns-builder\nLABEL previous-stage=smartdns-builder\n\n# prepare builder\nARG OPENSSL_VER=3.5.4\nAR"
  },
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "Makefile",
    "chars": 2408,
    "preview": "# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redistribute it "
  },
  {
    "path": "ReadMe.md",
    "chars": 4027,
    "preview": "# SmartDNS\n\n**[English](ReadMe_en.md)**\n\n![SmartDNS](doc/smartdns-banner.png)\nSmartDNS 是一个运行在本地的 DNS 服务器,它接受来自本地客户端的 DNS"
  },
  {
    "path": "ReadMe_en.md",
    "chars": 6113,
    "preview": "# SmartDNS\n\n![SmartDNS](doc/smartdns-banner.png)  \nSmartDNS is a local DNS server. SmartDNS accepts DNS query requests f"
  },
  {
    "path": "etc/default/smartdns",
    "chars": 148,
    "preview": "# Default settings for smartdns server. This file is sourced by /bin/sh from\n# /etc/init.d/smartdns.\n\n# Options to pass "
  },
  {
    "path": "etc/init.d/smartdns",
    "chars": 2392,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "etc/smartdns/smartdns.conf",
    "chars": 16572,
    "preview": "# dns server name, default is host name\n# server-name, \n# example:\n#   server-name smartdns\n#\n\n# whether resolv local ho"
  },
  {
    "path": "package/build-pkg.sh",
    "chars": 10094,
    "preview": "#!/bin/sh\n# Copyright (C) 2018-2025 Nick Peng (pymumu@gmail.com)\n\nCURR_DIR=$(cd $(dirname $0);pwd)\nWORKDIR=$CURR_DIR/tar"
  },
  {
    "path": "package/copy-smartdns.sh",
    "chars": 1552,
    "preview": "#!/bin/sh\n\nCURR_DIR=$(cd $(dirname $0);pwd)\nWORKDIR=$CURR_DIR/target\nCODE_DIR=\"$CURR_DIR/..\"\nSMARTDNS_STATIC_DIR=\"$WORKD"
  },
  {
    "path": "package/debian/DEBIAN/changelog",
    "chars": 138,
    "preview": "smartdns (1:1.2022.04.05) stable; urgency=low\n\n  * Initial build\n\n -- initial release. <pymumu@gmail.com>  Mon, 9 jul 20"
  },
  {
    "path": "package/debian/DEBIAN/compat",
    "chars": 2,
    "preview": "9\n"
  },
  {
    "path": "package/debian/DEBIAN/conffiles",
    "chars": 28,
    "preview": "/etc/smartdns/smartdns.conf\n"
  },
  {
    "path": "package/debian/DEBIAN/control",
    "chars": 208,
    "preview": "Source: smartdns  \nMaintainer: Nick Peng <pymumu@gmail.com>\nBuild-Depends: debhelper (>= 8.0.0)\nVersion: \nSection: net\nP"
  },
  {
    "path": "package/debian/DEBIAN/copyright",
    "chars": 202,
    "preview": "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: smartdns\nSource: http://github."
  },
  {
    "path": "package/debian/DEBIAN/prerm",
    "chars": 62,
    "preview": "#!/bin/sh\n\nsystemctl stop smartdns\nsystemctl disable smartdns\n"
  },
  {
    "path": "package/debian/DEBIAN/rules",
    "chars": 345,
    "preview": "#!/usr/bin/make -f  \n%:  \n\tdh $@ --with systemd --builddirectory=./target/\n\nclean:\n\tmake -C ../src clean\n\nbuild:\n\tmake -"
  },
  {
    "path": "package/debian/make.sh",
    "chars": 3390,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/linux/install",
    "chars": 6682,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/linux/make.sh",
    "chars": 2648,
    "preview": "#!/bin/sh\n\nCURR_DIR=$(cd $(dirname $0);pwd)\nVER=\"`date +\"1.%Y.%m.%d-%H%M\"`\"\nSMARTDNS_DIR=$CURR_DIR/../../\nSMARTDNS_CP=$S"
  },
  {
    "path": "package/luci/control/control",
    "chars": 201,
    "preview": "Package: luci-app-smartdns\nVersion: git-18.201.27126-7bf0367-1\nDepends: libc, smartdns\nSource: feeds/luci/applications/l"
  },
  {
    "path": "package/luci/control/postinst",
    "chars": 856,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci/control/prerm",
    "chars": 813,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci/debian-binary",
    "chars": 4,
    "preview": "2.0\n"
  },
  {
    "path": "package/luci/files/luci/i18n/smartdns.zh-cn.po",
    "chars": 16441,
    "preview": "\nmsgid \"Additional Args for upstream dns servers\"\nmsgstr \"额外的上游 DNS 服务器参数\"\n\nmsgid \"\"\n\"Additional Flags for rules, read h"
  },
  {
    "path": "package/luci/files/root/usr/share/luci/menu.d/luci-app-smartdns.json",
    "chars": 214,
    "preview": "{\n\t\"admin/services/smartdns\": {\n\t\t\"title\": \"SmartDNS\",\n\t\t\"action\": {\n\t\t\t\"type\": \"view\",\n\t\t\t\"path\": \"smartdns/smartdns\"\n\t"
  },
  {
    "path": "package/luci/files/root/usr/share/rpcd/acl.d/luci-app-smartdns.json",
    "chars": 421,
    "preview": "{\n\t\"luci-app-smartdns\": {\n\t\t\"description\": \"Grant access to LuCI app smartdns\",\n\t\t\"read\": {\n\t\t\t\"file\": {\n\t\t\t\t\"/etc/smart"
  },
  {
    "path": "package/luci/files/root/www/luci-static/resources/view/smartdns/smartdns.js",
    "chars": 52364,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "package/luci/make.sh",
    "chars": 3690,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci-compat/control/control",
    "chars": 201,
    "preview": "Package: luci-app-smartdns\nVersion: git-18.201.27126-7bf0367-1\nDepends: libc, smartdns\nSource: feeds/luci/applications/l"
  },
  {
    "path": "package/luci-compat/control/postinst",
    "chars": 856,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci-compat/control/prerm",
    "chars": 813,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci-compat/debian-binary",
    "chars": 4,
    "preview": "2.0\n"
  },
  {
    "path": "package/luci-compat/files/etc/uci-defaults/50_luci-smartdns",
    "chars": 889,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci-compat/files/luci/controller/smartdns.lua",
    "chars": 2069,
    "preview": "--\n-- Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n--\n-- smartdns is free software: you can redistribu"
  },
  {
    "path": "package/luci-compat/files/luci/i18n/smartdns.zh-cn.po",
    "chars": 16301,
    "preview": "\nmsgid \"Additional Args for upstream dns servers\"\nmsgstr \"额外的上游 DNS 服务器参数\"\n\nmsgid \"\"\n\"Additional Flags for rules, read h"
  },
  {
    "path": "package/luci-compat/files/luci/model/cbi/smartdns/smartdns.lua",
    "chars": 40198,
    "preview": "--\n-- Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n--\n-- smartdns is free software: you can redistribu"
  },
  {
    "path": "package/luci-compat/files/luci/model/cbi/smartdns/upstream.lua",
    "chars": 5369,
    "preview": "--\n-- Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n--\n-- smartdns is free software: you can redistribu"
  },
  {
    "path": "package/luci-compat/files/luci/model/smartdns.lua",
    "chars": 1032,
    "preview": "--\n-- Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n--\n-- smartdns is free software: you can redistribu"
  },
  {
    "path": "package/luci-compat/files/luci/view/smartdns/smartdns_status.htm",
    "chars": 818,
    "preview": "<script type=\"text/javascript\">//<![CDATA[\nXHR.poll(3, '<%=luci.dispatcher.build_url(\"admin\", \"services\", \"smartdns\", \"s"
  },
  {
    "path": "package/luci-compat/files/usr/share/rpcd/acl.d/luci-app-smartdns.json",
    "chars": 421,
    "preview": "{\n\t\"luci-app-smartdns\": {\n\t\t\"description\": \"Grant access to LuCI app smartdns\",\n\t\t\"read\": {\n\t\t\t\"file\": {\n\t\t\t\t\"/etc/smart"
  },
  {
    "path": "package/luci-compat/make.sh",
    "chars": 2892,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci-lite/control/conffiles",
    "chars": 26,
    "preview": "/etc/config/smartdns-lite\n"
  },
  {
    "path": "package/luci-lite/control/control",
    "chars": 221,
    "preview": "Package: luci-app-smartdns-lite\nVersion: git-18.201.27126-7bf0367-1\nDepends: libc, smartdns\nSource: feeds/luci/applicati"
  },
  {
    "path": "package/luci-lite/control/postinst",
    "chars": 940,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci-lite/control/prerm",
    "chars": 925,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/luci-lite/debian-binary",
    "chars": 4,
    "preview": "2.0\n"
  },
  {
    "path": "package/luci-lite/files/luci/i18n/smartdns-lite.zh-cn.po",
    "chars": 5167,
    "preview": "msgid \"\"\nmsgstr \"Content-Type: text/plain; charset=UTF-8\"\n\nmsgid \"A local SmartDNS server for lite users.\"\nmsgstr \"为入门用户"
  },
  {
    "path": "package/luci-lite/files/root/etc/config/smartdns-lite",
    "chars": 46,
    "preview": "config 'smartdns-lite'\n\toption 'enabled' '0'\n\t"
  },
  {
    "path": "package/luci-lite/files/root/etc/init.d/smartdns-lite",
    "chars": 9871,
    "preview": "#!/bin/sh /etc/rc.common\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free softwar"
  },
  {
    "path": "package/luci-lite/files/root/usr/share/luci/menu.d/luci-app-smartdns-lite.json",
    "chars": 244,
    "preview": "{\n\t\"admin/services/smartdns-lite\": {\n\t\t\"title\": \"SmartDNS Lite\",\n\t\t\"action\": {\n\t\t\t\"type\": \"view\",\n\t\t\t\"path\": \"smartdns-l"
  },
  {
    "path": "package/luci-lite/files/root/usr/share/rpcd/acl.d/luci-app-smartdns-lite.json",
    "chars": 470,
    "preview": "{\n\t\"luci-app-smartdns-lite\": {\n\t\t\"description\": \"Grant access to LuCI app smartdns\",\n\t\t\"read\": {\n\t\t\t\"file\": {\n\t\t\t\t\"/etc/"
  },
  {
    "path": "package/luci-lite/files/root/www/luci-static/resources/view/smartdns-lite/smartdns-lite.js",
    "chars": 14026,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "package/luci-lite/make.sh",
    "chars": 3777,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/openwrt/Makefile",
    "chars": 4716,
    "preview": "#\n# Copyright (c) 2018-2025 Nick Peng (pymumu@gmail.com)\n# This is free software, licensed under the GNU General Public "
  },
  {
    "path": "package/openwrt/address.conf",
    "chars": 824,
    "preview": "# Add domains which you want to force to an IP address here.\n# The example below send any host in example.com to a local"
  },
  {
    "path": "package/openwrt/blacklist-ip.conf",
    "chars": 231,
    "preview": "# Add IP blacklist which you want to filtering from some DNS server here.\n# The example below filtering ip from the resu"
  },
  {
    "path": "package/openwrt/control/conffiles",
    "chars": 175,
    "preview": "/etc/config/smartdns\n/etc/smartdns/address.conf\n/etc/smartdns/blacklist-ip.conf\n/etc/smartdns/custom.conf\n/etc/smartdns/"
  },
  {
    "path": "package/openwrt/control/control",
    "chars": 203,
    "preview": "Package: smartdns\nArchitecture: \nPriority: optional\nSection: net\nVersion: \nDepends: libc, libopenssl, libpthread\nMaintai"
  },
  {
    "path": "package/openwrt/control/postinst",
    "chars": 935,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/openwrt/control/prerm",
    "chars": 1028,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/openwrt/custom.conf",
    "chars": 97,
    "preview": "# Add custom settings here.\n# please read https://pymumu.github.io/smartdns/config/basic-config/\n"
  },
  {
    "path": "package/openwrt/debian-binary",
    "chars": 4,
    "preview": "2.0\n"
  },
  {
    "path": "package/openwrt/domain-block.list",
    "chars": 96,
    "preview": "# domain block list, one domain name per line.\n# example: block a.com, and b.com\n# a.com\n# b.com"
  },
  {
    "path": "package/openwrt/domain-forwarding.list",
    "chars": 106,
    "preview": "# domain forwarding list, one domain name per line.\n# example: forwarding a.com, and b.com\n# a.com\n# b.com"
  },
  {
    "path": "package/openwrt/files/etc/config/smartdns",
    "chars": 62,
    "preview": "config 'smartdns'\n\toption 'enabled' '0'\n\t\nconfig 'domain-rule'"
  },
  {
    "path": "package/openwrt/files/etc/init.d/smartdns",
    "chars": 35670,
    "preview": "#!/bin/sh /etc/rc.common\n\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n\n# smartdns is free software "
  },
  {
    "path": "package/openwrt/make.sh",
    "chars": 5111,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/optware/S50smartdns",
    "chars": 11439,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/optware/control/conffiles",
    "chars": 68,
    "preview": "/opt/etc/smartdns/smartdns.conf\n/opt/etc/smartdns/smartdns-opt.conf\n"
  },
  {
    "path": "package/optware/control/control",
    "chars": 208,
    "preview": "Package: smartdns\nArchitecture: mipsbig\nPriority: optional\nSection: net\nVersion: 2018.7.6-1921\nMaintainer: pymumu\nSource"
  },
  {
    "path": "package/optware/control/postinst",
    "chars": 781,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/optware/control/prerm",
    "chars": 739,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/optware/debian-binary",
    "chars": 4,
    "preview": "2.0\n"
  },
  {
    "path": "package/optware/make.sh",
    "chars": 3517,
    "preview": "#!/bin/sh\n#\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redi"
  },
  {
    "path": "package/optware/smartdns-opt.conf",
    "chars": 174,
    "preview": "# workmode \n# 0: run as port only\n# 1: redirect port\n# 2: replace \nSMARTDNS_WORKMODE=\"1\"\n\n# smartdns port\nSMARTDNS_PORT="
  },
  {
    "path": "package/redhat/smartdns.spec",
    "chars": 1475,
    "preview": "Name:           smartdns\nVersion:        1.2020.09.08\nRelease:        2235%{?dist}\nSummary:        smartdns\n\nLicense:   "
  },
  {
    "path": "package/run-smartdns",
    "chars": 949,
    "preview": "#!/bin/sh\n\nCWD=$(pwd)\nreal_path=$(readlink -f \"$0\")\nCURDIR=$(cd $(dirname $real_path); pwd)\nSMARTDNS_BIN=${CURDIR}/smart"
  },
  {
    "path": "package/tool/po2lmo/Makefile",
    "chars": 246,
    "preview": "\nINSTALL = install\nPREFIX  = /usr/bin\nCFLAGS  = -Wall -O2\npo2lmo: src/po2lmo.o src/template_lmo.o\n\t$(CC) $(LDFLAGS) -o s"
  },
  {
    "path": "package/tool/po2lmo/src/po2lmo.c",
    "chars": 4715,
    "preview": "/*\n * lmo - Lua Machine Objects - PO to LMO conversion tool\n *\n *   Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsigna"
  },
  {
    "path": "package/tool/po2lmo/src/template_lmo.c",
    "chars": 5884,
    "preview": "/*\n * lmo - Lua Machine Objects - Base functions\n *\n *   Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>\n *\n "
  },
  {
    "path": "package/tool/po2lmo/src/template_lmo.h",
    "chars": 2243,
    "preview": "/*\n * lmo - Lua Machine Objects - General header\n *\n *   Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>\n *\n "
  },
  {
    "path": "package/windows/install.bat",
    "chars": 484,
    "preview": "@echo off\r\nset \"CURR_PATH=%~dp0\"\r\nset \"STARTUP_PATH=%userprofile%\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\"
  },
  {
    "path": "package/windows/reload.bat",
    "chars": 511,
    "preview": "@echo off\r\nset \"CURR_PATH=%~dp0\"\r\nset \"STARTUP_PATH=%userprofile%\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\"
  },
  {
    "path": "package/windows/uninstall.bat",
    "chars": 471,
    "preview": "@echo off\r\nset \"CURR_PATH=%~dp0\"\r\nset \"STARTUP_PATH=%userprofile%\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\"
  },
  {
    "path": "package/windows/wsl-run.vbs",
    "chars": 102,
    "preview": "Set ws = WScript.CreateObject(\"WScript.Shell\")\r\nws.run \"wsl sudo /etc/init.d/smartdns restart\", vbhide"
  },
  {
    "path": "plugin/demo/.gitignore",
    "chars": 24,
    "preview": ".vscode\n*.o\n*.so\n*.swp.\n"
  },
  {
    "path": "plugin/demo/Makefile",
    "chars": 1360,
    "preview": "\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redistribute it"
  },
  {
    "path": "plugin/demo/demo.c",
    "chars": 1514,
    "preview": "#include \"demo.h\"\n#include \"smartdns/dns_server.h\"\n#include \"smartdns/tlog.h\"\n#include \"smartdns/util.h\"\n#include <arpa/"
  },
  {
    "path": "plugin/demo/demo.h",
    "chars": 210,
    "preview": "\n#ifndef SMART_DNS_PLUGIN_DEMO_H\n#define SMART_DNS_PLUGIN_DEMO_H\n\n#include \"smartdns/dns_plugin.h\"\n\n#ifdef __cplusplus\ne"
  },
  {
    "path": "plugin/smartdns-ui/.gitignore",
    "chars": 18,
    "preview": "/target\nCargo.lock"
  },
  {
    "path": "plugin/smartdns-ui/Cargo.toml",
    "chars": 1520,
    "preview": "[package]\nname = \"smartdns-ui\"\nversion = \"1.0.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"cdylib\", \"lib\"]\n\n[dependencies]\n"
  },
  {
    "path": "plugin/smartdns-ui/Makefile",
    "chars": 4187,
    "preview": "\n# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redistribute it"
  },
  {
    "path": "plugin/smartdns-ui/build.rs",
    "chars": 3699,
    "preview": "use std::collections::HashSet;\nuse std::env;\nuse std::path::PathBuf;\n\n#[derive(Debug)]\nstruct IgnoreMacros(HashSet<Strin"
  },
  {
    "path": "plugin/smartdns-ui/src/data_server.rs",
    "chars": 30116,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/data_stats.rs",
    "chars": 15562,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/data_upstream_server.rs",
    "chars": 2564,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/db.rs",
    "chars": 55358,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/http_api_msg.rs",
    "chars": 31039,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/http_error.rs",
    "chars": 2744,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/http_jwt.rs",
    "chars": 2942,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/http_server.rs",
    "chars": 33190,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/http_server_api.rs",
    "chars": 44632,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/http_server_stream.rs",
    "chars": 19893,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/lib.rs",
    "chars": 1861,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/plugin.rs",
    "chars": 7347,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/server_log.rs",
    "chars": 3937,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/smartdns.rs",
    "chars": 28913,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/utils.rs",
    "chars": 3223,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/src/whois.rs",
    "chars": 8682,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/tests/common/client.rs",
    "chars": 5632,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/tests/common/mod.rs",
    "chars": 853,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/tests/common/server.rs",
    "chars": 13859,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/tests/httpserver_test.rs",
    "chars": 3269,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "plugin/smartdns-ui/tests/restapi_test.rs",
    "chars": 22551,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/.gitignore",
    "chars": 47,
    "preview": ".vscode\n.o\n.DS_Store\n.swp.\nsmartdns\n!smartdns/\n"
  },
  {
    "path": "src/Makefile",
    "chars": 3716,
    "preview": "# Copyright (C) 2018-2025 Ruilin Peng (Nick) <pymumu@gmail.com>.\n#\n# smartdns is free software: you can redistribute it "
  },
  {
    "path": "src/dns.c",
    "chars": 79017,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_cache.c",
    "chars": 26592,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_http2.c",
    "chars": 16382,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_http2.h",
    "chars": 1701,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_http3.c",
    "chars": 4213,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_http3.h",
    "chars": 1234,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_https.c",
    "chars": 3079,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_https.h",
    "chars": 1246,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_mdns.c",
    "chars": 6017,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_mdns.h",
    "chars": 1187,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_quic.c",
    "chars": 20795,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_quic.h",
    "chars": 1517,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_socket.c",
    "chars": 9515,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_socket.h",
    "chars": 1630,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_tcp.c",
    "chars": 15144,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_tcp.h",
    "chars": 1322,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_tls.c",
    "chars": 28131,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_tls.h",
    "chars": 1955,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_udp.c",
    "chars": 14362,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/client_udp.h",
    "chars": 1341,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/conn_stream.c",
    "chars": 3203,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/conn_stream.h",
    "chars": 1298,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/dns_client.c",
    "chars": 21288,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/dns_client.h",
    "chars": 6480,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/ecs.c",
    "chars": 3288,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/ecs.h",
    "chars": 1247,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/group.c",
    "chars": 5935,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/group.h",
    "chars": 1350,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/packet.c",
    "chars": 3448,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/packet.h",
    "chars": 1229,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/pending_server.c",
    "chars": 13927,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/pending_server.h",
    "chars": 1780,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/proxy.c",
    "chars": 3244,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/proxy.h",
    "chars": 1113,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/query.c",
    "chars": 10002,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/query.h",
    "chars": 1867,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/server_info.c",
    "chars": 18088,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/server_info.h",
    "chars": 1705,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/wake_event.c",
    "chars": 1991,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_client/wake_event.h",
    "chars": 1162,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/address.c",
    "chars": 5129,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/address.h",
    "chars": 1144,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/bind.c",
    "chars": 11141,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/bind.h",
    "chars": 1338,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/bootstrap_dns.c",
    "chars": 1298,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/bootstrap_dns.h",
    "chars": 1062,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/client_rule.c",
    "chars": 12533,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/client_rule.h",
    "chars": 1302,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/client_subnet.c",
    "chars": 2295,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/client_subnet.h",
    "chars": 1213,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/cname.c",
    "chars": 2027,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/cname.h",
    "chars": 1133,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/conf_file.c",
    "chars": 4242,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/conf_file.h",
    "chars": 1159,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/ddns_domain.c",
    "chars": 1309,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/ddns_domain.h",
    "chars": 1082,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/dhcp_lease_dnsmasq.c",
    "chars": 3014,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/dhcp_lease_dnsmasq.h",
    "chars": 1148,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/dns64.c",
    "chars": 2123,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/dns64.h",
    "chars": 1098,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/dns_conf.c",
    "chars": 17201,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/dns_conf.h",
    "chars": 1202,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/dns_conf_group.c",
    "chars": 12592,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/dns_conf_group.h",
    "chars": 2503,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/domain_rule.c",
    "chars": 31661,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/domain_rule.h",
    "chars": 2049,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/domain_set.c",
    "chars": 4078,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/domain_set.h",
    "chars": 1178,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/get_domain.c",
    "chars": 2045,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/get_domain.h",
    "chars": 1109,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/group.c",
    "chars": 3748,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/group.h",
    "chars": 1192,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/host_file.c",
    "chars": 6840,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/host_file.h",
    "chars": 1267,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  },
  {
    "path": "src/dns_conf/https_record.c",
    "chars": 6667,
    "preview": "/*************************************************************************\n *\n * Copyright (C) 2018-2025 Ruilin Peng (Ni"
  }
]

// ... and 205 more files (download for full content)

About this extraction

This page contains the full source code of the pymumu/smartdns GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 405 files (2.5 MB), approximately 686.3k tokens, and a symbol index with 3220 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!