Showing preview only (7,636K chars total). Download the full file or copy to clipboard to get everything.
Repository: AdguardTeam/AdGuardHome
Branch: master
Commit: d7b6dc0cf7a1
Files: 933
Total size: 7.1 MB
Directory structure:
gitextract_lq2m_xle/
├── .codecov.yml
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug.yml
│ │ ├── config.yml
│ │ └── feature.yml
│ ├── PULL_REQUEST_TEMPLATE
│ ├── stale.yml
│ └── workflows/
│ ├── build.yml
│ ├── lint.yml
│ └── potential-duplicates.yml
├── .gitignore
├── .markdownlint.json
├── .twosky.json
├── AGHTechDoc.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── HACKING.md
├── LICENSE.txt
├── Makefile
├── README.md
├── SECURITY.md
├── bamboo-specs/
│ ├── bamboo.yaml
│ ├── release.yaml
│ ├── snapcraft.yaml
│ └── test.yaml
├── build/
│ └── gitkeep
├── changelog.config.js
├── client/
│ ├── .eslintrc.json
│ ├── .gitattributes
│ ├── .prettierrc
│ ├── .stylelintrc.js
│ ├── babel.config.cjs
│ ├── constants.js
│ ├── dev.eslintrc
│ ├── global.d.ts
│ ├── package.json
│ ├── playwright.config.ts
│ ├── prod.eslintrc
│ ├── public/
│ │ ├── index.html
│ │ ├── install.html
│ │ └── login.html
│ ├── src/
│ │ ├── __locales/
│ │ │ ├── ar.json
│ │ │ ├── be.json
│ │ │ ├── bg.json
│ │ │ ├── cs.json
│ │ │ ├── da.json
│ │ │ ├── de.json
│ │ │ ├── en.json
│ │ │ ├── es.json
│ │ │ ├── fa.json
│ │ │ ├── fi.json
│ │ │ ├── fr.json
│ │ │ ├── hr.json
│ │ │ ├── hu.json
│ │ │ ├── id.json
│ │ │ ├── it.json
│ │ │ ├── ja.json
│ │ │ ├── ko.json
│ │ │ ├── nl.json
│ │ │ ├── no.json
│ │ │ ├── pl.json
│ │ │ ├── pt-br.json
│ │ │ ├── pt-pt.json
│ │ │ ├── ro.json
│ │ │ ├── ru.json
│ │ │ ├── si-lk.json
│ │ │ ├── sk.json
│ │ │ ├── sl.json
│ │ │ ├── sr-cs.json
│ │ │ ├── sv.json
│ │ │ ├── th.json
│ │ │ ├── tr.json
│ │ │ ├── uk.json
│ │ │ ├── vi.json
│ │ │ ├── zh-cn.json
│ │ │ ├── zh-hk.json
│ │ │ └── zh-tw.json
│ │ ├── __locales-services/
│ │ │ ├── ar.json
│ │ │ ├── be.json
│ │ │ ├── bg.json
│ │ │ ├── cs.json
│ │ │ ├── da.json
│ │ │ ├── de.json
│ │ │ ├── en.json
│ │ │ ├── es.json
│ │ │ ├── fa.json
│ │ │ ├── fi.json
│ │ │ ├── fr.json
│ │ │ ├── hr.json
│ │ │ ├── hu.json
│ │ │ ├── id.json
│ │ │ ├── it.json
│ │ │ ├── ja.json
│ │ │ ├── ko.json
│ │ │ ├── nl.json
│ │ │ ├── no.json
│ │ │ ├── pl.json
│ │ │ ├── pt-br.json
│ │ │ ├── pt-pt.json
│ │ │ ├── ro.json
│ │ │ ├── ru.json
│ │ │ ├── si-lk.json
│ │ │ ├── sk.json
│ │ │ ├── sl.json
│ │ │ ├── sr-cs.json
│ │ │ ├── sv.json
│ │ │ ├── th.json
│ │ │ ├── tr.json
│ │ │ ├── uk.json
│ │ │ ├── vi.json
│ │ │ ├── zh-cn.json
│ │ │ ├── zh-hk.json
│ │ │ └── zh-tw.json
│ │ ├── __tests__/
│ │ │ └── helpers.test.ts
│ │ ├── actions/
│ │ │ ├── access.ts
│ │ │ ├── clients.ts
│ │ │ ├── dnsConfig.ts
│ │ │ ├── encryption.ts
│ │ │ ├── filtering.ts
│ │ │ ├── index.tsx
│ │ │ ├── install.ts
│ │ │ ├── login.ts
│ │ │ ├── queryLogs.ts
│ │ │ ├── rewrites.ts
│ │ │ ├── services.ts
│ │ │ ├── stats.ts
│ │ │ └── toasts.ts
│ │ ├── api/
│ │ │ └── Api.ts
│ │ ├── components/
│ │ │ ├── App/
│ │ │ │ ├── index.css
│ │ │ │ └── index.tsx
│ │ │ ├── Dashboard/
│ │ │ │ ├── BlockedDomains.tsx
│ │ │ │ ├── Clients.tsx
│ │ │ │ ├── Counters.tsx
│ │ │ │ ├── Dashboard.css
│ │ │ │ ├── DomainCell.tsx
│ │ │ │ ├── QueriedDomains.tsx
│ │ │ │ ├── Statistics.tsx
│ │ │ │ ├── StatsCard.tsx
│ │ │ │ ├── UpstreamAvgTime.tsx
│ │ │ │ ├── UpstreamResponses.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── Filters/
│ │ │ │ ├── Actions.tsx
│ │ │ │ ├── Check/
│ │ │ │ │ ├── Info.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── CustomRules.tsx
│ │ │ │ ├── DnsAllowlist.tsx
│ │ │ │ ├── DnsBlocklist.tsx
│ │ │ │ ├── Examples.tsx
│ │ │ │ ├── FiltersList.tsx
│ │ │ │ ├── Form.tsx
│ │ │ │ ├── Modal.tsx
│ │ │ │ ├── Rewrites/
│ │ │ │ │ ├── Form.tsx
│ │ │ │ │ ├── Modal.tsx
│ │ │ │ │ ├── Table.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── Services/
│ │ │ │ │ ├── Form.tsx
│ │ │ │ │ ├── ScheduleForm/
│ │ │ │ │ │ ├── Modal.tsx
│ │ │ │ │ │ ├── TimePeriod.tsx
│ │ │ │ │ │ ├── TimeSelect.tsx
│ │ │ │ │ │ ├── Timezone.tsx
│ │ │ │ │ │ ├── helpers.ts
│ │ │ │ │ │ ├── index.tsx
│ │ │ │ │ │ └── styles.css
│ │ │ │ │ ├── ServiceField.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ └── Table.tsx
│ │ │ ├── Header/
│ │ │ │ ├── Header.css
│ │ │ │ ├── Menu.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── Logs/
│ │ │ │ ├── AnonymizerNotification.tsx
│ │ │ │ ├── Cells/
│ │ │ │ │ ├── ClientCell.tsx
│ │ │ │ │ ├── DateCell.tsx
│ │ │ │ │ ├── DomainCell.tsx
│ │ │ │ │ ├── Header.tsx
│ │ │ │ │ ├── HeaderCell.tsx
│ │ │ │ │ ├── IconTooltip.css
│ │ │ │ │ ├── IconTooltip.tsx
│ │ │ │ │ ├── ResponseCell.tsx
│ │ │ │ │ ├── helpers/
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── Disabled.tsx
│ │ │ │ ├── Filters/
│ │ │ │ │ ├── Form.tsx
│ │ │ │ │ ├── SearchField.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── InfiniteTable.tsx
│ │ │ │ ├── Logs.css
│ │ │ │ └── index.tsx
│ │ │ ├── ProtectionTimer/
│ │ │ │ └── index.ts
│ │ │ ├── Settings/
│ │ │ │ ├── Clients/
│ │ │ │ │ ├── AutoClients.tsx
│ │ │ │ │ ├── ClientsTable/
│ │ │ │ │ │ ├── ClientsTable.tsx
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── Form/
│ │ │ │ │ │ ├── components/
│ │ │ │ │ │ │ ├── BlockedServices.tsx
│ │ │ │ │ │ │ ├── ClientIds.tsx
│ │ │ │ │ │ │ ├── MainSettings.tsx
│ │ │ │ │ │ │ ├── ScheduleServices.tsx
│ │ │ │ │ │ │ ├── UpstreamDns.tsx
│ │ │ │ │ │ │ └── index.ts
│ │ │ │ │ │ ├── index.tsx
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ ├── Modal.tsx
│ │ │ │ │ ├── Service.css
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── whoisCell.tsx
│ │ │ │ ├── Dhcp/
│ │ │ │ │ ├── FormDHCPv4.tsx
│ │ │ │ │ ├── FormDHCPv6.tsx
│ │ │ │ │ ├── Interfaces.tsx
│ │ │ │ │ ├── Leases.tsx
│ │ │ │ │ ├── StaticLeases/
│ │ │ │ │ │ ├── Form.tsx
│ │ │ │ │ │ ├── Modal.tsx
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ ├── index.css
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── Dns/
│ │ │ │ │ ├── Access/
│ │ │ │ │ │ ├── Form.tsx
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ ├── Cache/
│ │ │ │ │ │ ├── Form.tsx
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ ├── Config/
│ │ │ │ │ │ ├── Form.tsx
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ ├── Upstream/
│ │ │ │ │ │ ├── Examples.tsx
│ │ │ │ │ │ ├── Form.tsx
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── Encryption/
│ │ │ │ │ ├── CertificateStatus.tsx
│ │ │ │ │ ├── Form.tsx
│ │ │ │ │ ├── KeyStatus.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── FiltersConfig/
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── FormButton.css
│ │ │ │ ├── LogsConfig/
│ │ │ │ │ ├── Form.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── Settings.css
│ │ │ │ ├── StatsConfig/
│ │ │ │ │ ├── Form.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── SetupGuide/
│ │ │ │ ├── Guide.css
│ │ │ │ └── index.tsx
│ │ │ ├── Toasts/
│ │ │ │ ├── Toast.css
│ │ │ │ ├── Toast.tsx
│ │ │ │ └── index.tsx
│ │ │ └── ui/
│ │ │ ├── Card.css
│ │ │ ├── Card.tsx
│ │ │ ├── Cell.tsx
│ │ │ ├── CellWrap.tsx
│ │ │ ├── Controls/
│ │ │ │ ├── Checkbox/
│ │ │ │ │ ├── checkbox.css
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── Input.tsx
│ │ │ │ ├── Radio.tsx
│ │ │ │ ├── Select.tsx
│ │ │ │ └── Textarea.tsx
│ │ │ ├── Dropdown.css
│ │ │ ├── Dropdown.tsx
│ │ │ ├── EncryptionTopline.tsx
│ │ │ ├── Footer.css
│ │ │ ├── Footer.tsx
│ │ │ ├── Guide/
│ │ │ │ ├── Guide.tsx
│ │ │ │ ├── MobileConfigForm.tsx
│ │ │ │ └── index.ts
│ │ │ ├── Icons.css
│ │ │ ├── Icons.tsx
│ │ │ ├── Line.css
│ │ │ ├── Line.tsx
│ │ │ ├── Loading.css
│ │ │ ├── Loading.tsx
│ │ │ ├── LogsSearchLink.tsx
│ │ │ ├── Modal.css
│ │ │ ├── Overlay.css
│ │ │ ├── PageTitle.css
│ │ │ ├── PageTitle.tsx
│ │ │ ├── ReactTable.css
│ │ │ ├── Select.css
│ │ │ ├── Status.tsx
│ │ │ ├── Tab.tsx
│ │ │ ├── Tabler.css
│ │ │ ├── Tabs.css
│ │ │ ├── Tabs.tsx
│ │ │ ├── Tooltip.css
│ │ │ ├── Tooltip.tsx
│ │ │ ├── Topline.css
│ │ │ ├── Topline.tsx
│ │ │ ├── UpdateOverlay.tsx
│ │ │ ├── UpdateTopline.tsx
│ │ │ ├── Version.css
│ │ │ ├── Version.tsx
│ │ │ ├── svg/
│ │ │ │ └── logo.tsx
│ │ │ └── texareaCommentsHighlight.css
│ │ ├── configureStore.ts
│ │ ├── containers/
│ │ │ ├── Clients.ts
│ │ │ ├── CustomRules.ts
│ │ │ ├── Dashboard.ts
│ │ │ ├── Dhcp.ts
│ │ │ ├── Dns.ts
│ │ │ ├── DnsAllowlist.ts
│ │ │ ├── DnsBlocklist.ts
│ │ │ ├── DnsRewrites.ts
│ │ │ ├── Encryption.ts
│ │ │ ├── Settings.ts
│ │ │ └── SetupGuide.ts
│ │ ├── helpers/
│ │ │ ├── constants.ts
│ │ │ ├── filters/
│ │ │ │ └── filters.ts
│ │ │ ├── form.tsx
│ │ │ ├── helpers.tsx
│ │ │ ├── highlightTextareaComments.tsx
│ │ │ ├── localStorageHelper.ts
│ │ │ ├── renderFormattedClientCell.tsx
│ │ │ ├── trackers/
│ │ │ │ ├── trackers.json
│ │ │ │ ├── trackers.ts
│ │ │ │ └── whotracksme_web.json
│ │ │ ├── twosky.ts
│ │ │ ├── useDebounce.ts
│ │ │ ├── validators.ts
│ │ │ └── version.ts
│ │ ├── i18n.ts
│ │ ├── index.tsx
│ │ ├── initialState.ts
│ │ ├── install/
│ │ │ ├── Setup/
│ │ │ │ ├── AddressList.tsx
│ │ │ │ ├── Auth.tsx
│ │ │ │ ├── Controls.tsx
│ │ │ │ ├── Devices.tsx
│ │ │ │ ├── Greeting.tsx
│ │ │ │ ├── Progress.tsx
│ │ │ │ ├── Settings.tsx
│ │ │ │ ├── Setup.css
│ │ │ │ ├── Submit.tsx
│ │ │ │ └── index.tsx
│ │ │ └── index.tsx
│ │ ├── login/
│ │ │ ├── Login/
│ │ │ │ ├── Form.tsx
│ │ │ │ ├── Login.css
│ │ │ │ └── index.tsx
│ │ │ └── index.tsx
│ │ ├── reducers/
│ │ │ ├── access.ts
│ │ │ ├── clients.ts
│ │ │ ├── dashboard.ts
│ │ │ ├── dhcp.ts
│ │ │ ├── dnsConfig.ts
│ │ │ ├── encryption.ts
│ │ │ ├── filtering.ts
│ │ │ ├── index.ts
│ │ │ ├── install.ts
│ │ │ ├── login.ts
│ │ │ ├── queryLogs.ts
│ │ │ ├── rewrites.ts
│ │ │ ├── services.ts
│ │ │ ├── settings.ts
│ │ │ ├── stats.ts
│ │ │ └── toasts.ts
│ │ └── types.d.ts
│ ├── tests/
│ │ ├── constants.ts
│ │ ├── e2e/
│ │ │ ├── control-panel.spec.ts
│ │ │ ├── dhcp.spec.ts
│ │ │ ├── dns-settings.spec.ts
│ │ │ ├── filtering.spec.ts
│ │ │ ├── general-settings.spec.ts
│ │ │ ├── globalSetup.ts
│ │ │ ├── globalTeardown.ts
│ │ │ ├── login.spec.ts
│ │ │ ├── querylog.spec.ts
│ │ │ └── rewrites.spec.ts
│ │ └── helpers/
│ │ └── network.ts
│ ├── tsconfig.json
│ ├── vitest.config.ts
│ ├── webpack.common.js
│ ├── webpack.dev.js
│ └── webpack.prod.js
├── docker/
│ ├── build.Dockerfile
│ ├── build.Dockerfile.dockerignore
│ ├── ci.Dockerfile
│ ├── ci.Dockerfile.dockerignore
│ ├── frontend.Dockerfile
│ ├── frontend.Dockerfile.dockerignore
│ ├── snapcraft.Dockerfile
│ └── snapcraft.Dockerfile.dockerignore
├── go.mod
├── go.sum
├── internal/
│ ├── agh/
│ │ └── agh.go
│ ├── aghalg/
│ │ ├── aghalg.go
│ │ ├── nullbool.go
│ │ ├── nullbool_test.go
│ │ ├── sortedmap.go
│ │ └── sortedmap_test.go
│ ├── aghhttp/
│ │ ├── aghhttp.go
│ │ ├── header.go
│ │ ├── json.go
│ │ ├── json_test.go
│ │ └── registrar.go
│ ├── aghnet/
│ │ ├── addr.go
│ │ ├── dhcp.go
│ │ ├── dhcp_unix.go
│ │ ├── dhcp_windows.go
│ │ ├── hostgen.go
│ │ ├── hostgen_test.go
│ │ ├── hostscontainer.go
│ │ ├── hostscontainer_internal_test.go
│ │ ├── hostscontainer_test.go
│ │ ├── ignore.go
│ │ ├── ignore_test.go
│ │ ├── interfaces.go
│ │ ├── interfaces_bsd.go
│ │ ├── interfaces_linux.go
│ │ ├── interfaces_test.go
│ │ ├── ipmut.go
│ │ ├── ipmut_test.go
│ │ ├── net.go
│ │ ├── net_bsd.go
│ │ ├── net_darwin.go
│ │ ├── net_darwin_internal_test.go
│ │ ├── net_freebsd.go
│ │ ├── net_freebsd_internal_test.go
│ │ ├── net_internal_test.go
│ │ ├── net_linux.go
│ │ ├── net_linux_internal_test.go
│ │ ├── net_openbsd.go
│ │ ├── net_openbsd_internal_test.go
│ │ ├── net_test.go
│ │ ├── net_unix.go
│ │ ├── net_windows.go
│ │ ├── upstream.go
│ │ └── upstream_test.go
│ ├── aghos/
│ │ ├── filewalker.go
│ │ ├── filewalker_internal_test.go
│ │ ├── filewalker_test.go
│ │ ├── fswatcher.go
│ │ ├── os.go
│ │ ├── os_bsd.go
│ │ ├── os_freebsd.go
│ │ ├── os_internal_test.go
│ │ ├── os_linux.go
│ │ ├── os_unix.go
│ │ ├── os_windows.go
│ │ ├── service.go
│ │ ├── service_darwin.go
│ │ ├── service_others.go
│ │ ├── syslog.go
│ │ ├── syslog_others.go
│ │ ├── syslog_windows.go
│ │ ├── user.go
│ │ ├── user_unix.go
│ │ └── user_windows.go
│ ├── aghrenameio/
│ │ ├── renameio.go
│ │ ├── renameio_test.go
│ │ ├── renameio_unix.go
│ │ └── renameio_windows.go
│ ├── aghslog/
│ │ └── aghslog.go
│ ├── aghtest/
│ │ ├── aghtest.go
│ │ ├── interface.go
│ │ ├── interface_test.go
│ │ └── upstream.go
│ ├── aghtls/
│ │ ├── aghtls.go
│ │ ├── aghtls_test.go
│ │ ├── defaultmanager.go
│ │ ├── manager.go
│ │ ├── root.go
│ │ ├── root_linux.go
│ │ └── root_others.go
│ ├── aghuser/
│ │ ├── aghuser.go
│ │ ├── aghuser_test.go
│ │ ├── db.go
│ │ ├── db_test.go
│ │ ├── session.go
│ │ ├── sessionstorage.go
│ │ ├── sessionstorage_test.go
│ │ └── user.go
│ ├── arpdb/
│ │ ├── arpdb.go
│ │ ├── arpdb_bsd.go
│ │ ├── arpdb_bsd_internal_test.go
│ │ ├── arpdb_internal_test.go
│ │ ├── arpdb_linux.go
│ │ ├── arpdb_linux_internal_test.go
│ │ ├── arpdb_openbsd.go
│ │ ├── arpdb_openbsd_internal_test.go
│ │ ├── arpdb_windows.go
│ │ ├── arpdb_windows_internal_test.go
│ │ └── testdata/
│ │ └── proc_net_arp
│ ├── client/
│ │ ├── addrproc.go
│ │ ├── addrproc_test.go
│ │ ├── client.go
│ │ ├── client_test.go
│ │ ├── index.go
│ │ ├── index_internal_test.go
│ │ ├── persistent.go
│ │ ├── persistent_internal_test.go
│ │ ├── runtimeindex.go
│ │ ├── storage.go
│ │ ├── storage_test.go
│ │ └── upstreammanager.go
│ ├── configmigrate/
│ │ ├── configmigrate.go
│ │ ├── configmigrate_internal_test.go
│ │ ├── configmigrate_test.go
│ │ ├── migrations_internal_test.go
│ │ ├── migrator.go
│ │ ├── migrator_test.go
│ │ ├── testdata/
│ │ │ └── TestMigrateConfig_Migrate/
│ │ │ ├── v1/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v10/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v11/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v12/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v13/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v14/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v15/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v16/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v17/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v18/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v19/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v2/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v20/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v21/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v22/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v23/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v24/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v25/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v26/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v27/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v28/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v29/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v3/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v30/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v31/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v32/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v33/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v4/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v5/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v6/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v7/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ ├── v8/
│ │ │ │ ├── input.yml
│ │ │ │ └── output.yml
│ │ │ └── v9/
│ │ │ ├── input.yml
│ │ │ └── output.yml
│ │ ├── v1.go
│ │ ├── v10.go
│ │ ├── v11.go
│ │ ├── v12.go
│ │ ├── v13.go
│ │ ├── v14.go
│ │ ├── v15.go
│ │ ├── v16.go
│ │ ├── v17.go
│ │ ├── v18.go
│ │ ├── v19.go
│ │ ├── v2.go
│ │ ├── v20.go
│ │ ├── v21.go
│ │ ├── v22.go
│ │ ├── v23.go
│ │ ├── v24.go
│ │ ├── v25.go
│ │ ├── v26.go
│ │ ├── v27.go
│ │ ├── v28.go
│ │ ├── v29.go
│ │ ├── v3.go
│ │ ├── v30.go
│ │ ├── v31.go
│ │ ├── v32.go
│ │ ├── v33.go
│ │ ├── v4.go
│ │ ├── v5.go
│ │ ├── v6.go
│ │ ├── v7.go
│ │ ├── v8.go
│ │ ├── v9.go
│ │ └── yaml.go
│ ├── dhcpd/
│ │ ├── README.md
│ │ ├── bitset.go
│ │ ├── bitset_internal_test.go
│ │ ├── broadcast_bsd.go
│ │ ├── broadcast_bsd_internal_test.go
│ │ ├── broadcast_others.go
│ │ ├── broadcast_others_internal_test.go
│ │ ├── config.go
│ │ ├── conn_bsd.go
│ │ ├── conn_bsd_internal_test.go
│ │ ├── conn_linux.go
│ │ ├── conn_linux_internal_test.go
│ │ ├── conn_unix.go
│ │ ├── db.go
│ │ ├── dhcpd.go
│ │ ├── dhcpd_internal_test.go
│ │ ├── dhcpd_unix_internal_test.go
│ │ ├── http_unix.go
│ │ ├── http_unix_internal_test.go
│ │ ├── http_windows.go
│ │ ├── http_windows_internal_test.go
│ │ ├── iprange.go
│ │ ├── iprange_internal_test.go
│ │ ├── migrate.go
│ │ ├── migrate_internal_test.go
│ │ ├── options_unix.go
│ │ ├── options_unix_internal_test.go
│ │ ├── routeradv.go
│ │ ├── routeradv_internal_test.go
│ │ ├── v46_windows.go
│ │ ├── v4_unix.go
│ │ ├── v4_unix_internal_test.go
│ │ ├── v6_unix.go
│ │ └── v6_unix_internal_test.go
│ ├── dhcpsvc/
│ │ ├── addresschecker.go
│ │ ├── bitset.go
│ │ ├── bitset_internal_test.go
│ │ ├── config.go
│ │ ├── config_test.go
│ │ ├── db.go
│ │ ├── db_internal_test.go
│ │ ├── dhcpsvc.go
│ │ ├── dhcpsvc_test.go
│ │ ├── errors.go
│ │ ├── handle.go
│ │ ├── handler4.go
│ │ ├── handler4_test.go
│ │ ├── handler6.go
│ │ ├── interface.go
│ │ ├── iprange.go
│ │ ├── iprange_internal_test.go
│ │ ├── lease.go
│ │ ├── lease_internal_test.go
│ │ ├── leaseindex.go
│ │ ├── networkdevice.go
│ │ ├── networkdevice_test.go
│ │ ├── options4.go
│ │ ├── options4_internal_test.go
│ │ ├── options4_test.go
│ │ ├── server.go
│ │ ├── server_test.go
│ │ ├── testdata/
│ │ │ ├── TestDHCPServer_RemoveLease/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_Reset/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_ServeEther4_decline/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_ServeEther4_discover/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_ServeEther4_discoverExpired/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_ServeEther4_release/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_ServeEther4_requestInitReboot/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_ServeEther4_requestRenew/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_ServeEther4_requestSelecting/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_UpdateStaticLease/
│ │ │ │ └── leases.json
│ │ │ ├── TestDHCPServer_index/
│ │ │ │ └── leases.json
│ │ │ └── TestServer_Leases/
│ │ │ └── leases.json
│ │ ├── v4.go
│ │ └── v6.go
│ ├── dnsforward/
│ │ ├── access.go
│ │ ├── access_internal_test.go
│ │ ├── clientid.go
│ │ ├── clientid_internal_test.go
│ │ ├── clientscontainer.go
│ │ ├── config.go
│ │ ├── config_internal_test.go
│ │ ├── configvalidator.go
│ │ ├── context.go
│ │ ├── dialcontext.go
│ │ ├── dns64.go
│ │ ├── dns64_internal_test.go
│ │ ├── dnsforward.go
│ │ ├── dnsforward_internal_test.go
│ │ ├── dnsrewrite.go
│ │ ├── dnsrewrite_internal_test.go
│ │ ├── filter.go
│ │ ├── filter_internal_test.go
│ │ ├── http.go
│ │ ├── http_internal_test.go
│ │ ├── ipset.go
│ │ ├── ipset_internal_test.go
│ │ ├── middleware.go
│ │ ├── middleware_internal_test.go
│ │ ├── msg.go
│ │ ├── process.go
│ │ ├── process_internal_test.go
│ │ ├── requesthandler.go
│ │ ├── requesthandler_internal_test.go
│ │ ├── stats.go
│ │ ├── stats_internal_test.go
│ │ ├── svcbmsg.go
│ │ ├── svcbmsg_internal_test.go
│ │ ├── testdata/
│ │ │ ├── TestDNSForwardHTTP_handleGetConfig.json
│ │ │ └── TestDNSForwardHTTP_handleSetConfig.json
│ │ ├── upstreams.go
│ │ └── upstreams_internal_test.go
│ ├── filtering/
│ │ ├── blocked.go
│ │ ├── dnsrewrite.go
│ │ ├── dnsrewrite_test.go
│ │ ├── filter.go
│ │ ├── filter_internal_test.go
│ │ ├── filtering.go
│ │ ├── filtering_internal_test.go
│ │ ├── filtering_test.go
│ │ ├── hashprefix/
│ │ │ ├── cache.go
│ │ │ ├── cache_internal_test.go
│ │ │ ├── hashprefix.go
│ │ │ └── hashprefix_internal_test.go
│ │ ├── hosts.go
│ │ ├── hosts_test.go
│ │ ├── http.go
│ │ ├── http_internal_test.go
│ │ ├── idgenerator.go
│ │ ├── idgenerator_internal_test.go
│ │ ├── path.go
│ │ ├── path_unix_internal_test.go
│ │ ├── path_windows_internal_test.go
│ │ ├── result.go
│ │ ├── rewrite/
│ │ │ ├── item.go
│ │ │ ├── item_internal_test.go
│ │ │ ├── storage.go
│ │ │ └── storage_internal_test.go
│ │ ├── rewritehttp.go
│ │ ├── rewritehttp_test.go
│ │ ├── rewrites.go
│ │ ├── rewrites_internal_test.go
│ │ ├── rulelist/
│ │ │ ├── engine.go
│ │ │ ├── engine_test.go
│ │ │ ├── error.go
│ │ │ ├── filter.go
│ │ │ ├── filter_test.go
│ │ │ ├── parser.go
│ │ │ ├── parser_test.go
│ │ │ ├── rulelist.go
│ │ │ ├── rulelist_test.go
│ │ │ ├── storage.go
│ │ │ ├── storage_test.go
│ │ │ ├── textengine.go
│ │ │ └── textengine_test.go
│ │ ├── safesearch/
│ │ │ ├── rules/
│ │ │ │ ├── bing.txt
│ │ │ │ ├── duckduckgo.txt
│ │ │ │ ├── ecosia.txt
│ │ │ │ ├── google.txt
│ │ │ │ ├── pixabay.txt
│ │ │ │ ├── yandex.txt
│ │ │ │ └── youtube.txt
│ │ │ ├── rules.go
│ │ │ ├── safesearch.go
│ │ │ ├── safesearch_internal_test.go
│ │ │ └── safesearch_test.go
│ │ ├── safesearch.go
│ │ ├── safesearchhttp.go
│ │ ├── servicelist.go
│ │ └── tests/
│ │ └── dns.txt
│ ├── home/
│ │ ├── auth.go
│ │ ├── auth_internal_test.go
│ │ ├── authglinet.go
│ │ ├── authglinet_internal_test.go
│ │ ├── authhttp.go
│ │ ├── authhttp_internal_test.go
│ │ ├── authratelimiter.go
│ │ ├── authratelimiter_internal_test.go
│ │ ├── clients.go
│ │ ├── clients_internal_test.go
│ │ ├── clientshttp.go
│ │ ├── clientshttp_internal_test.go
│ │ ├── config.go
│ │ ├── config_internal_test.go
│ │ ├── context.go
│ │ ├── control.go
│ │ ├── controlinstall.go
│ │ ├── controlupdate.go
│ │ ├── dns.go
│ │ ├── home.go
│ │ ├── home_internal_test.go
│ │ ├── httpclient.go
│ │ ├── httpclient_internal_test.go
│ │ ├── i18n.go
│ │ ├── log.go
│ │ ├── middlewares.go
│ │ ├── middlewares_internal_test.go
│ │ ├── mobileconfig.go
│ │ ├── mobileconfig_internal_test.go
│ │ ├── options.go
│ │ ├── options_internal_test.go
│ │ ├── profilehttp.go
│ │ ├── profilehttp_internal_test.go
│ │ ├── service.go
│ │ ├── signal.go
│ │ ├── tls.go
│ │ ├── tls_internal_test.go
│ │ └── web.go
│ ├── ipset/
│ │ ├── ipset.go
│ │ ├── ipset_linux.go
│ │ ├── ipset_linux_internal_test.go
│ │ └── ipset_others.go
│ ├── next/
│ │ ├── AdGuardHome.example.yaml
│ │ ├── agh/
│ │ │ └── agh.go
│ │ ├── changelog.md
│ │ ├── cmd/
│ │ │ ├── cmd.go
│ │ │ ├── log.go
│ │ │ ├── opt.go
│ │ │ └── service.go
│ │ ├── configmgr/
│ │ │ ├── config.go
│ │ │ └── configmgr.go
│ │ ├── dnssvc/
│ │ │ ├── config.go
│ │ │ ├── dnssvc.go
│ │ │ └── dnssvc_test.go
│ │ ├── jsonpatch/
│ │ │ ├── jsonpatch.go
│ │ │ └── jsonpatch_test.go
│ │ └── websvc/
│ │ ├── config.go
│ │ ├── dns.go
│ │ ├── dns_test.go
│ │ ├── http.go
│ │ ├── http_test.go
│ │ ├── middleware.go
│ │ ├── route.go
│ │ ├── server.go
│ │ ├── settings.go
│ │ ├── settings_test.go
│ │ ├── system.go
│ │ ├── system_test.go
│ │ ├── websvc.go
│ │ └── websvc_test.go
│ ├── ossvc/
│ │ ├── action.go
│ │ ├── config.go
│ │ ├── config_darwin.go
│ │ ├── config_freebsd.go
│ │ ├── config_linux.go
│ │ ├── config_openbsd.go
│ │ ├── config_windows.go
│ │ ├── defaultaction.go
│ │ ├── defaultmanager.go
│ │ ├── manager.go
│ │ ├── manager_unix.go
│ │ ├── manager_windows.go
│ │ ├── ossvc.go
│ │ ├── reloadmanager.go
│ │ ├── service_linux.go
│ │ ├── service_openbsd.go
│ │ └── service_others.go
│ ├── permcheck/
│ │ ├── check_unix.go
│ │ ├── check_windows.go
│ │ ├── migrate_unix.go
│ │ ├── migrate_windows.go
│ │ ├── permcheck.go
│ │ ├── security_unix.go
│ │ └── security_windows.go
│ ├── querylog/
│ │ ├── client.go
│ │ ├── decode.go
│ │ ├── decode_internal_test.go
│ │ ├── entry.go
│ │ ├── http.go
│ │ ├── json.go
│ │ ├── qlog.go
│ │ ├── qlog_internal_test.go
│ │ ├── qlogfile.go
│ │ ├── qlogfile_internal_test.go
│ │ ├── qlogreader.go
│ │ ├── qlogreader_internal_test.go
│ │ ├── querylog.go
│ │ ├── querylogfile.go
│ │ ├── search.go
│ │ ├── search_internal_test.go
│ │ ├── searchcriterion.go
│ │ └── searchparams.go
│ ├── rdns/
│ │ ├── rdns.go
│ │ └── rdns_test.go
│ ├── schedule/
│ │ ├── schedule.go
│ │ └── schedule_internal_test.go
│ ├── stats/
│ │ ├── http.go
│ │ ├── http_internal_test.go
│ │ ├── stats.go
│ │ ├── stats_internal_test.go
│ │ ├── stats_test.go
│ │ ├── unit.go
│ │ └── unit_internal_test.go
│ ├── updater/
│ │ ├── check.go
│ │ ├── check_test.go
│ │ ├── updater.go
│ │ ├── updater_internal_test.go
│ │ └── updater_test.go
│ ├── version/
│ │ ├── norace.go
│ │ ├── race.go
│ │ └── version.go
│ └── whois/
│ ├── whois.go
│ └── whois_test.go
├── main.go
├── main_next.go
├── openapi/
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.html
│ ├── next.yaml
│ └── openapi.yaml
├── scripts/
│ ├── README.md
│ ├── blocked-services/
│ │ └── main.go
│ ├── companiesdb/
│ │ └── download.sh
│ ├── hooks/
│ │ ├── helper.sh
│ │ ├── pre-commit
│ │ └── pre-merge-commit
│ ├── install.sh
│ ├── make/
│ │ ├── build-docker.sh
│ │ ├── build-release.sh
│ │ ├── go-bench.sh
│ │ ├── go-build.sh
│ │ ├── go-deps.sh
│ │ ├── go-fuzz.sh
│ │ ├── go-lint.sh
│ │ ├── go-test.sh
│ │ ├── go-upd-tools.sh
│ │ ├── helper.sh
│ │ ├── md-lint.sh
│ │ ├── sh-lint.sh
│ │ ├── txt-lint.sh
│ │ └── version.sh
│ ├── snap/
│ │ ├── build.sh
│ │ ├── download.sh
│ │ └── upload.sh
│ ├── translations/
│ │ ├── download.go
│ │ ├── main.go
│ │ ├── twosky.go
│ │ └── upload.go
│ └── vetted-filters/
│ └── main.go
├── snap/
│ ├── gui/
│ │ └── adguard-home-web.desktop
│ ├── local/
│ │ └── adguard-home-web.sh
│ └── snap.tmpl.yaml
└── staticcheck.conf
================================================
FILE CONTENTS
================================================
================================================
FILE: .codecov.yml
================================================
'coverage':
'status':
'project':
'default':
'target': '40%'
'threshold': null
'patch': false
'changes': false
================================================
FILE: .gitattributes
================================================
client/* linguist-vendored
# This file contains a lot of inline SVG data, which often interferes with
# grepping. Technically, this file must be reviewed when new icons appear, but
# that happens fairly rarely.
client/src/components/ui/Icons.js -diff
================================================
FILE: .github/ISSUE_TEMPLATE/bug.yml
================================================
'body':
- 'attributes':
'description': >
Please make sure that the issue is not a duplicate or a question.
If it's a duplicate, please react to the original issue with a
thumbs up. If it's a question, please post it to the GitHub
Discussions page.
'label': 'Prerequisites'
'options':
- 'label': >
I have checked the
[Wiki](https://github.com/AdguardTeam/AdGuardHome/wiki) and
[Discussions](https://github.com/AdguardTeam/AdGuardHome/discussions/categories/q-a)
and found no answer
'required': true
- 'label': >
I have searched other issues and found no duplicates
'required': true
- 'label': >
I want to report a bug and not [ask a question or ask for
help](https://github.com/AdguardTeam/AdGuardHome/discussions/categories/q-a)
'required': true
- 'label': >
I have set up AdGuard Home correctly and [configured clients to
use it](https://github.com/AdguardTeam/AdGuardHome/wiki/Clients).
(Use the
[Discussions](https://github.com/AdguardTeam/AdGuardHome/discussions/categories/q-a)
for help with installing and configuring clients.)
'required': true
'id': 'prerequisites'
'type': 'checkboxes'
- 'attributes':
'description': 'On which Platform does the issue occur?'
'label': 'Platform (OS and CPU architecture)'
# NOTE: Keep the 386 at the bottom for each OS, because a lot of people
# Seem to confuse them with AMD64, which is what they actually need.
'options':
- 'Darwin (aka macOS), AMD64 (aka x86_64)'
- 'Darwin (aka macOS), ARM64'
- 'FreeBSD, AMD64 (aka x86_64)'
- 'FreeBSD, ARM64'
- 'FreeBSD, ARMv5'
- 'FreeBSD, ARMv6'
- 'FreeBSD, ARMv7'
- 'FreeBSD, 32-bit Intel (aka 386)'
- 'Linux, AMD64 (aka x86_64)'
- 'Linux, ARM64'
- 'Linux, ARMv5'
- 'Linux, ARMv6'
- 'Linux, ARMv7'
- 'Linux, MIPS LE'
- 'Linux, MIPS'
- 'Linux, MIPS64 LE'
- 'Linux, MIPS64'
- 'Linux, PPC64 LE'
- 'Linux, 32-bit Intel (aka 386)'
- 'OpenBSD, AMD64 (aka x86_64)'
- 'OpenBSD, ARM64'
- 'Windows, AMD64 (aka x86_64)'
- 'Windows, ARM64'
- 'Windows, 32-bit Intel (aka 386)'
- 'Custom (please mention in the description)'
'id': 'os'
'type': 'dropdown'
'validations':
'required': true
- 'attributes':
'description': 'How did you install AdGuard Home?'
'label': 'Installation'
'options':
- 'GitHub releases or script from README'
- 'Docker'
- 'Snapcraft'
- 'Custom package (OpenWrt, HomeAssistant, etc; please mention in the description)'
- 'Other (please mention in the description)'
'id': 'install'
'type': 'dropdown'
'validations':
'required': true
- 'attributes':
'description': 'How did you setup AdGuard Home?'
'label': 'Setup'
'options':
- 'On one machine'
- 'On a router, DHCP is handled by the router'
- 'On a router, DHCP is handled by AdGuard Home'
- 'Other (please mention in the description)'
'id': 'setup'
'type': 'dropdown'
'validations':
'required': true
- 'attributes':
'description': 'What version of AdGuard Home are you using?'
'label': 'AdGuard Home version'
'id': 'version'
'type': 'input'
'validations':
'required': true
- 'attributes':
'description': >
Please describe what you did. An `nslookup` or a `dig` command is
the best way. For crashes, please provide a full failure log.
'label': 'Action'
'value': |
Replace the following command with the one you're calling or a
description of the failing action:
```sh
nslookup -debug -type=a 'www.example.com' '$YOUR_AGH_ADDRESS'
```
'id': 'failing_action'
'type': 'textarea'
'validations':
'required': true
- 'attributes':
'description': >
What did you expect to see? Please add a description and/or
screenshots, if applicable.
'label': 'Expected result'
'placeholder': >
What did you expect to see?
'id': 'expected'
'type': 'textarea'
'validations':
'required': true
- 'attributes':
'description': >
What happened instead? Please add a description and/or screenshots,
if applicable.
'label': 'Actual result'
'placeholder': >
What did you see instead?
'id': 'result'
'type': 'textarea'
'validations':
'required': true
- 'attributes':
'description': >
Please add additional information, such as non-standard OS or port,
here. You can also put screenshots here, if applicable. For
example, it is better to copy and paste text from a terminal instead
of posting a screenshot of the terminal.
'label': 'Additional information and/or screenshots'
'placeholder': >
Additional OS information, screenshots of the UI, etc.
'id': 'additional'
'type': 'textarea'
'validations':
'required': false
# NOTE: GitHub limits the description length to 200 characters. Also, Markdown
# doesn't work here.
'description': |
For help, use the Discussions section instead. Write the title in English
to make it easier for other people to search for duplicates. (Any language
is fine in the body.)
'name': 'Bug'
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
'blank_issues_enabled': false
'contact_links':
- 'about': >
Please report filtering issues, for example advertising filters
misfiring or safe browsing false positives, using the form on our
website
'name': 'AdGuard filters issues'
'url': 'https://link.adtidy.org/forward.html?action=report&app=home&from=github'
- 'about': >
Please send requests for new blocked services and vetted filtering lists
to the Hostlists Registry repository
'name': 'Blocked services and vetted filtering rule lists: AdGuard Hostlists Registry'
'url': 'https://github.com/AdguardTeam/HostlistsRegistry'
- 'about': >
Please use GitHub Discussions for questions
'name': 'Q&A Discussions'
'url': 'https://github.com/AdguardTeam/AdGuardHome/discussions'
- 'about': >
Please check our Wiki for configuration file description, frequently
asked questions, and other documentation
'name': 'Wiki'
'url': 'https://github.com/AdguardTeam/AdGuardHome/wiki'
================================================
FILE: .github/ISSUE_TEMPLATE/feature.yml
================================================
'body':
- 'attributes':
'description': >
Please make sure that the issue is not a duplicate or a question.
If it's a duplicate, please react to the original issue with a
thumbs up. If it's a question, please post it to the GitHub
Discussions page.
'label': 'Prerequisites'
'options':
- 'label': >
I have checked the
[Wiki](https://github.com/AdguardTeam/AdGuardHome/wiki) and
[Discussions](https://github.com/AdguardTeam/AdGuardHome/discussions)
and found no answer
'required': true
- 'label': >
I have searched other issues and found no duplicates
'required': true
- 'label': >
I want to request a feature or enhancement and not ask a
question
'required': true
'id': 'prerequisites'
'type': 'checkboxes'
- 'attributes':
'description': 'Please describe the problem you are trying to solve'
'label': 'The problem'
'placeholder': >
Please describe the problem you are trying to solve
'id': 'problem'
'type': 'textarea'
'validations':
'required': true
- 'attributes':
'description': 'What feature are you proposing to solve this problem?'
'label': 'Proposed solution'
'placeholder': >
What feature are you proposing to solve this problem?
'id': 'proposed_solution'
'type': 'textarea'
'validations':
'required': true
- 'attributes':
'label': 'Alternatives considered and additional information'
'placeholder': >
Are there any other ways to solve the problem?
'id': 'additional'
'type': 'textarea'
'validations':
'required': false
# NOTE: GitHub limits the description length to 200 characters. Also, Markdown
# doesn't work here.
'description': |
Write the title in English to make it easier for other people to search for
duplicates. (Any language is fine in the body.)
'labels':
- 'feature request'
'name': 'Feature request or enhancement'
================================================
FILE: .github/PULL_REQUEST_TEMPLATE
================================================
Before submitting a PR please make sure that:
1. You have discussed your solution in an issue and have got an
approval from a maintainer. See our
[contribution guide](https://github.com/AdguardTeam/AdGuardHome/blob/master/CONTRIBUTING.md).
2. This isn't a localization fix; please send those to our
[CrowdIn](https://crowdin.com/project/adguard-applications/en#/adguard-home)
page.
3. Your code follows our
[code guidelines](https://github.com/AdguardTeam/CodeGuidelines/blob/master/Go/Go.md).
Add a short description here. The description should include:
1. Which issue this PR closes (`Closes #NNNN.`) or updates (`Updates
#NNNN.`). Please do not open PRs without filing an issue first.
2. A short description of how the change achieves that.
Do not forget to remove these instructions!
================================================
FILE: .github/stale.yml
================================================
# Number of days of inactivity before an issue becomes stale.
'daysUntilStale': 90
# Number of days of inactivity before a stale issue is closed.
'daysUntilClose': 15
# Issues with these labels will never be considered stale.
'exemptLabels':
- 'bug'
- 'documentation'
- 'enhancement'
- 'feature request'
- 'help wanted'
- 'localization'
- 'needs investigation'
- 'recurrent'
- 'research'
# Set to true to ignore issues in a milestone.
'exemptMilestones': true
# Label to use when marking an issue as stale.
'staleLabel': 'wontfix'
# Comment to post when marking an issue as stale. Set to `false` to disable.
'markComment': >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable.
'closeComment': false
# Limit the number of actions per hour.
'limitPerRun': 1
================================================
FILE: .github/workflows/build.yml
================================================
'name': 'build'
'env':
'GO_VERSION': '1.26.1'
'NODE_VERSION': '20'
'on':
'push':
'branches':
- '*'
'tags':
- 'v*'
'pull_request':
'jobs':
'test':
'runs-on': '${{ matrix.os }}'
'env':
'GO111MODULE': 'on'
'GOPROXY': 'https://goproxy.cn'
'strategy':
'fail-fast': false
'matrix':
'os':
- 'ubuntu-latest'
- 'macOS-latest'
- 'windows-latest'
'steps':
- 'name': 'Checkout'
'uses': 'actions/checkout@v2'
'with':
'fetch-depth': 0
- 'name': 'Set up Go'
'uses': 'actions/setup-go@v3'
'with':
'go-version': '${{ env.GO_VERSION }}'
- 'name': 'Set up Node'
'uses': 'actions/setup-node@v1'
'with':
'node-version': '${{ env.NODE_VERSION }}'
- 'name': 'Set up Go modules cache'
'uses': 'actions/cache@v4'
'with':
'path': '~/go/pkg/mod'
'key': "${{ runner.os }}-go-${{ hashFiles('go.sum') }}"
'restore-keys': '${{ runner.os }}-go-'
- 'name': 'Get npm cache directory'
'id': 'npm-cache'
'run': 'echo "::set-output name=dir::$( npm config get cache )"'
- 'name': 'Set up npm cache'
'uses': 'actions/cache@v4'
'with':
'path': '${{ steps.npm-cache.outputs.dir }}'
'key': "${{ runner.os }}-node-${{ hashFiles('client/package-lock.json') }}"
'restore-keys': '${{ runner.os }}-node-'
- 'name': 'Run tests'
'shell': 'bash'
'run': 'make VERBOSE=1 deps test go-bench go-fuzz'
- 'name': 'Upload coverage'
'uses': 'codecov/codecov-action@v1'
'if': "success() && matrix.os == 'ubuntu-latest'"
'with':
'token': '${{ secrets.CODECOV_TOKEN }}'
'file': './coverage.txt'
'build-release':
'runs-on': 'ubuntu-latest'
'needs': 'test'
'steps':
- 'name': 'Checkout'
'uses': 'actions/checkout@v2'
'with':
'fetch-depth': 0
- 'name': 'Set up Go'
'uses': 'actions/setup-go@v3'
'with':
'go-version': '${{ env.GO_VERSION }}'
- 'name': 'Set up Node'
'uses': 'actions/setup-node@v1'
'with':
'node-version': '${{ env.NODE_VERSION }}'
- 'name': 'Set up Go modules cache'
'uses': 'actions/cache@v4'
'with':
'path': '~/go/pkg/mod'
'key': "${{ runner.os }}-go-${{ hashFiles('go.sum') }}"
'restore-keys': '${{ runner.os }}-go-'
- 'name': 'Get npm cache directory'
'id': 'npm-cache'
'run': 'echo "::set-output name=dir::$(npm config get cache)"'
- 'name': 'Set up npm cache'
'uses': 'actions/cache@v4'
'with':
'path': '${{ steps.npm-cache.outputs.dir }}'
'key': "${{ runner.os }}-node-${{ hashFiles('client/package-lock.json') }}"
'restore-keys': '${{ runner.os }}-node-'
- 'name': 'Set up Snapcraft'
'run': 'sudo snap install snapcraft --classic'
- 'name': 'Set up QEMU'
'uses': 'docker/setup-qemu-action@v3'
- 'name': 'Set up Docker Buildx'
'uses': 'docker/setup-buildx-action@v3'
'with':
'install': true
- 'name': 'Run snapshot build'
# Set a custom version string, since the checkout@v2 action does not seem
# to know about the master branch, while the version script uses it to
# count the number of commits within the branch.
'run': 'make SIGN=0 VERBOSE=1 VERSION="v0.0.0-github" build-release build-docker'
'notify':
'needs':
- 'build-release'
# Secrets are not passed to workflows that are triggered by a pull request
# from a fork.
#
# Use always() to signal to the runner that this job must run even if the
# previous ones failed.
'if':
${{
always() &&
github.repository_owner == 'AdguardTeam' &&
(
github.event_name == 'push' ||
github.event.pull_request.head.repo.full_name == github.repository
)
}}
'runs-on': 'ubuntu-latest'
'steps':
- 'name': 'Conclusion'
'uses': 'technote-space/workflow-conclusion-action@v1'
- 'name': 'Send Slack notif'
'uses': '8398a7/action-slack@v3'
'with':
'status': '${{ env.WORKFLOW_CONCLUSION }}'
'fields': 'repo, message, commit, author, workflow'
'env':
'GITHUB_TOKEN': '${{ secrets.GITHUB_TOKEN }}'
'SLACK_WEBHOOK_URL': '${{ secrets.SLACK_WEBHOOK_URL }}'
================================================
FILE: .github/workflows/lint.yml
================================================
'name': 'lint'
'env':
'GO_VERSION': '1.26.1'
'on':
'push':
'tags':
- 'v*'
'branches':
- '*'
'pull_request':
'jobs':
'go-lint':
'runs-on': 'ubuntu-latest'
'steps':
- 'uses': 'actions/checkout@v2'
- 'name': 'Set up Go'
'uses': 'actions/setup-go@v3'
'with':
'go-version': '${{ env.GO_VERSION }}'
- 'name': 'run-lint'
'run': >
make go-deps go-lint
'eslint':
'runs-on': 'ubuntu-latest'
'steps':
- 'uses': 'actions/checkout@v2'
- 'name': 'Install modules'
'run': 'npm --prefix="./client" ci'
- 'name': 'Run ESLint'
'run': 'npm --prefix="./client" run lint'
'notify':
'needs':
- 'go-lint'
- 'eslint'
# Secrets are not passed to workflows that are triggered by a pull request
# from a fork.
#
# Use always() to signal to the runner that this job must run even if the
# previous ones failed.
'if':
${{
always() &&
github.repository_owner == 'AdguardTeam' &&
(
github.event_name == 'push' ||
github.event.pull_request.head.repo.full_name == github.repository
)
}}
'runs-on': 'ubuntu-latest'
'steps':
- 'name': 'Conclusion'
'uses': 'technote-space/workflow-conclusion-action@v1'
- 'name': 'Send Slack notif'
'uses': '8398a7/action-slack@v3'
'with':
'status': '${{ env.WORKFLOW_CONCLUSION }}'
'fields': 'repo, message, commit, author, workflow'
'env':
'GITHUB_TOKEN': '${{ secrets.GITHUB_TOKEN }}'
'SLACK_WEBHOOK_URL': '${{ secrets.SLACK_WEBHOOK_URL }}'
================================================
FILE: .github/workflows/potential-duplicates.yml
================================================
'name': 'potential-duplicates'
'on':
'issues':
'types':
- 'opened'
'jobs':
'run':
'runs-on': 'ubuntu-latest'
'steps':
- 'uses': 'wow-actions/potential-duplicates@v1'
'with':
'GITHUB_TOKEN': '${{ secrets.GITHUB_TOKEN }}'
'state': 'all'
'threshold': 0.6
'comment': |
Potential duplicates: {{#issues}}
* [#{{ number }}] {{ title }} ({{ accuracy }}%)
{{/issues}}
================================================
FILE: .gitignore
================================================
# This comment is used to simplify checking local copies of the file. Bump
# this number every time a significant change is made to this file.
#
# AdGuard-Project-Version: 1
# Please, DO NOT put your text editors' temporary files here. The more are
# added, the harder it gets to maintain and manage projects' gitignores. Put
# them into your global gitignore file instead.
#
# See https://stackoverflow.com/a/7335487/1892060.
#
# Only build, run, and test outputs here. Sorted. With negations at the
# bottom to make sure they take effect.
*.db
*.log
*.out
*.snap
*.test
/agh-backup/
/bin/
/build/*
/client/blob-report/
/client/playwright-report/
/client/playwright/.cache/
/client/test-results/
/data/
/dist/
/filtering/tests/filtering.TestLotsOfRules*.pprof
/filtering/tests/top-1m.csv
/internal/next/AdGuardHome.yaml
/launchpad_credentials
/querylog.json*
/snapcraft_login
/test-reports/
AdGuardHome
AdGuardHome.exe
AdGuardHome.yaml*
coverage.txt
node_modules/
tmp/
!/build/gitkeep
================================================
FILE: .markdownlint.json
================================================
{
"ul-indent": {
"indent": 4
},
"ul-style": {
"style": "dash"
},
"emphasis-style": {
"style": "asterisk"
},
"no-duplicate-heading": {
"siblings_only": true
},
"no-inline-html": {
"allowed_elements": [
"a"
]
},
"no-trailing-spaces": {
"br_spaces": 0
},
"line-length": false,
"no-bare-urls": false,
"no-emphasis-as-heading": false,
"link-fragments": false
}
================================================
FILE: .twosky.json
================================================
[
{
"project_id": "home",
"base_locale": "en",
"localizable_files": [
"client/src/__locales/en.json"
],
"languages": {
"ar": "العربية",
"be": "Беларуская",
"bg": "Български",
"cs": "Český",
"da": "Dansk",
"de": "Deutsch",
"en": "English",
"es": "Español",
"fa": "فارسی",
"fi": "Suomi",
"fr": "Français",
"hr": "Hrvatski",
"hu": "Magyar",
"id": "Indonesian",
"it": "Italiano",
"ja": "日本語",
"ko": "한국어",
"nl": "Nederlands",
"no": "Norsk",
"pl": "Polski",
"pt-br": "Português (BR)",
"pt-pt": "Português (PT)",
"ro": "Română",
"ru": "Русский",
"si-lk": "සිංහල",
"sk": "Slovenčina",
"sl": "Slovenščina",
"sr-cs": "Srpski",
"sv": "Svenska",
"th": "ภาษาไทย",
"tr": "Türkçe",
"uk": "Українська",
"vi": "Tiếng Việt",
"zh-cn": "简体中文",
"zh-hk": "繁體中文(香港)",
"zh-tw": "正體中文(台灣)"
}
},
{
"project_id": "hostlists-registry",
"base_locale": "en",
"localizable_files": [
"client/src/__locales-services/services.json"
],
"languages": {
"ar": "العربية",
"be": "Беларуская",
"bg": "Български",
"cs": "Český",
"da": "Dansk",
"de": "Deutsch",
"en": "English",
"es": "Español",
"fa": "فارسی",
"fi": "Suomi",
"fr": "Français",
"hr": "Hrvatski",
"hu": "Magyar",
"id": "Indonesian",
"it": "Italiano",
"ja": "日本語",
"ko": "한국어",
"nl": "Nederlands",
"no": "Norsk",
"pl": "Polski",
"pt-br": "Português (BR)",
"pt-pt": "Português (PT)",
"ro": "Română",
"ru": "Русский",
"si-lk": "සිංහල",
"sk": "Slovenčina",
"sl": "Slovenščina",
"sr-cs": "Srpski",
"sv": "Svenska",
"th": "ภาษาไทย",
"tr": "Türkçe",
"uk": "Українська",
"vi": "Tiếng Việt",
"zh-cn": "简体中文",
"zh-hk": "繁體中文(香港)",
"zh-tw": "正體中文(台灣)"
}
}
]
================================================
FILE: AGHTechDoc.md
================================================
# AdGuard Home Technical Document
The document describes technical details and internal algorithms of AdGuard Home.
Contents:
* First startup
* Installation wizard
* "Get install settings" command
* "Check configuration" command
* Disable DNSStubListener
* "Apply configuration" command
* Updating
* Get version command
* Update command
* API: Get global status
* TLS
* API: Get TLS configuration
* API: Set TLS configuration
* Device Names and Per-client Settings
* Per-client settings
* Get list of clients
* Add client
* Update client
* Delete client
* API: Find clients by IP
* DHCP server
* DHCP server in DNS
* DHCP Custom Options
* API: Show DHCP interfaces
* API: Show DHCP status
* API: Check DHCP
* API: Enable DHCP
* Static IP check/set
* API: Add a static lease
* API: Reset DHCP configuration
* RA+SLAAC
* DNS general settings
* API: Get DNS general settings
* API: Set DNS general settings
* DNS access settings
* List access settings
* Set access settings
* Rewrites
* API: List rewrite entries
* API: Add a rewrite entry
* API: Remove a rewrite entry
* Services Filter
* API: Get blocked services list
* API: Set blocked services list
* Statistics
* API: Get statistics data
* API: Clear statistics data
* API: Set statistics parameters
* API: Get statistics parameters
* Query logs
* API: Get query log
* API: Set querylog parameters
* API: Get querylog parameters
* Filtering
* Filters update mechanism
* API: Get filtering parameters
* API: Set filtering parameters
* API: Refresh filters
* API: Add Filter
* API: Set URL parameters
* API: Delete URL
* API: Domain Check
* Log-in page
* API: Log in
* API: Log out
* API: Get current user info
* Safe services
* ipset
## Relations between subsystems

## First startup
The first application startup is detected when there's no .yaml configuration file.
We check if the user is root, otherwise we fail with an error.
Web server is started up on port 3000 and automatically redirects requests to `/` to Installation wizard.
After Installation wizard steps are completed, we write configuration to a file and start normal operation.
## Installation wizard
This is the collection of UI screens that are shown to a user on first application startup.
The screens are:
1. Welcome
2. Set up network interface and listening ports for Web and DNS servers
3. Set up administrator username and password
4. Configuration complete
5. Done
Algorithm:
Screen 2:
* UI asks server for initial information and shows it
* User edits the default settings, clicks on "Next" button
* UI asks server to check new settings
* Server searches for the known issues
* UI shows information about the known issues and the means to fix them
* Server applies automatic fixes of the known issues on command from UI
Screen 3:
* UI asks server to apply the configuration
* Server restarts DNS server
### "Get install settings" command
Request:
GET /control/install/get_addresses
Response:
200 OK
{
"web_port":80,
"dns_port":53,
"interfaces":{
"enp2s0":{"name":"enp2s0","mtu":1500,"hardware_address":"","ip_addresses":["",""],"flags":"up|broadcast|multicast"},
"lo":{"name":"lo","mtu":65536,"hardware_address":"","ip_addresses":["127.0.0.1","::1"],"flags":"up|loopback"},
}
}
If `interfaces.flags` doesn't contain `up` flag, UI must show `(Down)` status next to its IP address in interfaces selector.
### "Check configuration" command
Request:
POST /control/install/check_config
{
"web":{"port":80,"ip":"192.168.11.33"},
"dns":{"port":53,"ip":"127.0.0.1","autofix":false},
"set_static_ip": true | false
}
Server should check whether a port is available only in case it itself isn't already listening on that port.
If `set_static_ip` is `true`, Server attempts to set a static IP for the network interface chosen by `dns.ip` setting. If the operation is successful, `static_ip.static` setting will be `yes`. If it fails, `static_ip.static` setting will be set to `error` and `static_ip.error` will contain the error message.
Server replies on success:
200 OK
{
"web":{"status":""},
"dns":{"status":""},
"static_ip": {
"static": "yes|no|error",
"ip": "<Current dynamic IP address>", // set if static=no
"error": "..." // set if static=error
}
}
If `static_ip.static` is `no`, Server has detected that the system uses a dynamic address and it can automatically set a static address if `set_static_ip` in request is `true`. See section `Static IP check/set` for detailed process.
Server replies on error:
200 OK
{
"web":{"status":"ERROR MESSAGE"},
"dns":{"status":"ERROR MESSAGE", "can_autofix": true|false},
}
### Disable DNSStubListener
On Linux, if 53 port is not available, server performs several additional checks to determine if the issue can be fixed automatically.
#### Phase 1
Request:
POST /control/install/check_config
{
"dns":{
"port":53,
"ip":"127.0.0.1",
"autofix":false
}
}
Check if DNSStubListener is enabled:
systemctl is-enabled systemd-resolved
Check if DNSStubListener is active:
grep -E '#?DNSStubListener=yes' /etc/systemd/resolved.conf
If the issue can be fixed automatically, server replies with `"can_autofix":true`
200 OK
{
"dns":{"status":"ERROR MESSAGE", "can_autofix":true},
}
In this case UI shows "Fix" button next to error message.
#### Phase 2
If user clicks on "Fix" button, UI sends request to perform an automatic fix
POST /control/install/check_config
{
"dns":{"port":53,"ip":"127.0.0.1","autofix":true},
}
Deactivate DNSStubListener and update DNS server address. Create a new file: `/etc/systemd/resolved.conf.d/adguardhome.conf` (create a `/etc/systemd/resolved.conf.d` directory if necessary):
[Resolve]
DNS=127.0.0.1
DNSStubListener=no
Specifying "127.0.0.1" as DNS server address is necessary because otherwise the nameserver will be "127.0.0.53" which doesn't work without DNSStubListener.
Activate another resolv.conf file:
mv /etc/resolv.conf /etc/resolv.conf.backup
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
Stop DNSStubListener:
systemctl reload-or-restart systemd-resolved
Server replies:
200 OK
{
"dns":{"status":""},
}
### "Apply configuration" command
Request:
POST /control/install/configure
{
"web":{"port":80,"ip":"192.168.11.33"},
"dns":{"port":53,"ip":"127.0.0.1"},
"username":"u",
"password":"p",
}
Server checks the parameters once again, restarts DNS server, replies:
200 OK
On error, server responds with code 400 or 500. In this case UI should show error message and reset to the beginning.
400 Bad Request
ERROR MESSAGE
## Updating
Algorithm of an update by command:
* UI requests the latest version information from Server
* Server requests information from Internet; stores the data in cache for several hours; sends data to UI
* If UI sees that a new version is available, it shows notification message and "Update Now" button
* When user clicks on "Update Now" button, UI sends Update command to Server
* UI shows "Please wait, AGH is being updated..." message
* Server performs an update:
* Use working directory from `--work-dir` if necessary
* Download new package for the current OS and CPU
* Unpack the package to a temporary directory `update-vXXX`
* Copy the current configuration file to the directory we unpacked new AGH to
* Check configuration compatibility by executing `./AGH --check-config`. If this command fails, we won't be able to update.
* Create `backup-vXXX` directory and copy the current configuration file there
* Copy supporting files (README, LICENSE, etc.) to backup directory
* Copy supporting files from the update directory to the current directory
* Move the current binary file to backup directory
* Note: if power fails here, AGH won't be able to start at system boot. Administrator has to fix it manually
* Move new binary file to the current directory
* Send response to UI
* Stop all tasks, including DNS server, DHCP server, HTTP server
* If AGH is running as a service, use service control functionality to restart
* If AGH is not running as a service, use the current process arguments to start a new process
* Exit process
* UI resends Get Status command until Server responds to it with the new version. This means that Server is successfully restarted after update.
* UI reloads itself
### Get version command
On receiving this request server downloads version.json data from github and stores it in cache for several hours.
Example of version.json data:
{
"version": "v0.95-hotfix",
"announcement": "AdGuard Home v0.95-hotfix is now available!",
"announcement_url": "",
"download_windows_amd64": "",
"download_windows_386": "",
"download_darwin_amd64": "",
"download_linux_amd64": "",
"download_linux_386": "",
"download_linux_arm": "",
"download_linux_arm64": "",
"download_linux_mips": "",
"download_linux_mipsle": "",
"selfupdate_min_version": "v0.0"
}
Server can only auto-update if the current version is equal or higher than `selfupdate_min_version`.
Request:
POST /control/version.json
{
"recheck_now": true | false // if false, server will check for a new version data only once in several hours
}
Response:
200 OK
{
"new_version": "v0.95",
"announcement": "AdGuard Home v0.95 is now available!",
"announcement_url": "http://...",
"can_autoupdate": true
}
If `can_autoupdate` is true, then the server can automatically upgrade to a new version.
Response when auto-update is disabled by command-line argument:
200 OK
{
"disabled":true
}
It means that update check is disabled by user. UI should do nothing.
### Update command
Perform an update procedure to the latest available version
Request:
POST /control/update
Response:
200 OK
Error response:
500
UI shows error message "Auto-update has failed"
## API: Get global status
Request:
GET /control/status
Response:
200 OK
{
"dns_addresses":["..."],
"dns_port":53,
"http_port":3000,
"language":"en",
"protection_enabled":true,
"running":true,
"dhcp_available":true,
"protection_disabled_duration":0
"version":"undefined"
}
## DHCP server
Enable DHCP server algorithm:
* UI shows DHCP configuration screen with "Enabled DHCP" button disabled, and "Check DHCP" button enabled
* User clicks on "Check DHCP"; UI sends request to server
* Server may fail to detect whether there is another DHCP server working in the network. In this case UI shows a warning.
* Server may detect that a dynamic IP configuration is used for this interface. In this case UI shows a warning.
* UI enables "Enable DHCP" button
* User clicks on "Enable DHCP"; UI sends request to server
* Server sets a static IP (if necessary), enables DHCP server, sends the status back to UI
* UI shows the status
### DHCP server in DNS
DHCP leases are used in several ways by DNS module.
* For "A" DNS request we reply with an IP address leased by our DHCP server.
< A bills-notebook.lan.
> A bills-notebook.lan. = 192.168.1.100
* For "PTR" DNS request we reply with a hostname from an active DHCP lease.
< PTR 100.1.168.192.in-addr.arpa.
> PTR 100.1.168.192.in-addr.arpa. = bills-notebook.
### DHCP Custom Options
Option with arbitrary hexadecimal data:
DEC_CODE hex HEX_DATA
where DEC_CODE is a decimal DHCPv4 option code in range [1..255]
Option with IP data (only 1 IP is supported):
DEC_CODE ip IP_ADDR
### API: Show DHCP interfaces
Request:
GET /control/dhcp/interfaces
Response:
200 OK
{
"iface_name":{
"name":"iface_name",
"hardware_address":"...",
"ipv4_addresses":["ipv4 addr", ...],
"ipv6_addresses":["ipv6 addr", ...],
"gateway_ip":"...",
"flags":"up|broadcast|multicast"
}
...
}
### API: Show DHCP status
Request:
GET /control/dhcp/status
Response:
200 OK
{
"enabled":false,
"interface_name":"...",
"v4":{
"gateway_ip":"...",
"subnet_mask":"...",
"range_start":"...", // if empty: DHCPv4 won't be enabled
"range_end":"...",
"lease_duration":60,
},
"v6":{
"range_start":"...", // if empty: DHCPv6 won't be enabled
"lease_duration":60,
}
"leases":[
{"ip":"...","mac":"...","hostname":"...","expires":"..."}
...
],
"static_leases":[
{"ip":"...","mac":"...","hostname":"..."}
...
]
}
### API: Check DHCP
Request:
POST /control/dhcp/find_active_dhcp
vboxnet0
Response:
200 OK
{
v4: {
"other_server": {
"found": "yes|no|error",
"error": "Error message", // set if found=error
},
"static_ip": {
"static": "yes|no|error",
"ip": "<Current dynamic IP address>", // set if static=no
}
}
v6: {
"other_server": {
"found": "yes|no|error",
"error": "Error message", // set if found=error
},
}
}
If `other_server.found` is:
* `no`: everything is fine - there is no other DHCP server
* `yes`: we found another DHCP server. UI shows a warning.
* `error`: we failed to determine whether there's another DHCP server. `other_server.error` contains error details. UI shows a warning.
If `static_ip.static` is:
* `yes`: everything is fine - server uses static IP address.
* `no`: `static_ip.ip` contains the current dynamic IP address which we may set as static. In this case UI shows a warning:
Your system uses dynamic IP address configuration for interface <CURRENT INTERFACE NAME>. In order to use DHCP server a static IP address must be set. Your current IP address is <static_ip.ip>. We will automatically set this IP address as static if you press Enable DHCP button.
* `error`: this means that the server failed to check for a static IP. In this case UI shows a warning:
In order to use DHCP server a static IP address must be set. We failed to determine if this network interface is configured using static IP address. Please set a static IP address manually.
### API: Enable DHCP
Request:
POST /control/dhcp/set_config
{
"enabled":true,
"interface_name":"vboxnet0",
"v4":{
"gateway_ip":"192.169.56.1",
"subnet_mask":"255.255.255.0",
"range_start":"192.169.56.100",
"range_end":"192.169.56.200", // Note: first 3 octets must match "range_start"
"lease_duration":60,
},
"v6":{
"range_start":"...",
"lease_duration":60,
}
}
Response:
200 OK
OK
For v4, if range_start = "1.2.3.4", the range_end must be "1.2.3.X" where X > 4.
For v6, if range_start = "2001::1", the last IP is "2001:ff".
### Static IP check/set
Before enabling DHCP server we have to make sure the network interface we use has a static IP configured.
#### Phase 1
On Debian systems DHCP is configured by `/etc/dhcpcd.conf`.
To detect if a static IP is used currently we search for line
interface eth0
and then look for line
static ip_address=...
If the interface already has a static IP, everything is set up, we don't have to change anything.
To get the current IP address along with netmask we execute
ip -oneline -family inet address show eth0
which will print:
2: eth0 inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\ valid_lft forever preferred_lft forever
To get the current gateway address:
ip route show dev enp2s0
which will print:
default via 192.168.0.1 proto dhcp metric 100
#### Phase 2 (Raspbian)
Step 1.
To set a static IP address we add these lines to `dhcpcd.conf`:
interface eth0
static ip_address=192.168.0.1/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
* Don't set 'routers' if we couldn't find gateway IP
* Set 'domain_name_servers' equal to our IP
Step 2.
If we would set a different IP address, we'd need to replace the IP address for the current network configuration. But currently this step isn't necessary.
ip addr replace dev eth0 192.168.0.1/24
#### Phase 2 (Ubuntu)
`/etc/netplan/01-netcfg.yaml` or `/etc/netplan/01-network-manager-all.yaml`
This configuration example has a static IP set for `enp0s3` interface:
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: no
addresses: [192.168.0.2/24]
gateway: 192.168.0.1
nameservers:
addresses: [192.168.0.1,8.8.8.8]
For dynamic configuration `dhcp4: yes` is set.
Make a backup copy to `/etc/netplan/01-netcfg.yaml.backup`.
Apply:
netplan apply
Restart network:
systemctl restart networking
or:
systemctl restart network-manager
or:
systemctl restart system-networkd
### API: Add a static lease
Request:
POST /control/dhcp/add_static_lease
{
"mac":"...",
"ip":"...",
"hostname":"..."
}
Response:
200 OK
### Remove a static lease
Request:
POST /control/dhcp/remove_static_lease
{
"mac":"...",
"ip":"...",
"hostname":"..."
}
Response:
200 OK
### API: Reset DHCP configuration
Clear all DHCP leases and configuration settings.
DHCP server will be stopped if it's currently running.
Request:
POST /control/dhcp/reset
Response:
200 OK
### RA+SLAAC
There are 3 options for a client to get IPv6 address:
1. via DHCPv6.
Client doesn't receive any `ICMPv6.RouterAdvertisement` packets, so it tries to use DHCPv6.
2. via SLAAC.
Client receives a `ICMPv6.RouterAdvertisement` packet with `Managed=false` flag and IPv6 prefix.
Client then assigns to itself an IPv6 address using this prefix and its MAC address.
DHCPv6 server won't be started in this case.
3. via DHCPv6 or SLAAC.
Client receives a `ICMPv6.RouterAdvertisement` packet with `Managed=true` flag and IPv6 prefix.
Client may choose to use SLAAC or DHCPv6 to obtain an IPv6 address.
Configuration:
dhcp:
...
dhcpv6:
...
ra_slaac_only: false
ra_allow_slaac: false
* `ra_slaac_only:false; ra_allow_slaac:false`: use option #1.
Don't send any `ICMPv6.RouterAdvertisement` packets.
* `ra_slaac_only:true; ra_allow_slaac:false`: use option #2.
Periodically send `ICMPv6.RouterAdvertisement(Flags=(Managed=false,Other=false))` packets.
* `ra_slaac_only:false; ra_allow_slaac:true`: use option #3.
Periodically send `ICMPv6.RouterAdvertisement(Flags=(Managed=true,Other=true))` packets.
ICMPv6.RouterAdvertisement packet description:
ICMPv6:
Type=RouterAdvertisement(134)
Flags
Managed=<BOOL>
Other=<BOOL>
Option=Prefix information(3)
<IPv6 address prefix (/64) of the network interface>
Option=MTU(5)
<...>
Option=Source link-layer address(1)
<MAC address>
Option=Recursive DNS Server(25)
<IPv6 address of DNS server>
## TLS
### API: Get TLS configuration
Request:
GET /control/tls/status
Response:
200 OK
{
"enabled":true,
"server_name":"...",
"port_https":443,
"port_dns_over_tls":853,
"port_dns_over_quic":784,
"certificate_chain":"...",
"private_key":"...",
"certificate_path":"...",
"private_key_path":"..."
"subject":"CN=...",
"issuer":"CN=...",
"not_before":"2019-03-19T08:23:45Z",
"not_after":"2029-03-16T08:23:45Z",
"dns_names":null,
"key_type":"RSA",
"valid_cert":true,
"valid_key":true,
"valid_chain":false,
"valid_pair":true,
"warning_validation":"Your certificate does not verify: x509: certificate signed by unknown authority"
}
### API: Set TLS configuration
Request:
POST /control/tls/configure
{
"enabled":true,
"server_name":"hostname",
"force_https":false,
"port_https":443,
"port_dns_over_tls":853,
"port_dns_over_quic":784,
"certificate_chain":"...",
"private_key":"...",
"certificate_path":"...", // if set, certificate_chain must be empty
"private_key_path":"..." // if set, private_key must be empty
}
Response:
200 OK
### API: Validate TLS configuration
Request:
POST /control/tls/validate
{
"enabled":true,
"port_https":443,
"port_dns_over_tls":853,
"port_dns_over_quic":784,
"allow_unencrypted_doh":false,
"certificate_chain":"...",
"private_key":"...",
"certificate_path":"...",
"private_key_path":"...",
"valid_cert":true,
"valid_chain":false,
"not_before":"2019-03-19T08:23:45Z",
"not_after":"2029-03-16T08:23:45Z",
"dns_names":null,
"valid_key":true,
"valid_pair":true
}
Response:
200 OK
## Device Names and Per-client Settings
When a client requests information from DNS server, he's identified by IP address.
Administrator can set a name for a client with a known IP and also override global settings for this client. The name is used to improve readability of DNS logs: client's name is shown in UI next to its IP address. The names are loaded from 3 sources:
* automatically from "/etc/hosts" file. It's a list of `IP<->Name` entries which is loaded once on AGH startup from "/etc/hosts" file.
* automatically using rDNS. It's a list of `IP<->Name` entries which is added in runtime using rDNS mechanism when a client first makes a DNS request.
* manually configured via UI. It's a list of client's names and their settings which is loaded from configuration file and stored on disk.
### Per-client settings
UI provides means to manage the list of known clients (List/Add/Update/Delete) and their settings. These settings are stored in configuration file as an array of objects.
Notes:
* `name`, `ip` and `mac` values are unique.
* If `mac` is set and DHCP server is enabled, IP is taken from DHCP lease table.
* If `use_global_settings` is true, then DNS responses for this client are processed and filtered using global settings.
* If `use_global_settings` is false, then the client-specific settings are used to override (enable or disable) global settings.
* If `use_global_blocked_services` is false, then the client-specific settings are used to override (enable or disable) global Blocked Services settings.
### Get list of clients
Request:
GET /control/clients
Response:
200 OK
{
clients: [
{
name: "client1"
ids: ["...", ...] // IP, CIDR or MAC
tags: ["...", ...]
use_global_settings: true
filtering_enabled: false
parental_enabled: false
safebrowsing_enabled: false
safesearch_enabled: false
use_global_blocked_services: true
blocked_services: [ "name1", ... ]
whois_info: {
key: "value"
...
}
upstreams: ["upstream1", ...]
}
]
auto_clients: [
{
name: "host"
ip: "..."
source: "etc/hosts" || "rDNS"
whois_info: {
key: "value"
...
}
}
]
supported_tags: ["...", ...]
}
Supported keys for `whois_info`: orgname, country, city.
### Add client
Request:
POST /control/clients/add
{
name: "client1"
ids: ["...", ...] // IP, CIDR or MAC
tags: ["...", ...]
use_global_settings: true
filtering_enabled: false
parental_enabled: false
safebrowsing_enabled: false
safesearch_enabled: false
use_global_blocked_services: true
blocked_services: [ "name1", ... ]
upstreams: ["upstream1", ...]
}
Response:
200 OK
Error response (Client already exists):
400
### Update client
Request:
POST /control/clients/update
{
name: "client1"
data: {
name: "client1"
ids: ["...", ...] // IP, CIDR or MAC
tags: ["...", ...]
use_global_settings: true
filtering_enabled: false
parental_enabled: false
safebrowsing_enabled: false
safesearch_enabled: false
use_global_blocked_services: true
blocked_services: [ "name1", ... ]
upstreams: ["upstream1", ...]
}
}
Response:
200 OK
Error response (Client not found):
400
### Delete client
Request:
POST /control/clients/delete
{
name: "client1"
}
Response:
200 OK
Error response (Client not found):
400
### API: Find clients by IP
This method returns the list of clients (manual and auto-clients) matching the IP list.
For auto-clients only `name`, `ids`, `whois_info`, `disallowed`, and `disallowed_rule` fields are set. Other fields are empty.
Request:
GET /control/clients/find?ip0=...&ip1=...&ip2=...
Response:
200 OK
[
{
"1.2.3.4": {
name: "client1"
ids: ["...", ...] // IP, CIDR or MAC
use_global_settings: true
filtering_enabled: false
parental_enabled: false
safebrowsing_enabled: false
safesearch_enabled: false
use_global_blocked_services: true
blocked_services: [ "name1", ... ]
whois_info: {
key: "value"
...
}
"disallowed": false,
"disallowed_rule": "..."
}
}
...
]
* `disallowed` - whether the client's IP is blocked or not.
* `disallowed_rule` - the rule due to which the client is disallowed. If `disallowed` is `true`, and this string is empty - it means that the client IP is disallowed by the "allowed IP list", i.e. it is not included in allowed.
## DNS general settings
### API: Get DNS general settings
Request:
GET /control/dns_info
Response:
200 OK
{
"upstream_dns": ["tls://...", ...],
"upstream_dns_file": "",
"bootstrap_dns": ["1.2.3.4", ...],
"protection_enabled": true | false,
"ratelimit": 1234,
"blocking_mode": "default" | "refused" | "nxdomain" | "null_ip" | "custom_ip",
"blocking_ipv4": "1.2.3.4",
"blocking_ipv6": "1:2:3::4",
"edns_cs_enabled": true | false,
"dnssec_enabled": true | false
"disable_ipv6": true | false,
"upstream_mode": "" | "parallel" | "fastest_addr"
"cache_size": 1234, // in bytes
"cache_ttl_min": 1234, // in seconds
"cache_ttl_max": 1234, // in seconds
}
### API: Set DNS general settings
Request:
POST /control/dns_config
{
"upstream_dns": ["tls://...", ...],
"upstream_dns_file": "",
"bootstrap_dns": ["1.2.3.4", ...],
"protection_enabled": true | false,
"ratelimit": 1234,
"blocking_mode": "default" | "refused" | "nxdomain" | "null_ip" | "custom_ip",
"blocking_ipv4": "1.2.3.4",
"blocking_ipv6": "1:2:3::4",
"edns_cs_enabled": true | false,
"dnssec_enabled": true | false
"disable_ipv6": true | false,
"upstream_mode": "" | "parallel" | "fastest_addr"
"cache_size": 1234, // in bytes
"cache_ttl_min": 1234, // in seconds
"cache_ttl_max": 1234, // in seconds
}
Response:
200 OK
`blocking_mode`:
* default: Respond with NXDOMAIN when blocked by Adblock-style rule; respond with the IP address specified in the rule when blocked by /etc/hosts-style rule
* NXDOMAIN: Respond with NXDOMAIN code
* Null IP: Respond with zero IP address (0.0.0.0 for A; :: for AAAA)
* Custom IP: Respond with a manually set IP address
`blocking_ipv4` and `blocking_ipv6` values are active when `blocking_mode` is set to `custom_ip`.
## DNS access settings
There are low-level settings that can block undesired DNS requests. "Blocking" means not responding to request.
There are 3 types of access settings:
* allowed_clients: Only these clients are allowed to make DNS requests.
* disallowed_clients: These clients are not allowed to make DNS requests.
* blocked_hosts: These hosts are not allowed to be resolved by a DNS request.
### List access settings
Request:
GET /control/access/list
Response:
200 OK
{
allowed_clients: ["127.0.0.1", ...]
disallowed_clients: ["127.0.0.1", ...]
blocked_hosts: ["host.com", ...] // host name or a wildcard
}
### Set access settings
Request:
POST /control/access/set
{
allowed_clients: ["127.0.0.1", ...]
disallowed_clients: ["127.0.0.1", ...]
blocked_hosts: ["host.com", ...]
}
Response:
200 OK
## Rewrites
This section allows the administrator to easily configure custom DNS response for a specific domain name.
A, AAAA and CNAME records are supported.
Syntax:
key -> value
where `key` is a host name or a wild card that matches Question in DNS request
and `value` is either:
* IPv4 address: use this IP in A response
* IPv6 address: use this IP in AAAA response
* canonical name: add CNAME record
* "`key`": CNAME exception - pass request to upstream
* "A": A exception - pass A request to upstream
* "AAAA": AAAA exception - pass AAAA request to upstream
#### Example: A record
host.com -> 1.2.3.4
Response:
A:
A = 1.2.3.4
AAAA:
<empty>
#### Example: AAAA record
host.com -> ::1
Response:
A:
<empty>
AAAA:
AAAA = ::1
#### Example: CNAME record
sub.host.com -> host.com
Response:
A:
CNAME = host.com
A = <IPv4 address of host.com>
AAAA:
CNAME = host.com
AAAA = <IPv6 address of host.com>
#### Example: CNAME+A records
sub.host.com -> host.com
host.com -> 1.2.3.4
Response:
A:
CNAME = host.com
A = 1.2.3.4
AAAA:
CNAME = host.com
#### Example: Wildcard CNAME+A record with CNAME exception
*.host.com -> 1.2.3.4
pass.host.com -> pass.host.com
Response to `my.host.com`:
A:
A = 1.2.3.4
AAAA:
<empty>
Response to `pass.host.com`:
A:
A = <IPv4 address of pass.host.com>
AAAA:
AAAA = <IPv6 address of pass.host.com>
#### Example: A record with AAAA exception
host.com -> 1.2.3.4
host.com -> AAAA
Response:
A:
A = 1.2.3.4
AAAA:
AAAA = <IPv6 address of host.com>
#### Example: pass A only
host.com -> A
Response:
A:
A = <IPv4 address of host.com>
AAAA:
<empty>
### API: List rewrite entries
Request:
GET /control/rewrite/list
Response:
200 OK
[
{
domain: "..."
answer: "..."
}
...
]
`domain` can be an exact host name (`www.host.com`) or a wildcard (`*.host.com`).
### API: Add a rewrite entry
Request:
POST /control/rewrite/add
{
domain: "..."
answer: "..." // "1.2.3.4" (A) || "::1" (AAAA) || "hostname" (CNAME)
}
Response:
200 OK
### API: Remove a rewrite entry
Request:
POST /control/rewrite/delete
{
domain: "..."
answer: "..."
}
Response:
200 OK
## Services Filter
Allows to quickly block popular sites globally or for specific client only.
UI manages these settings via global or per-client API.
UI and server have the same list of the services supported and this list must always be in synchronization.
UI code also contains icons for each service: `client/src/components/ui/Icons.js`.
How it works:
* UI presents the list of services which user may want to block
* Admin clicks on the checkboxes in front of the services to block and presses Save
* UI sends `Set blocked services list` or `Update client` message
* Server updates the internal configuration
* When a user sends a DNS request for a host which is blocked by these settings, he won't receive its IP address
* Query log will show that this request was blocked by "Blocked services"
Internally, all supported services are stored as a map:
service name -> list of rules
### API: Get blocked services list of available services
Request:
GET /control/blocked_services/services
Response:
200 OK
[ "name1", ... ]
### API: Get blocked services list
Request:
GET /control/blocked_services/list
Response:
200 OK
[ "name1", ... ]
### API: Set blocked services list
Request:
POST /control/blocked_services/set
[ "name1", ... ]
Response:
200 OK
## Statistics
Load (main thread):
. Load data from the last bucket from DB for the current hour
Runtime (DNS worker threads):
. Update current unit
Runtime (goroutine):
. Periodically check that current unit should be flushed to file (when the current hour changes)
. If so, flush it, allocate a new empty unit
Runtime (HTTP worker threads):
. To respond to "Get statistics" API request we:
. load all units from file
. load current unit
. process data from all loaded units:
. sum up data for "total counters" output values
. add value into "per time unit counters" output arrays
. aggregate data for "top_" output arrays; sort in descending order
Unload (main thread):
. Flush current unit to file
### API: Get statistics data
Request:
GET /control/stats
Response:
200 OK
{
time_units: hours | days
// total counters:
num_dns_queries: 123
num_blocked_filtering: 123
num_replaced_safebrowsing: 123
num_replaced_safesearch: 123
num_replaced_parental: 123
avg_processing_time: 123.123
// per time unit counters
dns_queries: [123, ...]
blocked_filtering: [123, ...]
replaced_parental: [123, ...]
replaced_safebrowsing: [123, ...]
top_queried_domains: [
{host: 123},
...
]
top_blocked_domains: [
{host: 123},
...
]
top_clients: [
{IP: 123},
...
]
}
### API: Clear statistics data
Request:
POST /control/stats_reset
Response:
200 OK
### API: Set statistics parameters
Request:
POST /control/stats_config
{
"interval": 1 | 7 | 30 | 90
}
Response:
200 OK
### API: Get statistics parameters
Request:
GET /control/stats_info
Response:
200 OK
{
"interval": 1 | 7 | 30 | 90
}
## Query logs
When a new DNS request is received and processed, we store information about this event in "query log". It is a file on disk in JSON format:
{
"IP":"127.0.0.1", // client IP
"T":"...", // response time
"QH":"...", // target host name without the last dot
"QT":"...", // question type
"QC":"...", // question class
"CP":"" | "doh", // client connection protocol
"Answer":"base64 data",
"OrigAnswer":"base64 data",
"Result":{
"IsFiltered":true,
"Reason":3,
"Rule":"...",
"FilterID":1,
"ServiceName":"..."
},
"Elapsed":12345,
"Upstream":"...",
}
### Adding new data
First, new data is stored in a memory region. When this array is filled to a particular amount of entries (e.g. 5000), we flush this data to a file and clear the array.
### Getting data
When UI asks for data from query log (see "API: Get query log"), server reads the newest entries from memory array and the file. The maximum number of items returned per one request is limited by configuration.
### Removing old data
We store data for a limited amount of time - the log file is automatically rotated.
* On AGH startup read the first line from query logs and store its time value
* If there's no log file yet, set the time value of the first log event when the file is created
* If this time value is older than our time limit, perform file rotate procedure
* While AGH is running, check the previous condition every 24 hours
### API: Get query log
Request:
GET /control/querylog
?older_than=2006-01-02T15:04:05.999999999Z07:00
&search=...
&response_status="..."
`older_than` setting is used for paging. UI uses an empty value for `older_than` on the first request and gets the latest log entries. To get the older entries, UI sets `older_than` to the `oldest` value from the server's response.
If search settings are set, server returns only entries that match the specified request.
`search`:
match by domain name or client IP address.
The server matches substrings by default: e.g. `adguard.com` matches `www.adguard.com`.
Strict matching can be enabled by enclosing the value in double quotes: e.g. `"adguard.com"` matches `adguard.com` but doesn't match `www.adguard.com`.
`response_status`:
* all
* filtered - all kinds of filtering
* blocked - blocked or blocked services
* blocked_services - blocked services
* blocked_safebrowsing - blocked by safebrowsing
* blocked_parental - blocked by parental control
* whitelisted - whitelisted
* rewritten - all kinds of rewrites
* safe_search - enforced safe search
* processed - not blocked, not white-listed entries
Response:
{
"oldest":"2006-01-02T15:04:05.999999999Z07:00"
"data":[
{
"answer":[
{
"ttl":10,
"type":"AAAA",
"value":"::"
}
...
],
"original_answer":[ // Answer from upstream server (optional)
{
"type":"AAAA",
"value":"::"
}
...
],
"upstream":"...", // Upstream URL starting with tcp://, tls://, https://, or with an IP address
"answer_dnssec": true,
"client":"127.0.0.1",
"client_proto": "" (plain) | "doh" | "dot" | "doq",
"elapsedMs":"0.098403",
"filterId":1,
"question":{
"class":"IN",
"host":"doubleclick.net",
"type":"AAAA"
},
"reason":"FilteredBlackList",
"rule":"||doubleclick.net^",
"service_name": "...", // set if reason=FilteredBlockedService
"status":"NOERROR",
"time":"2006-01-02T15:04:05.999999999Z07:00"
}
...
]
}
The most recent entries are at the top of list.
If there are no more older entries, `"oldest":""` is returned.
### API: Set querylog parameters
Request:
POST /control/querylog_config
{
"enabled": true | false
"interval": 1 | 7 | 30 | 90
"anonymize_client_ip": true | false // anonymize clients' IP addresses
}
Response:
200 OK
`anonymize_client_ip`:
1. New log entries written to a log file will contain modified client IP addresses. Note that there's no way to obtain the full IP address later for these entries.
2. `GET /control/querylog` response data will contain modified client IP addresses (masked /24 or /112).
3. Searching by client IP won't work for the previously stored entries.
How `anonymize_client_ip` affects Stats:
1. After AGH restart, new stats entries will contain modified client IP addresses.
2. Existing entries are not affected.
### API: Get querylog parameters
Request:
GET /control/querylog_info
Response:
200 OK
{
"enabled": true | false
"interval": 1 | 7 | 30 | 90
"anonymize_client_ip": true | false
}
## Filtering

This is how DNS requests and responses are filtered by AGH:
* 'dnsproxy' module receives DNS request from client and passes control to AGH
* AGH applies filtering logic to the host name in DNS Question:
* process Rewrite rules.
Can set CNAME and a list of IP addresses.
* process /etc/hosts entries.
Can set a list of IP addresses or a hostname (for PTR requests).
* match host name against filtering lists
* match host name against blocked services rules
* process SafeSearch rules
* request SafeBrowsing & ParentalControl services and process their response
* If the handlers above create a successful result that can be immediately sent to a client, it's passed back to 'dnsproxy' module
* Otherwise, AGH passes the DNS request to an upstream server via 'dnsproxy' module
* After 'dnsproxy' module has received a response from an upstream server, it passes control back to AGH
* If the filtering logic for DNS request returned a 'whitelist' flag, AGH passes the response to a client
* Otherwise, AGH applies filtering logic to each DNS record in response:
* For CNAME records, the target name is matched against filtering lists (ignoring 'whitelist' rules)
* For A and AAAA records, the IP address is matched against filtering lists (ignoring 'whitelist' rules)
### Filters update mechanism
Filters can be updated either manually by request from UI or automatically.
Auto-update interval can be configured in UI. If it is 0, auto-update is disabled.
When the last modification date of filter files is older than auto-update interval, auto-update procedure is started.
If an enabled filter file doesn't exist, it's downloaded on application startup. This includes the case when installation wizard is completed and there are no filter files yet.
When auto-update time comes, server starts the update procedure by downloading filter files. After new filter files are in place, it restarts DNS filtering module with new rules.
Only filters that are enabled by configuration can be updated.
As a result of the update procedure, all enabled filter files are written to disk, refreshed (their last modification date is equal to the current time) and loaded.
### API: Get filtering parameters
Request:
GET /control/filtering/status
Response:
200 OK
{
"enabled": true | false
"interval": 0 | 1 | 12 | 1*24 || 3*24 || 7*24
"filters":[
{
"id":1
"enabled":true,
"url":"https://...",
"name":"...",
"rules_count":1234,
"last_updated":"2019-09-04T18:29:30+00:00",
}
...
],
"whitelist_filters":[
{
"id":1
"enabled":true,
"url":"https://...",
"name":"...",
"rules_count":1234,
"last_updated":"2019-09-04T18:29:30+00:00",
}
...
],
"user_rules":["...", ...]
}
For both arrays `filters` and `whitelist_filters` there are unique values: id, url.
ID for each filter is assigned by Server - it's used for file names.
### API: Set filtering parameters
Request:
POST /control/filtering/config
{
"enabled": true | false
"interval": 0 | 1 | 12 | 1*24 || 3*24 || 7*24
}
Response:
200 OK
### API: Refresh filters
Request:
POST /control/filtering/refresh
{
"whitelist": true
}
Response:
200 OK
{
"updated": 123 // number of filters updated
}
### API: Add Filter
Request:
POST /control/filtering/add_url
{
"name": "..."
"url": "..." // URL or an absolute file path
"whitelist": true
}
Response:
200 OK
### API: Set URL parameters
Request:
POST /control/filtering/set_url
{
"url": "..."
"whitelist": true
"data": {
"name": "..."
"url": "..."
"enabled": true | false
}
}
Response:
200 OK
### API: Delete URL
Request:
POST /control/filtering/remove_url
{
"url": "..."
"whitelist": true
}
Response:
200 OK
### API: Domain Check
Check if host name is filtered.
Request:
GET /control/filtering/check_host?name=hostname
Response:
200 OK
{
"reason":"FilteredBlackList",
"rules":{
"filter_list_id":42,
"text":"||doubleclick.net^",
},
// If we have "reason":"FilteredBlockedService".
"service_name": "...",
// If we have "reason":"Rewrite".
"cname": "...",
"ip_addrs": ["1.2.3.4", ...]
}
There are also deprecated properties `filter_id` and `rule` on the top level of
the response object. Their usage should be replaced with
`rules[*].filter_list_id` and `rules[*].text` correspondingly. See the
_OpenAPI_ documentation and the `./openapi/CHANGELOG.md` file.
## Log-in page
After user completes the steps of installation wizard, he must log in into dashboard using his name and password. After user successfully logs in, he gets the Cookie which allows the server to authenticate him next time without password. After the Cookie is expired, user needs to perform log-in operation again.
Requests to / or /index.html without a proper Cookie get redirected to Log-In page with prompt for name and password. The server responds with 403 to all other requests (including all API methods) without a proper Cookie.
YAML configuration:
users:
- name: "..."
password: "..." // bcrypt hash
...
Session DB file:
session="..." user=name expire=123456
...
Session data is SHA(random()+name+password).
Expiration time is UNIX time when cookie gets expired.
Any request to server must come with Cookie header:
GET /...
Cookie: session=...
If not authenticated, server sends a redirect response:
302 Found
Location: /login.html
### Reset password
There is no mechanism to reset the password. Instead, the administrator must use `htpasswd` utility to generate a new hash:
htpasswd -B -n -b username password
It will print `username:<HASH>` to the terminal. `<HASH>` value may be used in AGH YAML configuration file as a value to `password` setting:
users:
- name: "..."
password: <HASH>
### API: Log in
Perform a log-in operation for administrator. Server generates a session for this name+password pair, stores it in file. UI needs to perform all requests with this value inside Cookie HTTP header.
Request:
POST /control/login
{
name: "..."
password: "..."
}
Response:
200 OK
Set-Cookie: session=...; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Path=/; HttpOnly
### API: Log out
Perform a log-out operation for administrator. Server removes the session from its DB and sets an expired cookie value.
Request:
GET /control/logout
Response:
302 Found
Location: /login.html
Set-Cookie: session=...; Expires=Thu, 01 Jan 1970 00:00:00 GMT
### API: Get current user info
Request:
GET /control/profile
Response:
200 OK
{
"name":"..."
}
If no client is configured then authentication is disabled and server sends an empty response.
### Safe services
Check if host name is blocked by SB/PC service:
* For each host name component, search for the result in cache by the first 2 bytes of SHA-256 hashes of host name components (max. is 4, i.e. sub2.sub1.host.com), excluding TLD:
hashes[] = cache_search(sha256(host.com)[0..1])
...
If hash prefix is found, search for a full hash sum in the cached data.
If found, the host is blocked.
If not found, the host is not blocked - don't request data for this prefix from the Family server again.
If hash prefix is not found, request data for this prefix from the Family server.
* Prepare query string which is generated from the first 2 bytes (converted to a 4-character string) of SHA-256 hashes of host name components (max. is 4, i.e. sub2.sub1.host.com), excluding TLD:
qs = ... + string(sha256(sub.host.com)[0..1]) + "." + string(sha256(host.com)[0..1]) + ".sb.dns.adguard.com."
For PC `.pc.dns.adguard.com` suffix is used.
* Send TXT query to Family server, receive response which contains the array of complete hash sums of the blocked hosts
* Check if one of received hash sums (`hashes[]`) matches hash sums for our host name
hashes[0] <> sha256(host.com)
hashes[0] <> sha256(sub.host.com)
hashes[1] <> sha256(host.com)
hashes[1] <> sha256(sub.host.com)
...
* Store all received hash sums in cache:
sha256(host.com)[0..1] -> hashes[0],hashes[1],...
sha256(sub.host.com)[0..1] -> hashes[2],...
...
## API: Get DNS over HTTPS .mobileconfig
Request:
GET /apple/doh.mobileconfig
Response:
200 OK
DOH plist file
## API: Get DNS over TLS .mobileconfig
Request:
GET /apple/dot.mobileconfig
Response:
200 OK
DOT plist file
## ipset
AGH can add IP addresses of the specified in configuration domain names to an ipset list.
Prepare: user creates an ipset list and configures AGH for using it.
1. User --( ipset create my_ipset hash:ip ) -> OS
2. User --( ipset: host.com,host2.com/my_ipset )-> AGH
Syntax:
ipset: "DOMAIN[,DOMAIN].../IPSET1_NAME[,IPSET2_NAME]..."
IPv4 addresses are added to an ipset list with `ipv4` family, IPv6 addresses - to `ipv6` ipset list.
Run-time: AGH adds IP addresses of a domain name to a corresponding ipset list.
1. AGH --( resolve host.com )-> upstream
2. AGH <-( host.com:[1.1.1.1,2.2.2.2] )-- upstream
3. AGH --( ipset.add(my_ipset, [1.1.1.1,2.2.2.2] ))-> OS
================================================
FILE: CHANGELOG.md
================================================
# AdGuard Home Changelog
All notable changes to this project will be documented in this file.
The format is based on [*Keep a Changelog*](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
<!--
## [v0.108.0] – TBA
## [v0.107.74] - 2026-03-24 (APPROX.)
See also the [v0.107.74 GitHub milestone][ms-v0.107.74].
[ms-v0.107.74]: https://github.com/AdguardTeam/AdGuardHome/milestone/109?closed=1
NOTE: Add new changes BELOW THIS COMMENT.
-->
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.26.1][go-1.26.1].
[go-1.26.1]: https://groups.google.com/g/golang-announce/c/EdhZqrQ98hkq
### Fixed
- Fixed clients block/unblock when moving clients between allowed and disallowed lists.
<!--
NOTE: Add new changes ABOVE THIS COMMENT.
-->
## [v0.107.73] - 2026-03-10
See also the [v0.107.73 GitHub milestone][ms-v0.107.73].
### Security
- Authentication is now applied to requests that have been upgraded from HTTP/2 Cleartext (H2C) requests to public resources.
**NOTE:** We thank @mandreko for reporting this security issue.
[ms-v0.107.73]: https://github.com/AdguardTeam/AdGuardHome/milestone/108?closed=1
## [v0.107.72] - 2026-02-19
See also the [v0.107.72 GitHub milestone][ms-v0.107.72].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.25.7][go-1.25.7].
### Added
- AdGuard Home now tracks the TLS certificate and key files for updates and reloads them after any updates are detected ([#3962]).
- New query parameter `recent` in `GET /control/stats/` defines statistics lookback period in millieseconds. See `openapi/openapi.yaml` for details.
- New field `"ignored_enabled"` in `GetStatsConfigResponse` or `GetQueryLogConfigResponse`. See `openapi/openapi.yaml` for details.
### Changed
- In addition to modifying the contents of a hosts file, deleting or renaming the file now also updates runtime clients and DNS filtering results.
#### Configuration changes
In this release, the schema version has changed from 32 to 33.
- Added a new boolean field `ignored_enabled` in querylog and statistics config.
```yaml
# BEFORE:
'querylog':
# …
'ignored':
- '|.^'
'statistics':
# …
'ignored':
- '|.^'
# AFTER:
'querylog':
# …
'ignored':
- '|.^'
'ignored_enabled': true
'statistics':
# …
'ignored':
- '|.^'
'ignored_enabled': true
```
To roll back this change, set the `schema_version` back to `32`.
### Fixed
- Executable permissions in some Docker installations ([#8237]).
- Unknown blocked services from both global and client configuration now logged instead of causing server crash.
[#3962]: https://github.com/AdguardTeam/AdGuardHome/issues/3962
[#8237]: https://github.com/AdguardTeam/AdGuardHome/issues/8237
[go-1.25.7]: https://groups.google.com/g/golang-announce/c/K09ubi9FQFk
[ms-v0.107.72]: https://github.com/AdguardTeam/AdGuardHome/milestone/107?closed=1
## [v0.107.71] - 2025-12-08
See also the [v0.107.71 GitHub milestone][ms-v0.107.71].
### Changed
- Stale records in optimistic DNS cache now have an upper age limit controlled by `dns.cache_optimistic_max_age`. The default value is 12 hours.
- TTL for stale answers from optimistic DNS cache is now controlled by `dns.cache_optimistic_answer_ttl`. The default value is 30 seconds.
#### Configuration changes
In this release, the schema version has changed from 31 to 32.
- Added a new string fields `dns.cache_optimistic_answer_ttl` and `dns.cache_optimistic_max_age`.
```yaml
# BEFORE:
'dns':
'cache_enabled': true
'cache_optimistic': true
# …
# AFTER:
'dns':
'cache_enabled': true
'cache_optimistic': true
'cache_optimistic_answer_ttl': '30s'
'cache_optimistic_max_age': '12h'
# …
```
To roll back this change, set the `schema_version` back to `31`.
### Fixed
- Optimistic DNS cache not working ([#8148]).
[#8148]: https://github.com/AdguardTeam/AdGuardHome/issues/8148
[ms-v0.107.71]: https://github.com/AdguardTeam/AdGuardHome/milestone/106?closed=1
## [v0.107.70] - 2025-12-03
See also the [v0.107.70 GitHub milestone][ms-v0.107.70].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.25.5][go-1.25.5].
### Added
- New field `"start_time"` in the `GET /control/status` response.
### Changed
- Stale records in optimistic DNS cache now have an upper age limit of 12 hours.
- New blocked services UI.
### Fixed
- Generated mobileconfig could not be installed on macOS 26.1.
[go-1.25.5]: https://groups.google.com/g/golang-announce/c/8FJoBkPddm4
[ms-v0.107.70]: https://github.com/AdguardTeam/AdGuardHome/milestone/105?closed=1
## [v0.107.69] - 2025-10-30
See also the [v0.107.69 GitHub milestone][ms-v0.107.69].
### Changed
- Node.js 24 is now used to build the frontend.
### Deprecated
- Node.js 20 and 22 support.
### Fixed
- DHCP settings could not be saved ([#8075]).
- DNS Rewrite edit modal did not populate with the correct values ([#8072]).
### Removed
- The outdated querylog anonymization script.
[#8075]: https://github.com/AdguardTeam/AdGuardHome/issues/8075
[#8072]: https://github.com/AdguardTeam/AdGuardHome/issues/8072
[ms-v0.107.69]: https://github.com/AdguardTeam/AdGuardHome/milestone/104?closed=1
## [v0.107.68] - 2025-10-23
See also the [v0.107.68 GitHub milestone][ms-v0.107.68].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.25.3][go-1.25.3].
### Added
- New DNS rewrite settings endpoints `GET /control/rewrite/settings` and `PUT /control/rewrite/settings/update` ([#1765]). See `openapi/openapi.yaml` for details.
- New fields `"groups"` and `"group_id"` added to the HTTP API (`GET /control/blocked_services/all`). See `openapi/openapi.yaml` for the full description.
### Changed
- `POST /control/rewrite/add` and `PUT /control/rewrite/update` now accept the optional field "enabled" ([#1765]). See `openapi/openapi.yaml` for details.
#### Configuration changes
In this release, the schema version has changed from 30 to 31.
- Added a new boolean field `filtering.rewrites_enabled` to globally enable/disable DNS rewrites.
- Added a new boolean field `enabled` for each entry in `filtering.rewrites` to toggle individual rewrites.
```yaml
# BEFORE:
'filtering':
'rewrites':
- 'domain': test.example
'answer': 192.0.2.0
# …
# AFTER:
'filtering':
'rewrites_enabled': true
'rewrites':
- 'domain': test.example
'answer': 192.0.2.0
'enabled': true
# …
```
To roll back this change, set `schema_version` back to `30`.
[#1765]: https://github.com/AdguardTeam/AdGuardHome/issues/1765
[go-1.25.3]: https://groups.google.com/g/golang-announce/c/YEyj6FUNbik
[ms-v0.107.68]: https://github.com/AdguardTeam/AdGuardHome/milestone/103?closed=1
## [v0.107.67] - 2025-09-29
See also the [v0.107.67 GitHub milestone][ms-v0.107.67].
### Added
- The *HaGeZi's DNS Rebind Protection* filter for protecting against DNS rebinding attacks ([#102]).
- Support for configuring the suggested default HTTP port for the installation wizard via the `ADGUARD_HOME_DEFAULT_WEB_PORT` environment variable (useful for vendors).
### Changed
- Optimized matching of filtering rules.
### Fixed
- Excessive configuration file overwrites when visiting the Web UI and a non-empty `language` is set.
- Lowered the severity of log messages for failed deletion of old filter files ([#7964]).
[#102]: https://github.com/AdguardTeam/AdGuardHome/issues/102
[#7964]: https://github.com/AdguardTeam/AdGuardHome/issues/7964
[ms-v0.107.67]: https://github.com/AdguardTeam/AdGuardHome/milestone/102?closed=1
## [v0.107.66] - 2025-09-15
See also the [v0.107.66 GitHub milestone][ms-v0.107.66].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.25.1][go-1.25.1].
### Changed
- Our snap package now uses the `core24` image as its base.
- Outgoing HTTP requests now use the `User-Agent` header `AdGuardHome/v0.107.66` (where `v0.107.66` is the current version) instead of `Go-http-client/1.1` ([#7979]).
### Fixed
- Authentication errors in the Web UI when AdGuard Home is behind a proxy that sets Basic Auth headers ([#7987]).
- The HTTP API `GET /control/profile` endpoint failing when no users were configured ([#7985]).
- Missing warning on the *Encryption Settings* page when using a certificate without an IP address.
[#7979]: https://github.com/AdguardTeam/AdGuardHome/issues/7979
[#7985]: https://github.com/AdguardTeam/AdGuardHome/issues/7985
[#7987]: https://github.com/AdguardTeam/AdGuardHome/issues/7987
[go-1.25.1]: https://groups.google.com/g/golang-announce/c/PtW9VW21NPs
[ms-v0.107.66]: https://github.com/AdguardTeam/AdGuardHome/milestone/101?closed=1
## [v0.107.65] - 2025-08-20
See also the [v0.107.65 GitHub milestone][ms-v0.107.65].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.24.6][go-1.24.6].
### Added
- A separate checkbox in the Web UI to enable or disable the global DNS response cache without losing the configured cache size.
- A new `"cache_enabled"` field to the HTTP API (`GET /control/dns_info` and `POST /control/dns_config`). See `openapi/openapi.yaml` for the full description.
### Changed
#### Configuration changes
In this release, the schema version has changed from 29 to 30.
- Added a new boolean field `dns.cache_enabled` to the configuration. This field explicitly controls whether DNS caching is enabled, replacing the previous implicit logic based on `dns.cache_size`.
```yaml
# BEFORE:
'dns':
# …
'cache_size': 123456
# AFTER:
'dns':
# …
'cache_enabled': true
'cache_size': 123456
```
To roll back this change, set the schema_version back to `29`.
### Fixed
- Disabled state of *Top clients* action button in web UI ([#7923]).
[#7923]: https://github.com/AdguardTeam/AdGuardHome/issues/7923
[go-1.24.6]: https://groups.google.com/g/golang-announce/c/x5MKroML2yM
[ms-v0.107.65]: https://github.com/AdguardTeam/AdGuardHome/milestone/100?closed=1
## [v0.107.64] - 2025-07-28
See also the [v0.107.64 GitHub milestone][ms-v0.107.64].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.24.5][go-1.24.5].
### Fixed
- TTL override calculation ([#7903]).
- Validation process for DNSCrypt settings ([#7856]).
[#7856]: https://github.com/AdguardTeam/AdGuardHome/issues/7856
[#7903]: https://github.com/AdguardTeam/AdGuardHome/issues/7903
[go-1.24.5]: https://groups.google.com/g/golang-announce/c/gTNJnDXmn34
[ms-v0.107.64]: https://github.com/AdguardTeam/AdGuardHome/milestone/99?closed=1
## [v0.107.63] - 2025-06-26
See also the [v0.107.63 GitHub milestone][ms-v0.107.63].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.24.4][go-1.24.4].
### Fixed
- The hostnames of DHCP clients with multiple labels not being recognized.
- Status reported by the systemd service implementation in cases of auto-restart after a failed start.
[go-1.24.4]: https://groups.google.com/g/golang-announce/c/ufZ8WpEsA3A
[ms-v0.107.63]: https://github.com/AdguardTeam/AdGuardHome/milestone/98?closed=1
## [v0.107.62] - 2025-05-27
See also the [v0.107.62 GitHub milestone][ms-v0.107.62].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.24.3][go-1.24.3].
### Fixed
- Clients with CIDR identifiers showing zero requests on the *Settings → Client settings* page ([#2945]).
- Command line option `--update` when the `dns.serve_plain_dns` configuration property was disabled ([#7801]).
- DNS cache not working for custom upstream configurations.
- Validation process for the DNS-over-TLS, DNS-over-QUIC, and HTTPS ports on the *Encryption Settings* page.
- Searching for persistent clients using an exact match for CIDR in the `POST /clients/search` HTTP API.
[#2945]: https://github.com/AdguardTeam/AdGuardHome/issues/2945
[#7801]: https://github.com/AdguardTeam/AdGuardHome/issues/7801
[go-1.24.3]: https://groups.google.com/g/golang-announce/c/UZoIkUT367A
[ms-v0.107.62]: https://github.com/AdguardTeam/AdGuardHome/milestone/97?closed=1
## [v0.107.61] - 2025-04-22
See also the [v0.107.61 GitHub milestone][ms-v0.107.61].
### Security
- Any simultaneous requests that are considered duplicates will now only result in a single request to upstreams, reducing the chance of a cache poisoning attack succeeding. This is controlled by the new configuration object `pending_requests`, which has a single `enabled` property, set to `true` by default.
**NOTE:** We thank [Xiang Li][mr-xiang-li] for reporting this security issue. It's strongly recommended to leave it enabled, otherwise AdGuard Home will be vulnerable to untrusted clients.
[mr-xiang-li]: https://lixiang521.com/
[ms-v0.107.61]: https://github.com/AdguardTeam/AdGuardHome/milestone/96?closed=1
## [v0.107.60] - 2025-04-14
See also the [v0.107.60 GitHub milestone][ms-v0.107.60].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.24.2][go-1.24.2].
### Changed
- Alpine Linux version in `Dockerfile` has been updated to 3.21 ([#7588]).
### Deprecated
- Node 20 support, Node 22 will be required in future releases.
**NOTE:** `npm` may be replaced with a different tool, such as `pnpm` or `yarn`, in a future release.
### Fixed
- Filtering for DHCP clients ([#7734]).
- Incorrect label on login page ([#7729]).
- Validation process for the HTTPS port on the *Encryption Settings* page.
### Removed
- Node 18 support.
[#7588]: https://github.com/AdguardTeam/AdGuardHome/issues/7588
[#7729]: https://github.com/AdguardTeam/AdGuardHome/issues/7729
[#7734]: https://github.com/AdguardTeam/AdGuardHome/issues/7734
[go-1.24.2]: https://groups.google.com/g/golang-announce/c/Y2uBTVKjBQk
[ms-v0.107.60]: https://github.com/AdguardTeam/AdGuardHome/milestone/95?closed=1
## [v0.107.59] - 2025-03-21
See also the [v0.107.59 GitHub milestone][ms-v0.107.59].
- Rules with the `client` modifier not working ([#7708]).
- The search form not working in the query log ([#7704]).
[#7704]: https://github.com/AdguardTeam/AdGuardHome/issues/7704
[#7708]: https://github.com/AdguardTeam/AdGuardHome/issues/7708
[ms-v0.107.59]: https://github.com/AdguardTeam/AdGuardHome/milestone/94?closed=1
## [v0.107.58] - 2025-03-19
See also the [v0.107.58 GitHub milestone][ms-v0.107.58].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.24.1][go-1.24.1].
### Added
- The ability to check filtering rules for host names using an optional query type and optional ClientID or client IP address ([#4036]).
- Optional `client` and `qtype` URL query parameters to the `GET /control/check_host` HTTP API.
### Fixed
- Clearing the DNS cache on the *DNS settings* page now includes both global cache and custom client cache.
- Invalid ICMPv6 Router Advertisement messages ([#7547]).
- Disabled button for autofilled login form.
- Formatting of elapsed times less than one millisecond.
- Changes to global upstream DNS settings not applying to custom client upstream configurations.
- The formatting of large numbers in the clients tables on the *Client settings* page ([#7583]).
[#4036]: https://github.com/AdguardTeam/AdGuardHome/issues/4036
[#7547]: https://github.com/AdguardTeam/AdGuardHome/issues/7547
[#7583]: https://github.com/AdguardTeam/AdGuardHome/issues/7583
[go-1.24.1]: https://groups.google.com/g/golang-announce/c/4t3lzH3I0eI
[ms-v0.107.58]: https://github.com/AdguardTeam/AdGuardHome/milestone/93?closed=1
## [v0.107.57] - 2025-02-20
See also the [v0.107.57 GitHub milestone][ms-v0.107.57].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.23.6][go-1.23.6].
### Added
- The ability to specify the upstream timeout in the Web UI.
### Changed
- The *Fastest IP address* upstream mode now correctly collects statistics for all upstream DNS servers.
### Fixed
- The hostnames of DHCP clients not being shown in the *Top clients* table on the dashboard ([#7627]).
- The formatting of large numbers in the upstream table and query log ([#7590]).
[#7590]: https://github.com/AdguardTeam/AdGuardHome/issues/7590
[#7627]: https://github.com/AdguardTeam/AdGuardHome/issues/7627
[go-1.23.6]: https://groups.google.com/g/golang-announce/c/xU1ZCHUZw3k
[ms-v0.107.57]: https://github.com/AdguardTeam/AdGuardHome/milestone/92?closed=1
## [v0.107.56] - 2025-01-23
See also the [v0.107.56 GitHub milestone][ms-v0.107.56].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.23.5][go-1.23.5].
### Added
- The new HTTP API `POST /clients/search` that finds clients by their IP addresses, CIDRs, MAC addresses, or ClientIDs. See `openapi/openapi.yaml` for the full description.
### Deprecated
- The `GET /clients/find` HTTP API is deprecated. Use the new `POST /clients/search` API.
### Fixed
- Request count link in the clients table ([#7513]).
- The formatting of large numbers on the dashboard ([#7329]).
[#7329]: https://github.com/AdguardTeam/AdGuardHome/issues/7329
[#7513]: https://github.com/AdguardTeam/AdGuardHome/issues/7513
[go-1.23.5]: https://groups.google.com/g/golang-announce/c/sSaUhLA-2SI
[ms-v0.107.56]: https://github.com/AdguardTeam/AdGuardHome/milestone/91?closed=1
## [v0.107.55] - 2024-12-11
See also the [v0.107.55 GitHub milestone][ms-v0.107.55].
### Security
- The permission check and migration on Windows has been fixed to use the Windows security model more accurately ([#7400]).
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.23.4][go-1.23.4].
- The Windows executables are now signed.
### Added
- The `--no-permcheck` command-line option to disable checking and migration of permissions for the security-sensitive files and directories, which caused issues on Windows ([#7400]).
### Fixed
- Setup guide styles in Firefox.
- Goroutine leak during the upstream DNS server test ([#7357]).
- Goroutine leak during configuration update resulting in increased response time ([#6818]).
[#7357]: https://github.com/AdguardTeam/AdGuardHome/issues/7357
[#7400]: https://github.com/AdguardTeam/AdGuardHome/issues/7400
[go-1.23.4]: https://groups.google.com/g/golang-announce/c/3DyiMkYx4Fo
[ms-v0.107.55]: https://github.com/AdguardTeam/AdGuardHome/milestone/90?closed=1
## [v0.107.54] - 2024-11-06
See also the [v0.107.54 GitHub milestone][ms-v0.107.54].
### Security
- Incorrect handling of sensitive files permissions on Windows ([#7314]).
### Changed
- Improved filtering performance ([#6818]).
### Fixed
- Repetitive statistics log messages ([#7338]).
- Custom client cache ([#7250]).
- Missing runtime clients with information from the system hosts file on first AdGuard Home start ([#7315]).
[#6818]: https://github.com/AdguardTeam/AdGuardHome/issues/6818
[#7250]: https://github.com/AdguardTeam/AdGuardHome/issues/7250
[#7314]: https://github.com/AdguardTeam/AdGuardHome/issues/7314
[#7315]: https://github.com/AdguardTeam/AdGuardHome/issues/7315
[#7338]: https://github.com/AdguardTeam/AdGuardHome/issues/7338
[ms-v0.107.54]: https://github.com/AdguardTeam/AdGuardHome/milestone/89?closed=1
## [v0.107.53] - 2024-10-03
See also the [v0.107.53 GitHub milestone][ms-v0.107.53].
### Security
- Previous versions of AdGuard Home allowed users to add any system file it had access to as filters, exposing them to be world-readable. To prevent this, AdGuard Home now allows adding filtering-rule list files only from files matching the patterns enumerated in the `filtering.safe_fs_patterns` property in the configuration file.
We thank @itz-d0dgy for reporting this vulnerability, designated CVE-2024-36814, to us.
- Additionally, AdGuard Home will now try to change the permissions of its files and directories to more restrictive ones to prevent similar vulnerabilities as well as limit the access to the configuration.
We thank @go-compile for reporting this vulnerability, designated CVE-2024-36586, to us.
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.23.2][go-1.23.2].
### Added
- Support for 64-bit RISC-V architecture ([#5704]).
- Ecosia search engine is now supported in safe search ([#5009]).
### Changed
- Upstream server URL domain names requirements has been relaxed and now follow the same rules as their domain specifications.
#### Configuration changes
In this release, the schema version has changed from 28 to 29.
- The new array `filtering.safe_fs_patterns` contains glob patterns for paths of files that can be added as local filtering-rule lists. The migration should add list files that have already been added, as well as the default value, `$DATA_DIR/userfilters/*`.
### Fixed
- Property `clients.runtime_sources.dhcp` in the configuration file not taking effect.
- Stale Google safe search domains list ([#7155]).
- Bing safe search from Edge sidebar ([#7154]).
- Text overflow on the query log page ([#7119]).
### Known issues
- Due to the complexity of the Windows permissions architecture and poor support from the standard Go library, we have to postpone the proper automated Windows fix until the next release.
**Temporary workaround:** Set the permissions of the `AdGuardHome` directory to more restrictive ones manually. To do that:
1. Locate the `AdGuardHome` directory.
2. Right-click on it and navigate to *Properties → Security → Advanced.*
3. (You might need to disable permission inheritance to make them more restricted.)
4. Adjust to give the `Full control` access to only the user which runs AdGuard Home. Typically, `Administrator`.
[#5009]: https://github.com/AdguardTeam/AdGuardHome/issues/5009
[#5704]: https://github.com/AdguardTeam/AdGuardHome/issues/5704
[#7119]: https://github.com/AdguardTeam/AdGuardHome/issues/7119
[#7154]: https://github.com/AdguardTeam/AdGuardHome/pull/7154
[#7155]: https://github.com/AdguardTeam/AdGuardHome/pull/7155
[go-1.23.2]: https://groups.google.com/g/golang-announce/c/NKEc8VT7Fz0
[ms-v0.107.53]: https://github.com/AdguardTeam/AdGuardHome/milestone/88?closed=1
## [v0.107.52] - 2024-07-04
See also the [v0.107.52 GitHub milestone][ms-v0.107.52].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [Go 1.22.5][go-1.22.5].
### Added
- The ability to disable logging using the new `log.enabled` configuration property ([#7079]).
### Changed
- Frontend rewritten in TypeScript.
- The `systemd`-based service now uses `journal` for logging by default. It also doesn’t create the `/var/log/` directory anymore ([#7053]).
**NOTE:** With an installed service for changes to take effect, you need to reinstall the service using `-r` flag of the [install script][install-script] or via the CLI (with root privileges):
```sh
./AdGuardHome -s uninstall
./AdGuardHome -s install
```
Don’t forget to backup your configuration file and other important data before reinstalling the service.
### Deprecated
- Node 18 support, Node 20 will be required in future releases.
### Fixed
- Panic caused by missing user-specific blocked services object in configuration file ([#7069]).
- Tracking `/etc/hosts` file changes causing panics within particular filesystems on start ([#7076]).
[#7053]: https://github.com/AdguardTeam/AdGuardHome/issues/7053
[#7069]: https://github.com/AdguardTeam/AdGuardHome/issues/7069
[#7076]: https://github.com/AdguardTeam/AdGuardHome/issues/7076
[#7079]: https://github.com/AdguardTeam/AdGuardHome/issues/7079
[go-1.22.5]: https://groups.google.com/g/golang-announce/c/gyb7aM1C9H4
[install-script]: https://github.com/AdguardTeam/AdGuardHome/?tab=readme-ov-file#automated-install-linux-and-mac
[ms-v0.107.52]: https://github.com/AdguardTeam/AdGuardHome/milestone/87?closed=1
## [v0.107.51] - 2024-06-06
See also the [v0.107.51 GitHub milestone][ms-v0.107.51].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [Go 1.22.4][go-1.22.4].
### Changed
- The HTTP server’s write timeout has been increased from 1 minute to 5 minutes to match the one used by AdGuard Home’s HTTP client to fetch filtering-list data ([#7041]).
[#7041]: https://github.com/AdguardTeam/AdGuardHome/issues/7041
[go-1.22.4]: https://groups.google.com/g/golang-announce/c/XbxouI9gY7k/
[ms-v0.107.51]: https://github.com/AdguardTeam/AdGuardHome/milestone/86?closed=1
## [v0.107.50] - 2024-05-23
See also the [v0.107.50 GitHub milestone][ms-v0.107.50].
### Fixed
- Broken private reverse DNS upstream servers validation causing update failures ([#7013]).
[#7013]: https://github.com/AdguardTeam/AdGuardHome/issues/7013
[ms-v0.107.50]: https://github.com/AdguardTeam/AdGuardHome/milestone/85?closed=1
## [v0.107.49] - 2024-05-21
See also the [v0.107.49 GitHub milestone][ms-v0.107.49].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [Go 1.22.3][go-1.22.3].
### Added
- Support for comments in the ipset file ([#5345]).
### Changed
- Private rDNS resolution now also affects `SOA` and `NS` requests ([#6882]).
- Rewrite rules mechanics were changed due to improved resolving in safe search.
### Deprecated
- Currently, AdGuard Home skips persistent clients that have duplicate fields when reading them from the configuration file. This behaviour is deprecated and will cause errors on startup in a future release.
### Fixed
- Acceptance of duplicate UIDs for persistent clients at startup. See also the section on client settings on the [Wiki page][wiki-config].
- Domain specifications for top-level domains not considered for requests to unqualified domains ([#6744]).
- Support for link-local subnets, i.e. `fe80::/16`, as client identifiers ([#6312]).
- Issues with QUIC and HTTP/3 upstreams on older Linux kernel versions ([#6422]).
- YouTube restricted mode is not enforced by HTTPS queries on Firefox.
- Support for link-local subnets, i.e. `fe80::/16`, in the access settings ([#6192]).
- The ability to apply an invalid configuration for private rDNS, which led to server not starting.
- Ignoring query log for clients with ClientID set ([#5812]).
- Subdomains of `in-addr.arpa` and `ip6.arpa` containing zero-length prefix incorrectly considered invalid when specified for private rDNS upstream servers ([#6854]).
- Unspecified IP addresses aren’t checked when using "Fastest IP address" mode ([#6875]).
[#5345]: https://github.com/AdguardTeam/AdGuardHome/issues/5345
[#5812]: https://github.com/AdguardTeam/AdGuardHome/issues/5812
[#6192]: https://github.com/AdguardTeam/AdGuardHome/issues/6192
[#6312]: https://github.com/AdguardTeam/AdGuardHome/issues/6312
[#6422]: https://github.com/AdguardTeam/AdGuardHome/issues/6422
[#6744]: https://github.com/AdguardTeam/AdGuardHome/issues/6744
[#6854]: https://github.com/AdguardTeam/AdGuardHome/issues/6854
[#6875]: https://github.com/AdguardTeam/AdGuardHome/issues/6875
[#6882]: https://github.com/AdguardTeam/AdGuardHome/issues/6882
[go-1.22.3]: https://groups.google.com/g/golang-announce/c/wkkO4P9stm0
[ms-v0.107.49]: https://github.com/AdguardTeam/AdGuardHome/milestone/84?closed=1
## [v0.107.48] - 2024-04-05
See also the [v0.107.48 GitHub milestone][ms-v0.107.48].
### Fixed
- Access settings not being applied to encrypted protocols ([#6890]).
[#6890]: https://github.com/AdguardTeam/AdGuardHome/issues/6890
[ms-v0.107.48]: https://github.com/AdguardTeam/AdGuardHome/milestone/83?closed=1
## [v0.107.47] - 2024-04-04
See also the [v0.107.47 GitHub milestone][ms-v0.107.47].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [Go 1.22.2][go-1.22.2].
### Changed
- Time Zone Database is now embedded in the binary ([#6758]).
- Failed authentication attempts show the originating IP address in the logs, if the request came from a trusted proxy ([#5829]).
### Deprecated
- Go 1.22 support. Future versions will require at least Go 1.23 to build.
- Currently, AdGuard Home uses a best-effort algorithm to fix invalid IDs of filtering-rule lists on startup. This feature is deprecated, and invalid IDs will cause errors on startup in a future version.
- Node.JS 16. Future versions will require at least Node.JS 18 to build.
### Fixed
- Resetting DNS upstream mode when applying unrelated settings ([#6851]).
- Symbolic links to the configuration file begin replaced by a copy of the real file upon startup on FreeBSD ([#6717]).
### Removed
- Go 1.21 support.
[#5829]: https://github.com/AdguardTeam/AdGuardHome/issues/5829
[#6717]: https://github.com/AdguardTeam/AdGuardHome/issues/6717
[#6758]: https://github.com/AdguardTeam/AdGuardHome/issues/6758
[#6851]: https://github.com/AdguardTeam/AdGuardHome/issues/6851
[go-1.22.2]: https://groups.google.com/g/golang-announce/c/YgW0sx8mN3M/
[ms-v0.107.47]: https://github.com/AdguardTeam/AdGuardHome/milestone/82?closed=1
## [v0.107.46] - 2024-03-20
See also the [v0.107.46 GitHub milestone][ms-v0.107.46].
### Added
- Ability to disable the use of system hosts file information for query resolution ([#6610]).
- Ability to define custom directories for storage of query log files and statistics ([#5992]).
### Changed
- Private rDNS resolution (`dns.use_private_ptr_resolvers` in YAML configuration) now requires a valid "Private reverse DNS servers", when enabled ([#6820]).
**NOTE:** Disabling private rDNS resolution behaves effectively the same as if no private reverse DNS servers provided by user and by the OS.
### Fixed
- Statistics for 7 days displayed by day on the dashboard graph ([#6712]).
- Missing "served from cache" label on long DNS server strings ([#6740]).
- Incorrect tracking of the system hosts file’s changes ([#6711]).
[#5992]: https://github.com/AdguardTeam/AdGuardHome/issues/5992
[#6610]: https://github.com/AdguardTeam/AdGuardHome/issues/6610
[#6711]: https://github.com/AdguardTeam/AdGuardHome/issues/6711
[#6712]: https://github.com/AdguardTeam/AdGuardHome/issues/6712
[#6740]: https://github.com/AdguardTeam/AdGuardHome/issues/6740
[#6820]: https://github.com/AdguardTeam/AdGuardHome/issues/6820
[ms-v0.107.46]: https://github.com/AdguardTeam/AdGuardHome/milestone/81?closed=1
## [v0.107.45] - 2024-03-06
See also the [v0.107.45 GitHub milestone][ms-v0.107.45].
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [Go 1.21.8][go-1.21.8].
### Added
- Context menu item in the Query Log to add a Client to the Persistent client list ([#6679]).
### Changed
- Starting with this release our scripts are using Go’s [forward compatibility mechanism][go-toolchain] for updating the Go version.
**Important note for porters:** This change means that if your `go` version is 1.21+ but is different from the one required by AdGuard Home, the `go` tool will automatically download the required version.
If you want to use the version installed on your builder, run:
```sh
go get go@$YOUR_VERSION
go mod tidy
```
and call `make` with `GOTOOLCHAIN=local`.
### Deprecated
- Go 1.21 support. Future versions will require at least Go 1.22 to build.
### Fixed
- Missing IP addresses in logs when querying for domain names from the ignore lists.
- Blank page after resetting access clients ([#6634]).
- Wrong algorithm for caching bootstrapped upstream addresses ([#6723]).
### Removed
- Go 1.20 support, as it has reached end of life.
[#6634]: https://github.com/AdguardTeam/AdGuardHome/issues/6634
[#6679]: https://github.com/AdguardTeam/AdGuardHome/issues/6679
[#6723]: https://github.com/AdguardTeam/AdGuardHome/issues/6723
[go-1.21.8]: https://groups.google.com/g/golang-announce/c/5pwGVUPoMbg
[go-toolchain]: https://go.dev/blog/toolchain
[ms-v0.107.45]: https://github.com/AdguardTeam/AdGuardHome/milestone/80?closed=1
## [v0.107.44] - 2024-02-06
See also the [v0.107.44 GitHub milestone][ms-v0.107.44].
### Added
- Timezones in the Etc/ area to the timezone list ([#6568]).
- The schema version of the configuration file to the output of running `AdGuardHome` (or `AdGuardHome.exe`) with `-v --version` command-line options ([#6545]).
- Ability to disable plain-DNS serving via UI if an encrypted protocol is already used ([#1660]).
### Changed
- The bootstrapped upstream addresses are now updated according to the TTL of the bootstrap DNS response ([#6321]).
- Logging level of timeout errors is now `error` instead of `debug` ([#6574]).
- The field `"upstream_mode"` in `POST /control/dns_config` and `GET /control/dns_info` HTTP APIs now accepts `load_balance` value. Check `openapi/CHANGELOG.md` for more details.
#### Configuration changes
In this release, the schema version has changed from 27 to 28.
- The new property `clients.persistent.*.uid`, which is a unique identifier of the persistent client.
- The properties `dns.all_servers` and `dns.fastest_addr` were removed, their values migrated to newly added field `dns.upstream_mode` that describes the logic through which upstreams will be used. See also a [Wiki page][wiki-config].
```yaml
# BEFORE:
'dns':
# …
'all_servers': true
'fastest_addr': true
# AFTER:
'dns':
# …
'upstream_mode': 'parallel'
```
To rollback this change, remove the new field `upstream_mode`, set back `dns.all_servers` and `dns.fastest_addr` properties in `dns` section, and change the `schema_version` back to `27`.
### Fixed
- “Invalid AddrPort” in the *Private reverse DNS servers* section on the *Settings → DNS settings* page.
- Panic on using `--no-etc-hosts` flag ([#6644]).
- Schedule display in the client settings after creating or updating.
- Zero value in `querylog.size_memory` disables logging ([#6570]).
- Non-anonymized IP addresses on the dashboard ([#6584]).
- Maximum cache TTL requirement when editing minimum cache TTL in the Web UI ([#6409]).
- Load balancing algorithm stuck on a single server ([#6480]).
- Statistics for 7 days displayed as 168 hours on the dashboard.
- Pre-filling the Edit static lease window with data ([#6534]).
- Names defined in the `/etc/hosts` for a single address family wrongly considered undefined for another family ([#6541]).
- Omitted CNAME records in safe search results, which can cause YouTube to not work on iOS ([#6352]).
[#6321]: https://github.com/AdguardTeam/AdGuardHome/issues/6321
[#6352]: https://github.com/AdguardTeam/AdGuardHome/issues/6352
[#6409]: https://github.com/AdguardTeam/AdGuardHome/issues/6409
[#6480]: https://github.com/AdguardTeam/AdGuardHome/issues/6480
[#6534]: https://github.com/AdguardTeam/AdGuardHome/issues/6534
[#6541]: https://github.com/AdguardTeam/AdGuardHome/issues/6541
[#6545]: https://github.com/AdguardTeam/AdGuardHome/issues/6545
[#6568]: https://github.com/AdguardTeam/AdGuardHome/issues/6568
[#6570]: https://github.com/AdguardTeam/AdGuardHome/issues/6570
[#6574]: https://github.com/AdguardTeam/AdGuardHome/issues/6574
[#6584]: https://github.com/AdguardTeam/AdGuardHome/issues/6584
[#6644]: https://github.com/AdguardTeam/AdGuardHome/issues/6644
[ms-v0.107.44]: https://github.com/AdguardTeam/AdGuardHome/milestone/79?closed=1
[wiki-config]: https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration
## [v0.107.43] - 2023-12-11
See also the [v0.107.43 GitHub milestone][ms-v0.107.43].
### Fixed
- Incorrect handling of IPv4-in-IPv6 addresses when binding to an unspecified address on some machines ([#6510]).
[#6510]: https://github.com/AdguardTeam/AdGuardHome/issues/6510
[ms-v0.107.43]: https://github.com/AdguardTeam/AdGuardHome/milestone/78?closed=1
## [v0.107.42] - 2023-12-07
See also the [v0.107.42 GitHub milestone][ms-v0.107.42].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-39326, CVE-2023-45283, and CVE-2023-45285 Go vulnerabilities fixed in [Go 1.20.12][go-1.20.12].
### Added
- Ability to set client’s custom DNS cache ([#6263]).
- Ability to disable plain-DNS serving through configuration file if an encrypted protocol is already enabled ([#1660]).
- Ability to specify rate limiting settings in the Web UI ([#6369]).
### Changed
#### Configuration changes
- The new property `dns.serve_plain_dns` has been added to the configuration file ([#1660]).
- The property `dns.bogus_nxdomain` is now validated more strictly.
- Added new properties `clients.persistent.*.upstreams_cache_enabled` and `clients.persistent.*.upstreams_cache_size` that describe cache configuration for each client’s custom upstream configuration.
### Fixed
- `ipset` entries family validation ([#6420]).
- Pre-filling the *New static lease* window with data ([#6402]).
- Protection pause timer synchronization ([#5759]).
[#1660]: https://github.com/AdguardTeam/AdGuardHome/issues/1660
[#5759]: https://github.com/AdguardTeam/AdGuardHome/issues/5759
[#6263]: https://github.com/AdguardTeam/AdGuardHome/issues/6263
[#6369]: https://github.com/AdguardTeam/AdGuardHome/issues/6369
[#6402]: https://github.com/AdguardTeam/AdGuardHome/issues/6402
[#6420]: https://github.com/AdguardTeam/AdGuardHome/issues/6420
[go-1.20.12]: https://groups.google.com/g/golang-announce/c/iLGK3x6yuNo/m/z6MJ-eB0AQAJ
[ms-v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/milestone/77?closed=1
## [v0.107.41] - 2023-11-13
See also the [v0.107.41 GitHub milestone][ms-v0.107.41].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-45283 and CVE-2023-45284 Go vulnerabilities fixed in [Go 1.20.11][go-1.20.11].
### Added
- Ability to specify subnet lengths for IPv4 and IPv6 addresses, used for rate limiting requests, in the configuration file ([#6368]).
- Ability to specify multiple domain specific upstreams per line, e.g. `[/domain1/../domain2/]upstream1 upstream2 .. upstreamN` ([#4977]).
### Changed
- Increased the height of the ready-to-use filter lists dialog ([#6358]).
- Improved logging of authentication failures ([#6357]).
#### Configuration changes
- New properties `dns.ratelimit_subnet_len_ipv4` and `dns.ratelimit_subnet_len_ipv6` have been added to the configuration file ([#6368]).
### Fixed
- Schedule timezone not being sent ([#6401]).
- Average request processing time calculation ([#6220]).
- Redundant truncation of long client names in the Top Clients table ([#6338]).
- Scrolling column headers in the tables ([#6337]).
- `$important,dnsrewrite` rules not overriding allowlist rules ([#6204]).
- Dark mode DNS rewrite background ([#6329]).
- Issues with QUIC and HTTP/3 upstreams on Linux ([#6335]).
[#4977]: https://github.com/AdguardTeam/AdGuardHome/issues/4977
[#6204]: https://github.com/AdguardTeam/AdGuardHome/issues/6204
[#6220]: https://github.com/AdguardTeam/AdGuardHome/issues/6220
[#6329]: https://github.com/AdguardTeam/AdGuardHome/issues/6329
[#6335]: https://github.com/AdguardTeam/AdGuardHome/issues/6335
[#6337]: https://github.com/AdguardTeam/AdGuardHome/issues/6337
[#6338]: https://github.com/AdguardTeam/AdGuardHome/issues/6338
[#6357]: https://github.com/AdguardTeam/AdGuardHome/issues/6357
[#6358]: https://github.com/AdguardTeam/AdGuardHome/issues/6358
[#6368]: https://github.com/AdguardTeam/AdGuardHome/issues/6368
[#6401]: https://github.com/AdguardTeam/AdGuardHome/issues/6401
[go-1.20.11]: https://groups.google.com/g/golang-announce/c/4tU8LZfBFkY/m/d-jSKR_jBwAJ
[ms-v0.107.41]: https://github.com/AdguardTeam/AdGuardHome/milestone/76?closed=1
## [v0.107.40] - 2023-10-18
See also the [v0.107.40 GitHub milestone][ms-v0.107.40].
### Changed
- *Block* and *Unblock* buttons of the query log moved to the tooltip menu ([#684]).
### Fixed
- Dashboard tables scroll issue ([#6180]).
- The time shown in the statistics is one hour less than the current time ([#6296]).
- Issues with QUIC and HTTP/3 upstreams on FreeBSD ([#6301]).
- Panic on clearing the query log ([#6304]).
[#684]: https://github.com/AdguardTeam/AdGuardHome/issues/684
[#6180]: https://github.com/AdguardTeam/AdGuardHome/issues/6180
[#6296]: https://github.com/AdguardTeam/AdGuardHome/issues/6296
[#6301]: https://github.com/AdguardTeam/AdGuardHome/issues/6301
[#6304]: https://github.com/AdguardTeam/AdGuardHome/issues/6304
[ms-v0.107.40]: https://github.com/AdguardTeam/AdGuardHome/milestone/75?closed=1
## [v0.107.39] - 2023-10-11
See also the [v0.107.39 GitHub milestone][ms-v0.107.39].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-39323 and CVE-2023-39325 Go vulnerabilities fixed in [Go 1.20.9][go-1.20.9] and [Go 1.20.10][go-1.20.10].
### Added
- Ability to edit static leases on *DHCP settings* page ([#1700]).
- Ability to specify for how long clients should cache a filtered response, using the *Blocked response TTL* field on the *DNS settings* page ([#4569]).
### Changed
- `ipset` entries are updated more frequently ([#6233]).
- Node.JS 16 is now required to build the frontend.
### Fixed
- Incorrect domain-specific upstream matching for `DS` queries ([#6156]).
- Improper validation of password length ([#6280]).
- Wrong algorithm for filtering self addresses from the list of private upstream DNS servers ([#6231]).
- An accidental change in DNS rewrite priority ([#6226]).
[#1700]: https://github.com/AdguardTeam/AdGuardHome/issues/1700
[#4569]: https://github.com/AdguardTeam/AdGuardHome/issues/4569
[#6156]: https://github.com/AdguardTeam/AdGuardHome/issues/6156
[#6226]: https://github.com/AdguardTeam/AdGuardHome/issues/6226
[#6231]: https://github.com/AdguardTeam/AdGuardHome/issues/6231
[#6233]: https://github.com/AdguardTeam/AdGuardHome/issues/6233
[#6280]: https://github.com/AdguardTeam/AdGuardHome/issues/6280
[go-1.20.10]: https://groups.google.com/g/golang-announce/c/iNNxDTCjZvo/m/UDd7VKQuAAAJ
[go-1.20.9]: https://groups.google.com/g/golang-announce/c/XBa1oHDevAo/m/desYyx3qAgAJ
[ms-v0.107.39]: https://github.com/AdguardTeam/AdGuardHome/milestone/74?closed=1
## [v0.107.38] - 2023-09-11
See also the [v0.107.38 GitHub milestone][ms-v0.107.38].
### Fixed
- Incorrect original answer when a response is filtered ([#6183]).
- Comments in the *Fallback DNS servers* field in the UI ([#6182]).
- Empty or default Safe Browsing and Parental Control settings ([#6181]).
- Various UI issues.
[#6181]: https://github.com/AdguardTeam/AdGuardHome/issues/6181
[#6182]: https://github.com/AdguardTeam/AdGuardHome/issues/6182
[#6183]: https://github.com/AdguardTeam/AdGuardHome/issues/6183
[ms-v0.107.38]: https://github.com/AdguardTeam/AdGuardHome/milestone/73?closed=1
## [v0.107.37] - 2023-09-07
See also the [v0.107.37 GitHub milestone][ms-v0.107.37].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-39318, CVE-2023-39319, and CVE-2023-39320 Go vulnerabilities fixed in [Go 1.20.8][go-1.20.8].
### Added
- AdBlock-style syntax support for ignored domains in logs and statistics ([#5720]).
- [`Strict-Transport-Security`][hsts] header in the HTTP API and DNS-over-HTTPS responses when HTTPS is forced ([#2998]). See [RFC 6797][rfc6797].
- UI for the schedule of the service-blocking pause ([#951]).
- IPv6 hints are now filtered in case IPv6 addresses resolving is disabled ([#6122]).
- The ability to set fallback DNS servers in the configuration file and the UI ([#3701]).
- While adding or updating blocklists, the title can now be parsed from `! Title:` definition of the blocklist’s source ([#6020]).
- The ability to filter DNS HTTPS records including IPv4 and IPv6 hints ([#6053]).
- Two new metrics showing total number of responses from each upstream DNS server and their average processing time in the Web UI ([#1453]).
- The ability to set the port for the `pprof` debug API, see configuration changes below.
### Changed
- `$dnsrewrite` rules containing IPv4-mapped IPv6 addresses are now working consistently with legacy DNS rewrites and match the `AAAA` requests.
- For non-A and non-AAAA requests, which has been filtered, the NODATA response is returned if the blocking mode isn’t set to `Null IP`. In previous versions it returned NXDOMAIN response in such cases.
#### Configuration changes
In this release, the schema version has changed from 24 to 27.
- Ignore rules blocking `.` in `querylog.ignored` and `statistics.ignored` have been migrated to AdBlock syntax (`|.^`). To rollback this change, restore the rules and change the `schema_version` back to `26`.
- Filtering-related settings have been moved from `dns` section of the YAML configuration file to the new section `filtering`:
```yaml
# BEFORE:
'dns':
'filtering_enabled': true
'filters_update_interval': 24
'parental_enabled': false
'safebrowsing_enabled': false
'safebrowsing_cache_size': 1048576
'safesearch_cache_size': 1048576
'parental_cache_size': 1048576
'safe_search':
'enabled': false
'bing': true
'duckduckgo': true
'google': true
'pixabay': true
'yandex': true
'youtube': true
'rewrites': []
'blocked_services':
'schedule':
'time_zone': 'Local'
'ids': []
'protection_enabled': true,
'blocking_mode': 'custom_ip',
'blocking_ipv4': '1.2.3.4',
'blocking_ipv6': '1:2:3::4',
'blocked_response_ttl': 10,
'protection_disabled_until': 'null',
'parental_block_host': 'p.dns.adguard.com',
'safebrowsing_block_host': 's.dns.adguard.com'
# AFTER:
'filtering':
'filtering_enabled': true
'filters_update_interval': 24
'parental_enabled': false
'safebrowsing_enabled': false
'safebrowsing_cache_size': 1048576
'safesearch_cache_size': 1048576
'parental_cache_size': 1048576
'safe_search':
'enabled': false
'bing': true
'duckduckgo': true
'google': true
'pixabay': true
'yandex': true
'youtube': true
'rewrites': []
'blocked_services':
'schedule':
'time_zone': 'Local'
'ids': []
'protection_enabled': true,
'blocking_mode': 'custom_ip',
'blocking_ipv4': '1.2.3.4',
'blocking_ipv6': '1:2:3::4',
'blocked_response_ttl': 10,
'protection_disabled_until': 'null',
'parental_block_host': 'p.dns.adguard.com',
'safebrowsing_block_host': 's.dns.adguard.com',
```
To rollback this change, remove the new object `filtering`, set back filtering properties in `dns` section, and change the `schema_version` back to `25`.
- Property `debug_pprof` which used to setup profiling HTTP handler, is now moved to the new `pprof` object under `http` section. The new object contains properties `enabled` and `port`:
```yaml
# BEFORE:
'debug_pprof': true
# AFTER:
'http':
'pprof':
'enabled': true
'port': 6060
```
Note that the new default `6060` is used as default. To rollback this change, remove the new object `pprof`, set back `debug_pprof`, and change the `schema_version` back to `24`.
### Fixed
- Incorrect display date on statistics graph ([#5793]).
- Missing query log entries and statistics on service restart ([#6100]).
- Occasional DNS-over-QUIC and DNS-over-HTTP/3 errors ([#6133]).
- Legacy DNS rewrites containing IPv4-mapped IPv6 addresses are now matching the `AAAA` requests, not `A` ([#6050]).
- File log configuration, such as `max_size`, being ignored ([#6093]).
- Panic on using a single-slash filtering rule.
- Panic on shutting down while DNS requests are in process of filtering ([#5948]).
[#1453]: https://github.com/AdguardTeam/AdGuardHome/issues/1453
[#2998]: https://github.com/AdguardTeam/AdGuardHome/issues/2998
[#3701]: https://github.com/AdguardTeam/AdGuardHome/issues/3701
[#5720]: https://github.com/AdguardTeam/AdGuardHome/issues/5720
[#5793]: https://github.com/AdguardTeam/AdGuardHome/issues/5793
[#5948]: https://github.com/AdguardTeam/AdGuardHome/issues/5948
[#6020]: https://github.com/AdguardTeam/AdGuardHome/issues/6020
[#6050]: https://github.com/AdguardTeam/AdGuardHome/issues/6050
[#6053]: https://github.com/AdguardTeam/AdGuardHome/issues/6053
[#6093]: https://github.com/AdguardTeam/AdGuardHome/issues/6093
[#6100]: https://github.com/AdguardTeam/AdGuardHome/issues/6100
[#6122]: https://github.com/AdguardTeam/AdGuardHome/issues/6122
[#6133]: https://github.com/AdguardTeam/AdGuardHome/issues/6133
[go-1.20.8]: https://groups.google.com/g/golang-announce/c/Fm51GRLNRvM/m/F5bwBlXMAQAJ
[hsts]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
[ms-v0.107.37]: https://github.com/AdguardTeam/AdGuardHome/milestone/72?closed=1
[rfc6797]: https://datatracker.ietf.org/doc/html/rfc6797
## [v0.107.36] - 2023-08-02
See also the [v0.107.36 GitHub milestone][ms-v0.107.36].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-29409 Go vulnerability fixed in [Go 1.20.7][go-1.20.7].
### Deprecated
- Go 1.20 support. Future versions will require at least Go 1.21 to build.
### Fixed
- Inability to block queries for the root domain, such as `NS .` queries, using the *Disallowed domains* feature on the *DNS settings* page ([#6049]). Users who want to block `.` queries should use the `|.^` AdBlock rule or a similar regular expression.
- Client hostnames not resolving when upstream server responds with zero-TTL records ([#6046]).
### Removed
- Go 1.19 support, as it has reached end of life.
[#6046]: https://github.com/AdguardTeam/AdGuardHome/issues/6046
[#6049]: https://github.com/AdguardTeam/AdGuardHome/issues/6049
[go-1.20.7]: https://groups.google.com/g/golang-announce/c/X0b6CsSAaYI/m/Efv5DbZ9AwAJ
[ms-v0.107.36]: https://github.com/AdguardTeam/AdGuardHome/milestone/71?closed=1
## [v0.107.35] - 2023-07-26
See also the [v0.107.35 GitHub milestone][ms-v0.107.35].
### Changed
- Improved reliability filtering-rule list updates on Unix systems.
### Fixed
- Occasional client information lookup failures that could lead to the DNS server getting stuck ([#6006]).
- `bufio.Scanner: token too long` and other errors when trying to add filtering-rule lists with lines over 1024 bytes long or containing cosmetic rules ([#6003]).
### Removed
- Default exposure of the non-standard ports 784 and 8853 for DNS-over-QUIC in the `Dockerfile`.
[#6003]: https://github.com/AdguardTeam/AdGuardHome/issues/6003
[#6006]: https://github.com/AdguardTeam/AdGuardHome/issues/6006
[ms-v0.107.35]: https://github.com/AdguardTeam/AdGuardHome/milestone/70?closed=1
## [v0.107.34] - 2023-07-12
See also the [v0.107.34 GitHub milestone][ms-v0.107.34].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-29406 Go vulnerability fixed in [Go 1.19.11][go-1.19.11].
### Added
- Ability to ignore queries for the root domain, such as `NS .` queries ([#5990]).
### Changed
- Improved CPU and RAM consumption during updates of filtering-rule lists.
#### Configuration changes
In this release, the schema version has changed from 23 to 24.
- Properties starting with `log_`, and `verbose` property, which used to set up logging are now moved to the new object `log` containing new properties `file`, `max_backups`, `max_size`, `max_age`, `compress`, `local_time`, and `verbose`:
```yaml
# BEFORE:
'log_file': ""
'log_max_backups': 0
'log_max_size': 100
'log_max_age': 3
'log_compress': false
'log_localtime': false
'verbose': false
# AFTER:
'log':
'file': ""
'max_backups': 0
'max_size': 100
'max_age': 3
'compress': false
'local_time': false
'verbose': false
```
To rollback this change, remove the new object `log`, set back `log_` and `verbose` properties and change the `schema_version` back to `23`.
### Deprecated
- Default exposure of the non-standard ports 784 and 8853 for DNS-over-QUIC in the `Dockerfile`.
### Fixed
- Two unspecified IPs when a host is blocked in two filter lists ([#5972]).
- Incorrect setting of Parental Control cache size.
- Excessive RAM and CPU consumption by Safe Browsing and Parental Control filters ([#5896]).
### Removed
- The `HEALTHCHECK` section and the use of `tini` in the `ENTRYPOINT` section in `Dockerfile` ([#5939]). They caused a lot of issues, especially with tools like `docker-compose` and `podman`.
**NOTE:** Some Docker tools may cache `ENTRYPOINT` sections, so some users may be required to backup their configuration, stop the container, purge the old image, and reload it from scratch.
[#5896]: https://github.com/AdguardTeam/AdGuardHome/issues/5896
[#5972]: https://github.com/AdguardTeam/AdGuardHome/issues/5972
[#5990]: https://github.com/AdguardTeam/AdGuardHome/issues/5990
[go-1.19.11]: https://groups.google.com/g/golang-announce/c/2q13H6LEEx0/m/sduSepLLBwAJ
[ms-v0.107.34]: https://github.com/AdguardTeam/AdGuardHome/milestone/69?closed=1
## [v0.107.33] - 2023-07-03
See also the [v0.107.33 GitHub milestone][ms-v0.107.33].
### Added
- The new command-line flag `--web-addr` is the address to serve the web UI on, in the host:port format.
- The ability to set inactivity periods for filtering blocked services, both globally and per client, in the configuration file ([#951]). The UI changes are coming in the upcoming releases.
- The ability to edit rewrite rules via `PUT /control/rewrite/update` HTTP API and the Web UI ([#1577]).
### Changed
#### Configuration changes
In this release, the schema version has changed from 20 to 23.
- Properties `bind_host`, `bind_port`, and `web_session_ttl` which used to setup web UI binding configuration, are now moved to a new object `http` containing new properties `address` and `session_ttl`:
```yaml
# BEFORE:
'bind_host': '1.2.3.4'
'bind_port': 8080
'web_session_ttl': 720
# AFTER:
'http':
'address': '1.2.3.4:8080'
'session_ttl': '720h'
```
Note that the new `http.session_ttl` property is now a duration string. To rollback this change, remove the new object `http`, set back `bind_host`, `bind_port`, `web_session_ttl`, and change the `schema_version` back to `22`.
- Property `clients.persistent.blocked_services`, which in schema versions 21 and earlier used to be a list containing ids of blocked services, is now an object containing ids and schedule for blocked services:
```yaml
# BEFORE:
'clients':
'persistent':
- 'name': 'client-name'
'blocked_services':
- id_1
- id_2
# AFTER:
'clients':
'persistent':
- 'name': client-name
'blocked_services':
'ids':
- id_1
- id_2
'schedule':
'time_zone': 'Local'
'sun':
'start': '0s'
'end': '24h'
'mon':
'start': '1h'
'end': '23h'
```
To rollback this change, replace `clients.persistent.blocked_services` object with the list of ids of blocked services and change the `schema_version` back to `21`.
- Property `dns.blocked_services`, which in schema versions 20 and earlier used to be a list containing ids of blocked services, is now an object containing ids and schedule for blocked services:
```yaml
# BEFORE:
'blocked_services':
- id_1
- id_2
# AFTER:
'blocked_services':
'ids':
- id_1
- id_2
'schedule':
'time_zone': 'Local'
'sun':
'start': '0s'
'end': '24h'
'mon':
'start': '10m'
'end': '23h30m'
'tue':
'start': '20m'
'end': '23h'
'wed':
'start': '30m'
'end': '22h30m'
'thu':
'start': '40m'
'end': '22h'
'fri':
'start': '50m'
'end': '21h30m'
'sat':
'start': '1h'
'end': '21h'
```
To rollback this change, replace `dns.blocked_services` object with the list of ids of blocked services and change the `schema_version` back to `20`.
### Deprecated
- The `HEALTHCHECK` section and the use of `tini` in the `ENTRYPOINT` section in `Dockerfile` ([#5939]). They cause a lot of issues, especially with tools like `docker-compose` and `podman`, and will be removed in a future release.
- Flags `-h`, `--host`, `-p`, `--port` have been deprecated. The `-h` flag will work as an alias for `--help`, instead of the deprecated `--host` in the future releases.
### Fixed
- Ignoring of `/etc/hosts` file when resolving the hostnames of upstream DNS servers ([#5902]).
- Excessive error logging when using DNS-over-QUIC ([#5285]).
- Inability to set `bind_host` in `AdGuardHome.yaml` in Docker ([#4231], [#4235]).
- The blocklists can now be deleted properly ([#5700]).
- Queries with the question-section target `.`, for example `NS .`, are now counted in the statistics and correctly shown in the query log ([#5910]).
- Safe Search not working with `AAAA` queries for domains that don’t have `AAAA` records ([#5913]).
[#951]: https://github.com/AdguardTeam/AdGuardHome/issues/951
[#1577]: https://github.com/AdguardTeam/AdGuardHome/issues/1577
[#4231]: https://github.com/AdguardTeam/AdGuardHome/issues/4231
[#4235]: https://github.com/AdguardTeam/AdGuardHome/pull/4235
[#5285]: https://github.com/AdguardTeam/AdGuardHome/issues/5285
[#5700]: https://github.com/AdguardTeam/AdGuardHome/issues/5700
[#5902]: https://github.com/AdguardTeam/AdGuardHome/issues/5902
[#5910]: https://github.com/AdguardTeam/AdGuardHome/issues/5910
[#5913]: https://github.com/AdguardTeam/AdGuardHome/issues/5913
[#5939]: https://github.com/AdguardTeam/AdGuardHome/discussions/5939
[ms-v0.107.33]: https://github.com/AdguardTeam/AdGuardHome/milestone/68?closed=1
## [v0.107.32] - 2023-06-13
### Fixed
- DNSCrypt upstream not resetting the client and resolver information on dialing errors ([#5872]).
## [v0.107.31] - 2023-06-08
See also the [v0.107.31 GitHub milestone][ms-v0.107.31].
### Fixed
- Startup errors on OpenWrt ([#5872]).
- Plain-UDP upstreams always falling back to TCP, causing outages and slowdowns ([#5873], [#5874]).
[#5872]: https://github.com/AdguardTeam/AdGuardHome/issues/5872
[#5873]: https://github.com/AdguardTeam/AdGuardHome/issues/5873
[#5874]: https://github.com/AdguardTeam/AdGuardHome/issues/5874
[ms-v0.107.31]: https://github.com/AdguardTeam/AdGuardHome/milestone/67?closed=1
## [v0.107.30] - 2023-06-07
See also the [v0.107.30 GitHub milestone][ms-v0.107.30].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-29402, CVE-2023-29403, and CVE-2023-29404 Go vulnerabilities fixed in [Go 1.19.10][go-1.19.10].
### Fixed
- Unquoted IPv6 bind hosts with trailing colons erroneously considered unspecified addresses are now properly validated ([#5752]).
**NOTE:** the Docker healthcheck script now also doesn’t interpret the `""` value as unspecified address.
- Incorrect `Content-Type` header value in `POST /control/version.json` and `GET /control/dhcp/interfaces` HTTP APIs ([#5716]).
- Provided bootstrap servers are now used to resolve the hostnames of plain UDP/TCP upstream servers.
[#5716]: https://github.com/AdguardTeam/AdGuardHome/issues/5716
[go-1.19.10]: https://groups.google.com/g/golang-announce/c/q5135a9d924/m/j0ZoAJOHAwAJ
[ms-v0.107.30]: https://github.com/AdguardTeam/AdGuardHome/milestone/66?closed=1
## [v0.107.29] - 2023-04-18
See also the [v0.107.29 GitHub milestone][ms-v0.107.29].
### Added
- The ability to exclude client activity from the query log or statistics by editing client’s settings on the respective page in the UI ([#1717], [#4299]).
### Changed
- Stored DHCP leases moved from `leases.db` to `data/leases.json`. The file format has also been optimized.
### Fixed
- The `github.com/mdlayher/raw` dependency has been temporarily returned to support raw connections on Darwin ([#5712]).
- Incorrect recording of blocked results as “Blocked by CNAME or IP” in the query log ([#5725]).
- All Safe Search services being unchecked by default.
- Panic when a DNSCrypt stamp is invalid ([#5721]).
[#5712]: https://github.com/AdguardTeam/AdGuardHome/issues/5712
[#5721]: https://github.com/AdguardTeam/AdGuardHome/issues/5721
[#5725]: https://github.com/AdguardTeam/AdGuardHome/issues/5725
[#5752]: https://github.com/AdguardTeam/AdGuardHome/issues/5752
[ms-v0.107.29]: https://github.com/AdguardTeam/AdGuardHome/milestone/65?closed=1
## [v0.107.28] - 2023-04-12
See also the [v0.107.28 GitHub milestone][ms-v0.107.28].
### Added
- The ability to exclude client activity from the query log or statistics by using the new properties `ignore_querylog` and `ignore_statistics` of the items of the `clients.persistent` array ([#1717], [#4299]). The UI changes are coming in the upcoming releases.
- Better profiling information when `debug_pprof` is set to `true`.
- IPv6 support in Safe Search for some services.
- The ability to make bootstrap DNS lookups prefer IPv6 addresses to IPv4 ones using the new `dns.bootstrap_prefer_ipv6` configuration file property ([#4262]).
- Docker container’s healthcheck ([#3290]).
- The new HTTP API `POST /control/protection`, that updates protection state and adds an optional pause duration ([#1333]). The format of request body is described in `openapi/openapi.yaml`. The duration of this pause could also be set with the property `protection_disabled_until` in the `dns` object of the YAML configuration file.
- The ability to create a static DHCP lease from a dynamic one more easily ([#3459]).
- Two new HTTP APIs, `PUT /control/stats/config/update` and `GET control/stats/config`, which can be used to set and receive the query log configuration. See `openapi/openapi.yaml` for the full description.
- Two new HTTP APIs, `PUT /control/querylog/config/update` and `GET control/querylog/config`, which can be used to set and receive the statistics configuration. See `openapi/openapi.yaml` for the full description.
- The ability to set custom IP for EDNS Client Subnet by using the DNS-server configuration section on the DNS settings page in the UI ([#1472]).
- The ability to manage Safe Search for each service by using the new `safe_search` property ([#1163]).
### Changed
- ARPA domain names containing a subnet within private networks now also considered private, behaving closer to [RFC 6761][rfc6761] ([#5567]).
#### Configuration changes
In this release, the schema version has changed from 17 to 20.
- Property `statistics.interval`, which in schema versions 19 and earlier used to be an integer number of days, is now a string with a human-readable duration:
```yaml
# BEFORE:
'statistics':
# …
'interval': 1
# AFTER:
'statistics':
# …
'interval': '24h'
```
To rollback this change, convert the property back into days and change the `schema_version` back to `19`.
- The `dns.safesearch_enabled` property has been replaced with `safe_search` object containing per-service settings.
- The `clients.persistent.safesearch_enabled` property has been replaced with `safe_search` object containing per-service settings.
```yaml
# BEFORE:
'safesearch_enabled': true
# AFTER:
'safe_search':
'enabled': true
'bing': true
'duckduckgo': true
'google': true
'pixabay': true
'yandex': true
'youtube': true
```
To rollback this change, move the value of `dns.safe_search.enabled` into the `dns.safesearch_enabled`, then remove `dns.safe_search` property. Do the same client’s specific `clients.persistent.safesearch` and then change the `schema_version` back to `17`.
### Deprecated
- The `POST /control/safesearch/enable` HTTP API is deprecated. Use the new `PUT /control/safesearch/settings` API.
- The `POST /control/safesearch/disable` HTTP API is deprecated. Use the new `PUT /control/safesearch/settings` API
- The `safesearch_enabled` property is deprecated in the following HTTP APIs:
- `GET /control/clients`;
- `POST /control/clients/add`;
- `POST /control/clients/update`;
- `GET /control/clients/find?ip0=...&ip1=...&ip2=...`.
Check `openapi/openapi.yaml` for more details.
- The `GET /control/stats_info` HTTP API; use the new `GET /control/stats/config` API instead.
**NOTE:** If interval is custom then it will be equal to `90` days for compatibility reasons. See `openapi/openapi.yaml` and `openapi/CHANGELOG.md`.
- The `POST /control/stats_config` HTTP API; use the new `PUT /control/stats/config/update` API instead.
- The `GET /control/querylog_info` HTTP API; use the new `GET /control/querylog/config` API instead.
**NOTE:** If interval is custom then it will be equal to `90` days for compatibility reasons. See `openapi/openapi.yaml` and `openapi/CHANGELOG.md`.
- The `POST /control/querylog_config` HTTP API; use the new `PUT /control/querylog/config/update` API instead.
### Fixed
- Logging of the client’s IP address after failed login attempts ([#5701]).
[#1163]: https://github.com/AdguardTeam/AdGuardHome/issues/1163
[#1333]: https://github.com/AdguardTeam/AdGuardHome/issues/1333
[#1472]: https://github.com/AdguardTeam/AdGuardHome/issues/1472
[#3290]: https://github.com/AdguardTeam/AdGuardHome/issues/3290
[#3459]: https://github.com/AdguardTeam/AdGuardHome/issues/3459
[#4262]: https://github.com/AdguardTeam/AdGuardHome/issues/4262
[#5567]: https://github.com/AdguardTeam/AdGuardHome/issues/5567
[#5701]: https://github.com/AdguardTeam/AdGuardHome/issues/5701
[ms-v0.107.28]: https://github.com/AdguardTeam/AdGuardHome/milestone/64?closed=1
[rfc6761]: https://datatracker.ietf.org/doc/html/rfc6761
## [v0.107.27] - 2023-04-05
See also the [v0.107.27 GitHub milestone][ms-v0.107.27].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-24534, CVE-2023-24536, CVE-2023-24537, and CVE-2023-24538 Go vulnerabilities fixed in [Go 1.19.8][go-1.19.8].
### Fixed
- Query log not showing all filtered queries when the “Filtered” log filter is selected ([#5639]).
- Panic in empty hostname in the filter’s URL ([#5631]).
- Panic caused by empty top-level domain name label in `/etc/hosts` files ([#5584]).
[#5584]: https://github.com/AdguardTeam/AdGuardHome/issues/5584
[#5631]: https://github.com/AdguardTeam/AdGuardHome/issues/5631
[#5639]: https://github.com/AdguardTeam/AdGuardHome/issues/5639
[go-1.19.8]: https://groups.google.com/g/golang-announce/c/Xdv6JL9ENs8/m/OV40vnafAwAJ
[ms-v0.107.27]: https://github.com/AdguardTeam/AdGuardHome/milestone/63?closed=1
## [v0.107.26] - 2023-03-09
See also the [v0.107.26 GitHub milestone][ms-v0.107.26].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2023-24532 Go vulnerability fixed in [Go 1.19.7][go-1.19.7].
### Added
- The ability to set custom IP for EDNS Client Subnet by using the new `dns.edns_client_subnet.use_custom` and `dns.edns_client_subnet.custom_ip` properties ([#1472]). The UI changes are coming in the upcoming releases.
- The ability to use `dnstype` rules in the disallowed domains list ([#5468]). This allows dropping requests based on their question types.
### Changed
#### Configuration changes
- Property `edns_client_subnet`, which in schema versions 16 and earlier used to be a part of the `dns` object, is now part of the `dns.edns_client_subnet` object:
```yaml
# BEFORE:
'dns':
# …
'edns_client_subnet': false
# AFTER:
'dns':
# …
'edns_client_subnet':
'enabled': false
'use_custom': false
'custom_ip': ''
```
To rollback this change, move the value of `dns.edns_client_subnet.enabled` into the `dns.edns_client_subnet`, remove the properties `dns.edns_client_subnet.enabled`, `dns.edns_client_subnet.use_custom`, `dns.edns_client_subnet.custom_ip`, and change the `schema_version` back to `16`.
### Fixed
- Obsolete value of the Interface MTU DHCP option is now omitted ([#5281]).
- Various dark theme bugs ([#5439], [#5441], [#5442], [#5515]).
- Automatic update on MIPS64 and little-endian 32-bit MIPS architectures ([#5270], [#5373]).
- Requirements to domain names in domain-specific upstream configurations have been relaxed to meet those from [RFC 3696][rfc3696] ([#4884]).
- Failing service installation via script on FreeBSD ([#5431]).
[#4884]: https://github.com/AdguardTeam/AdGuardHome/issues/4884
[#5270]: https://github.com/AdguardTeam/AdGuardHome/issues/5270
[#5281]: https://github.com/AdguardTeam/AdGuardHome/issues/5281
[#5373]: https://github.com/AdguardTeam/AdGuardHome/issues/5373
[#5431]: https://github.com/AdguardTeam/AdGuardHome/issues/5431
[#5439]: https://github.com/AdguardTeam/AdGuardHome/issues/5439
[#5441]: https://github.com/AdguardTeam/AdGuardHome/issues/5441
[#5442]: https://github.com/AdguardTeam/AdGuardHome/issues/5442
[#5468]: https://github.com/AdguardTeam/AdGuardHome/issues/5468
[#5515]: https://github.com/AdguardTeam/AdGuardHome/issues/5515
[go-1.19.7]: https://groups.google.com/g/golang-announce/c/3-TpUx48iQY
[ms-v0.107.26]: https://github.com/AdguardTeam/AdGuardHome/milestone/62?closed=1
[rfc3696]: https://datatracker.ietf.org/doc/html/rfc3696
## [v0.107.25] - 2023-02-21
See also the [v0.107.25 GitHub milestone][ms-v0.107.25].
### Fixed
- Panic when using unencrypted DNS-over-HTTPS ([#5518]).
[#5518]: https://github.com/AdguardTeam/AdGuardHome/issues/5518
[ms-v0.107.25]: https://github.com/AdguardTeam/AdGuardHome/milestone/61?closed=1
## [v0.107.24] - 2023-02-15
See also the [v0.107.24 GitHub milestone][ms-v0.107.24].
### Security
- Go version has been updated, both because Go 1.18 has reached end of life an to prevent the possibility of exploiting the Go vulnerabilities fixed in [Go 1.19.6][go-1.19.6].
### Added
- The ability to disable statistics by using the new `statistics.enabled` property. Previously it was necessary to set the `statistics_interval` to 0, losing the previous value ([#1717], [#4299]).
- The ability to exclude domain names from the query log or statistics by using the new `querylog.ignored` or `statistics.ignored` properties ([#1717], [#4299]). The UI changes are coming in the upcoming releases.
### Changed
#### Configuration changes
In this release, the schema version has changed from 14 to 16.
- Property `statistics_interval`, which in schema versions 15 and earlier used to be a part of the `dns` object, is now a part of the `statistics` object:
```yaml
# BEFORE:
'dns':
# …
'statistics_interval': 1
# AFTER:
'statistics':
# …
'interval': 1
```
To rollback this change, move the property back into the `dns` object and change the `schema_version` back to `15`.
- The properties `dns.querylog_enabled`, `dns.querylog_file_enabled`, `dns.querylog_interval`, and `dns.querylog_size_memory` have been moved to the new `querylog` object.
```yaml
# BEFORE:
'dns':
'querylog_enabled': true
'querylog_file_enabled': true
'querylog_interval': '2160h'
'querylog_size_memory': 1000
# AFTER:
'querylog':
'enabled': true
'file_enabled': true
'interval': '2160h'
'size_memory': 1000
'ignored': []
```
To rollback this change, rename and move properties back into the `dns` object, remove `querylog` object and `querylog.ignored` property, and change the `schema_version` back to `14`.
### Deprecated
- Go 1.19 support. Future versions will require at least Go 1.20 to build.
### Fixed
- Setting the AD (Authenticated Data) flag on responses that have the DO (DNSSEC OK) flag set but not the AD flag ([#5479]).
- Client names resolved via reverse DNS not being updated ([#4939]).
- The icon for League Of Legends on the Blocked services page ([#5433]).
### Removed
- Go 1.18 support, as it has reached end of life.
[#1717]: https://github.com/AdguardTeam/AdGuardHome/issues/1717
[#4299]: https://github.com/AdguardTeam/AdGuardHome/issues/4299
[#4939]: https://github.com/AdguardTeam/AdGuardHome/issues/4939
[#5433]: https://github.com/AdguardTeam/AdGuardHome/issues/5433
[#5479]: https://github.com/AdguardTeam/AdGuardHome/issues/5479
[go-1.19.6]: https://groups.google.com/g/golang-announce/c/V0aBFqaFs_E
[ms-v0.107.24]: https://github.com/AdguardTeam/AdGuardHome/milestone/60?closed=1
## [v0.107.23] - 2023-02-01
See also the [v0.107.23 GitHub milestone][ms-v0.107.23].
### Added
- DNS64 support ([#5117]). The function may be enabled with new `use_dns64` property under `dns` object in the configuration along with `dns64_prefixes`, the set of exclusion prefixes to filter AAAA responses. The Well-Known Prefix (`64:ff9b::/96`) is used if no custom prefixes are specified.
### Fixed
- Filtering rules with `*` as the hostname not working properly ([#5245]).
- Various dark theme bugs ([#5375]).
### Removed
- The “beta frontend” and the corresponding APIs. They never quite worked properly, and the future new version of AdGuard Home API will probably be different.
Correspondingly, the configuration parameter `beta_bind_port` has been removed as well.
[#5117]: https://github.com/AdguardTeam/AdGuardHome/issues/5117
[#5245]: https://github.com/AdguardTeam/AdGuardHome/issues/5245
[#5375]: https://github.com/AdguardTeam/AdGuardHome/issues/5375
[ms-v0.107.23]: https://github.com/AdguardTeam/AdGuardHome/milestone/59?closed=1
## [v0.107.22] - 2023-01-19
See also the [v0.107.22 GitHub milestone][ms-v0.107.22].
### Added
- Experimental Dark UI theme ([#613]).
- The new HTTP API `PUT /control/profile/update`, that updates current user language and UI theme. The format of request body is described in `openapi/openapi.yaml`.
### Changed
- The HTTP API `GET /control/profile` now returns enhanced object with current user’s name, language, and UI theme. The format of response body is described in `openapi/openapi.yaml` and `openapi/CHANGELOG.md`.
### Fixed
- `AdGuardHome --update` freezing when another instance of AdGuard Home is running ([#4223], [#5191]).
- The `--update` flag performing an update even when there is no version change.
- Failing HTTPS redirection on saving the encryption settings ([#4898]).
- Zeroing rules counter of erroneously edited filtering rule lists ([#5290]).
- Filters updating strategy, which could sometimes lead to use of broken or incompletely downloaded lists ([#5258]).
[#613]: https://github.com/AdguardTeam/AdGuardHome/issues/613
[#5191]: https://github.com/AdguardTeam/AdGuardHome/issues/5191
[#5290]: https://github.com/AdguardTeam/AdGuardHome/issues/5290
[#5258]: https://github.com/AdguardTeam/AdGuardHome/issues/5258
[ms-v0.107.22]: https://github.com/AdguardTeam/AdGuardHome/milestone/58?closed=1
## [v0.107.21] - 2022-12-15
See also the [v0.107.21 GitHub milestone][ms-v0.107.21].
### Changed
- The URLs of the default filters for new installations are synchronized to those introduced in v0.107.20 ([#5238]).
**NOTE:** Some users may need to re-add the lists from the vetted filter lists to update the URLs to the new ones. Custom filters added by users themselves do not require re-adding.
### Fixed
- Errors popping up during updates of settings, which could sometimes cause the server to stop responding ([#5251]).
[#5238]: https://github.com/AdguardTeam/AdGuardHome/issues/5238
[#5251]: https://github.com/AdguardTeam/AdGuardHome/issues/5251
[ms-v0.107.21]: https://github.com/AdguardTeam/AdGuardHome/milestone/57?closed=1
## [v0.107.20] - 2022-12-07
See also the [v0.107.20 GitHub milestone][ms-v0.107.20].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2022-41717 and CVE-2022-41720 Go vulnerabilities fixed in [Go 1.18.9][go-1.18.9].
### Added
- The ability to clear the DNS cache ([#5190]).
### Changed
- DHCP server initialization errors are now logged at debug level if the server itself disabled ([#4944]).
### Fixed
- Wrong validation error messages on the DHCP configuration page ([#5208]).
- Slow upstream checks making the API unresponsive ([#5193]).
- The TLS initialization errors preventing AdGuard Home from starting ([#5189]). Instead, AdGuard Home disables encryption and shows an error message on the encryption settings page in the UI, which was the intended previous behavior.
- URLs of some vetted blocklists.
[#4944]: https://github.com/AdguardTeam/AdGuardHome/issues/4944
[#5189]: https://github.com/AdguardTeam/AdGuardHome/issues/5189
[#5190]: https://github.com/AdguardTeam/AdGuardHome/issues/5190
[#5193]: https://github.com/AdguardTeam/AdGuardHome/issues/5193
[#5208]: https://github.com/AdguardTeam/AdGuardHome/issues/5208
[go-1.18.9]: https://groups.google.com/g/golang-announce/c/L_3rmdT0BMU
[ms-v0.107.20]: https://github.com/AdguardTeam/AdGuardHome/milestone/56?closed=1
## [v0.107.19] - 2022-11-23
See also the [v0.107.19 GitHub milestone][ms-v0.107.19].
### Added
- The ability to block popular Mastodon instances ([AdguardTeam/HostlistsRegistry#100]).
- The new `--update` command-line option, which allows updating AdGuard Home silently ([#4223]).
### Changed
- Minor UI changes.
[#4223]: https://github.com/AdguardTeam/AdGuardHome/issues/4223
[ms-v0.107.19]: https://github.com/AdguardTeam/AdGuardHome/milestone/55?closed=1
[AdguardTeam/HostlistsRegistry#100]: https://github.com/AdguardTeam/HostlistsRegistry/pull/100
## [v0.107.18] - 2022-11-08
See also the [v0.107.18 GitHub milestone][ms-v0.107.18].
### Fixed
- Crash on some systems when domains from system hosts files are processed ([#5089]).
[#5089]: https://github.com/AdguardTeam/AdGuardHome/issues/5089
[ms-v0.107.18]: https://github.com/AdguardTeam/AdGuardHome/milestone/54?closed=1
## [v0.107.17] - 2022-11-02
See also the [v0.107.17 GitHub milestone][ms-v0.107.17].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2022-41716 Go vulnerability fixed in [Go 1.18.8][go-1.18.8].
### Added
- The warning message when adding a certificate having no IP addresses ([#4898]).
- Several new blockable services ([#3972]). Those will now be more in sync with the services that are already blockable in AdGuard DNS.
- A new HTTP API, `GET /control/blocked_services/all`, that lists all available blocked services and their data, such as SVG icons ([#3972]).
- The new optional `tls.override_tls_ciphers` property, which allows overriding TLS ciphers used by AdGuard Home ([#4925], [#4990]).
- The ability to serve DNS on link-local IPv6 addresses ([#2926]).
- The ability to put [ClientIDs][clientid] into DNS-over-HTTPS hostnames as opposed to URL paths ([#3418]). Note that AdGuard Home checks the server name only if the URL does not contain a ClientID.
### Changed
- DNS-over-TLS resolvers aren’t returned anymore when the configured TLS certificate contains no IP addresses ([#4927]).
- Responses with `SERVFAIL` code are now cached for at least 30 seconds.
### Deprecated
- The `GET /control/blocked_services/services` HTTP API; use the new `GET /control/blocked_services/all` API instead ([#3972]).
### Fixed
- ClientIDs not working when using DNS-over-HTTPS with HTTP/3.
- Editing the URL of an enabled rule list also includes validation of the filter contents preventing from saving a bad one ([#4916]).
- The default value of `dns.cache_size` accidentally set to 0 has now been reverted to 4 MiB ([#5010]).
- Responses for which the DNSSEC validation had explicitly been omitted aren’t cached now ([#4942]).
- Web UI not switching to HTTP/3 ([#4986], [#4993]).
[#2926]: https://github.com/AdguardTeam/AdGuardHome/issues/2926
[#3418]: https://github.com/AdguardTeam/AdGuardHome/issues/3418
[#3972]: https://github.com/AdguardTeam/AdGuardHome/issues/3972
[#4898]: https://github.com/AdguardTeam/AdGuardHome/issues/4898
[#4916]: https://github.com/AdguardTeam/AdGuardHome/issues/4916
[#4925]: https://github.com/AdguardTeam/AdGuardHome/issues/4925
[#4942]: https://github.com/AdguardTeam/AdGuardHome/issues/4942
[#4986]: https://github.com/AdguardTeam/AdGuardHome/issues/4986
[#4990]: https://github.com/AdguardTeam/AdGuardHome/issues/4990
[#4993]: https://github.com/AdguardTeam/AdGuardHome/issues/4993
[#5010]: https://github.com/AdguardTeam/AdGuardHome/issues/5010
[clientid]: https://github.com/AdguardTeam/AdGuardHome/wiki/Clients#clientid
[go-1.18.8]: https://groups.google.com/g/golang-announce/c/mbHY1UY3BaM
[ms-v0.107.17]: https://github.com/AdguardTeam/AdGuardHome/milestone/53?closed=1
## [v0.107.16] - 2022-10-07
This is a security update. There is no GitHub milestone, since no GitHub issues were resolved.
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2022-2879, CVE-2022-2880, and CVE-2022-41715 Go vulnerabilities fixed in [Go 1.18.7][go-1.18.7].
[go-1.18.7]: https://groups.google.com/g/golang-announce/c/xtuG5faxtaU
## [v0.107.15] - 2022-10-03
See also the [v0.107.15 GitHub milestone][ms-v0.107.15].
### Security
- As an additional CSRF protection measure, AdGuard Home now ensures that requests that change its state but have no body (such as `POST /control/stats_reset` requests) do not have a `Content-Type` header set on them ([#4970]).
### Added
#### Experimental HTTP/3 Support
See [#3955] and the related issues for more details. These features are still experimental and may break or change in the future.
- DNS-over-HTTP/3 DNS and web UI client request support. This feature must be explicitly enabled by setting the new property `dns.serve_http3` in the configuration file to `true`.
- DNS-over-HTTP upstreams can now upgrade to HTTP/3 if the new configuration file property `dns.use_http3_upstreams` is set to `true`.
- Upstreams with forced DNS-over-HTTP/3 and no fallback to prior HTTP versions using the `h3://` scheme.
### Fixed
- User-specific blocked services not applying correctly ([#4945], [#4982], [#4983]).
- `only application/json is allowed` errors in various APIs ([#4970]).
[#3955]: https://github.com/AdguardTeam/AdGuardHome/issues/3955
[#4945]: https://github.com/AdguardTeam/AdGuardHome/issues/4945
[#4970]: https://github.com/AdguardTeam/AdGuardHome/issues/4970
[#4982]: https://github.com/AdguardTeam/AdGuardHome/issues/4982
[#4983]: https://github.com/AdguardTeam/AdGuardHome/issues/4983
[ms-v0.107.15]: https://github.com/AdguardTeam/AdGuardHome/milestone/51?closed=1
## [v0.107.14] - 2022-09-29
See also the [v0.107.14 GitHub milestone][ms-v0.107.14].
### Security
A Cross-Site Request Forgery (CSRF) vulnerability has been discovered. We thank Daniel Elkabes from Mend.io for reporting this vulnerability to us. This is [CVE-2022-32175].
#### `SameSite` Policy
The `SameSite` policy on the AdGuard Home session cookies is now set to `Lax`. Which means that the only cross-site HTTP request for which the browser is allowed to send the session cookie is navigating to the AdGuard Home domain.
**Users are strongly advised to log out, clear browser cache, and log in again after updating.**
#### Removal Of Plain-Text APIs (BREAKING API CHANGE)
We have implemented several measures to prevent such vulnerabilities in the future, but some of these measures break backwards compatibility for the sake of better protection.
The following APIs, which previously accepted or returned `text/plain` data, now accept or return data as JSON. All new formats for the request and response bodies are documented in `openapi/openapi.yaml` and `openapi/CHANGELOG.md`.
- `GET /control/i18n/current_language`;
- `POST /control/dhcp/find_active_dhcp`;
- `POST /control/filtering/set_rules`;
- `POST /control/i18n/change_language`.
#### Stricter Content-Type Checks (BREAKING API CHANGE)
All JSON APIs that expect a body now check if the request actually has `Content-Type` set to `application/json`.
#### Other Security Changes
- Weaker cipher suites that use the CBC (cipher block chaining) mode of operation have been disabled ([#2993]).
### Added
- Support for plain (unencrypted) HTTP/2 ([#4930]). This is useful for AdGuard Home installations behind a reverse proxy.
### Fixed
- Incorrect path template in DDR responses ([#4927]).
[#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993
[#4927]: https://github.com/AdguardTeam/AdGuardHome/issues/4927
[#4930]: https://github.com/AdguardTeam/AdGuardHome/issues/4930
[CVE-2022-32175]: https://www.cvedetails.com/cve/CVE-2022-32175
[ms-v0.107.14]: https://github.com/AdguardTeam/AdGuardHome/milestone/50?closed=1
## [v0.107.13] - 2022-09-14
See also the [v0.107.13 GitHub milestone][ms-v0.107.13].
### Added
- The new optional `dns.ipset_file` property, which can be set in the configuration file. It allows loading the `ipset` list from a file, just like `dns.upstream_dns_file` does for upstream servers ([#4686]).
### Changed
- The minimum DHCP message size is reassigned back to BOOTP’s constraint of 300 bytes ([#4904]).
### Fixed
- Panic when adding a static lease within the disabled DHCP server ([#4722]).
[#4686]: https://github.com/AdguardTeam/AdGuardHome/issues/4686
[#4722]: https://github.com/AdguardTeam/AdGuardHome/issues/4722
[#4904]: https://github.com/AdguardTeam/AdGuardHome/issues/4904
[ms-v0.107.13]: https://github.com/AdguardTeam/AdGuardHome/milestone/49?closed=1
## [v0.107.12] - 2022-09-07
See also the [v0.107.12 GitHub milestone][ms-v0.107.12].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2022-27664 and CVE-2022-32190 Go vulnerabilities fixed in [Go 1.18.6][go-1.18.6].
### Added
- New `bool`, `dur`, `u8`, and `u16` DHCP options to provide more convenience on options control by setting values in a human-readable format ([#4705]). See also a [Wiki page][wiki-dhcp-opts].
- New `del` DHCP option which removes the corresponding option from server’s response ([#4337]). See also a [Wiki page][wiki-dhcp-opts].
**NOTE:** This modifier affects all the parameters in the response and not only the requested ones.
- A new HTTP API, `GET /control/blocked_services/services`, that lists all available blocked services ([#4535]).
### Changed
- The DHCP options handling is now closer to the [RFC 2131][rfc-2131] ([#4705]).
- When the DHCP server is enabled, queries for domain names under `dhcp.local_domain_name` not pointing to real DHCP client hostnames are now processed by filters ([#4865]).
- The `DHCPREQUEST` handling is now closer to the [RFC 2131][rfc-2131] ([#4863]).
- The internal DNS client, used to resolve hostnames of external clients and also during automatic updates, now respects the upstream mode settings for the main DNS client ([#4403]).
### Deprecated
- Ports 784 and 8853 for DNS-over-QUIC in Docker images. Users who still serve DoQ on these ports are encouraged to move to the standard port 853. These ports will be removed from the `EXPOSE` section of our `Dockerfile` in a future release.
- Go 1.18 support. Future versions will require at least Go 1.19 to build.
### Fixed
- The length of the DHCP server’s response is now at least 576 bytes as per [RFC 2131][rfc-2131] recommendation ([#4337]).
- Dynamic leases created with empty hostnames ([#4745]).
- Unnecessary logging of non-critical statistics errors ([#4850]).
[#4337]: https://github.com/AdguardTeam/AdGuardHome/issues/4337
[#4403]: https://github.com/AdguardTeam/AdGuardHome/issues/4403
[#4535]: https://github.com/AdguardTeam/AdGuardHome/issues/4535
[#4705]: https://github.com/AdguardTeam/AdGuardHome/issues/4705
[#4745]: https://github.com/AdguardTeam/AdGuardHome/issues/4745
[#4850]: https://github.com/AdguardTeam/AdGuardHome/issues/4850
[#4863]: https://github.com/AdguardTeam/AdGuardHome/issues/4863
[#4865]: https://github.com/AdguardTeam/AdGuardHome/issues/4865
[go-1.18.6]: https://groups.google.com/g/golang-announce/c/x49AQzIVX-s
[ms-v0.107.12]: https://github.com/AdguardTeam/AdGuardHome/milestone/48?closed=1
[rfc-2131]: https://datatracker.ietf.org/doc/html/rfc2131
[wiki-dhcp-opts]: https://github.com/adguardTeam/adGuardHome/wiki/DHCP#config-4
## [v0.107.11] - 2022-08-19
See also the [v0.107.11 GitHub milestone][ms-v0.107.11].
### Added
- Bilibili service blocking ([#4795]).
### Changed
- DNS-over-QUIC connections now use keepalive.
### Fixed
- Migrations from releases older than v0.107.7 failing ([#4846]).
[#4795]: https://github.com/AdguardTeam/AdGuardHome/issues/4795
[#4846]: https://github.com/AdguardTeam/AdGuardHome/issues/4846
[ms-v0.107.11]: https://github.com/AdguardTeam/AdGuardHome/milestone/47?closed=1
## [v0.107.10] - 2022-08-17
See also the [v0.107.10 GitHub milestone][ms-v0.107.10].
### Added
- Arabic localization.
- Support for Discovery of Designated Resolvers (DDR) according to the [RFC draft][ddr-draft] ([#4463]).
### Changed
- Our snap package now uses the `core22` image as its base ([#4843]).
### Fixed
- DHCP not working on most OSes ([#4836]).
- `invalid argument` errors during update checks on older Linux kernels ([#4670]).
- Data races and concurrent map access in statistics module ([#4358], [#4342]).
[#4342]: https://github.com/AdguardTeam/AdGuardHome/issues/4342
[#4358]: https://github.com/AdguardTeam/AdGuardHome/issues/4358
[#4670]: https://github.com/AdguardTeam/AdGuardHome/issues/4670
[#4843]: https://github.com/AdguardTeam/AdGuardHome/issues/4843
[ddr-draft]: https://datatracker.ietf.org/doc/html/draft-ietf-add-ddr-08
[ms-v0.107.10]: https://github.com/AdguardTeam/AdGuardHome/milestone/46?closed=1
## [v0.107.9] - 2022-08-03
See also the [v0.107.9 GitHub milestone][ms-v0.107.9].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2022-32189 Go vulnerability fixed in [Go 1.18.5][go-1.18.5]. Go 1.17 support has also been removed, as it has reached end of life and will not receive security updates.
### Added
- Domain-specific upstream servers test. If such test fails, a warning message is shown ([#4517]).
- `windows/arm64` support ([#3057]).
### Changed
- UI and update links have been changed to make them more resistant to DNS blocking.
### Fixed
- DHCP not working on most OSes ([#4836]).
- Several UI issues ([#4775], [#4776], [#4782]).
### Removed
- Go 1.17 support, as it has reached end of life.
[#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057
[#4517]: https://github.com/AdguardTeam/AdGuardHome/issues/4517
[#4775]: https://github.com/AdguardTeam/AdGuardHome/issues/4775
[#4776]: https://github.com/AdguardTeam/AdGuardHome/issues/4776
[#4782]: https://github.com/AdguardTeam/AdGuardHome/issues/4782
[#4836]: https://github.com/AdguardTeam/AdGuardHome/issues/4836
[go-1.18.5]: https://groups.google.com/g/golang-announce/c/YqYYG87xB10
[ms-v0.107.9]: https://github.com/AdguardTeam/AdGuardHome/milestone/45?closed=1
## [v0.107.8] - 2022-07-13
See also the [v0.107.8 GitHub milestone][ms-v0.107.8].
### Security
- Go version has been updated to prevent the possibility of exploiting the CVE-2022-1705, CVE-2022-32148, CVE-2022-30631, and other Go vulnerabilities fixed in [Go 1.17.12][go-1.17.12].
### Fixed
- DHCP lease validation incorrectly letting users assign the IP address of the gateway as the address of the lease ([#4698]).
- Updater no longer expects a hardcoded name for `AdGuardHome` executable ([#4219]).
- Inconsistent names of runtime clients from hosts files ([#4683]).
- PTR requests for addresses leased by DHCP will now be resolved into hostnames under `dhcp.local_domain_name` ([#4699]).
- Broken service installation on OpenWrt ([#4677]).
[#4219]: https://github.com/AdguardTeam/AdGuardHome/issues/4219
[#4677]: https://github.com/AdguardTeam/AdGuardHome/issues/4677
[#4683]: https://github.com/AdguardTeam/AdGuardHome/issues/4683
[#4698]: https://github.com/AdguardTeam/AdGuardHome/issues/4698
[#4699]: https://github.com/AdguardTeam/AdGuardHome/issues/4699
[go-1.17.12]: https://groups.google.com/g/golang-announce/c/nqrv9fbR0zE
[ms-v0.107.8]: https://github.com/AdguardTeam/AdGuardHome/milestone/44?closed=1
## [v0.107.7] - 2022-06-06
See also the [v0.107.7 GitHub milestone][ms-v0.107.7].
### Security
- Go version has been updated to prevent the possibility of exploiting the [CVE-2022-29526], [CVE-2022-30634], [CVE-2022-30629], [CVE-2022-30580], and [CVE-2022-29804] Go vulnerabilities.
- Enforced password strength policy ([#3503]).
### Added
- Support for the final DNS-over-QUIC standard, [RFC 9250][rfc-9250] ([#4592]).
- Support upstreams for subdomains of a domain only ([#4503]).
- The ability to control each source of runtime clients separately via `clients.runtime_sources` configuration object ([#3020]).
- The ability to customize the set of networks that are considered private through the new `dns.private_networks` property in the configuration file ([#3142]).
- EDNS Client-Subnet information in the request details section of a query log record ([#3978]).
- Support for hostnames for plain UDP upstream servers using the `udp://` scheme ([#4166]).
- Logs are now collected by default on FreeBSD and OpenBSD when AdGuard Home is installed as a service ([#4213]).
### Changed
- On OpenBSD, the daemon script now uses the recommended `/bin/ksh` shell instead of the `/bin/sh` one ([#4533]). To apply this change, backup your data and run `AdGuardHome -s uninstall && AdGuardHome -s install`.
- The default DNS-over-QUIC port number is now `853` instead of `754` in accordance with [RFC 9250][rfc-9250] ([#4276]).
- Reverse DNS now has a greater priority as the source of runtime clients’ information than ARP neighborhood.
- Improved detection of runtime clients through more resilient ARP processing ([#3597]).
- The TTL of responses served from the optimistic cache is now lowered to 10 seconds.
- Domain-specific private reverse DNS upstream servers are now validated to allow only `*.in-addr.arpa` and `*.ip6.arpa` domains pointing to locally-served networks ([#3381]).
**NOTE:** If you already have invalid entries in your configuration, consider removing them manually, since they essentially had no effect.
- Response filtering is now performed using the record types of the answer section of messages as opposed to the type of the question ([#4238]).
- Instead of adding the build time information, the build scripts now use the standardized environment variable [`SOURCE_DATE_EPOCH`][repr] to add the date of the commit from which the binary was built ([#4221]). This should simplify reproducible builds for package maintainers and those who compile their own AdGuard Home.
- The property `local_domain_name` is now in the `dhcp` object in the configuration file to avoid confusion ([#3367]).
- The `dns.bogus_nxdomain` property in the configuration file now supports CIDR notation alongside IP addresses ([#1730]).
#### Configuration changes
In this release, the schema version has changed from 12 to 14.
- Object `clients`, which in schema versions 13 and earlier was an array of actual persistent clients, is now consist of `persistent` and `runtime_sources` properties:
```yaml
# BEFORE:
'clients':
- name: client-name
# …
# AFTER:
'clients':
'persistent':
- name: client-name
# …
'runtime_sources':
whois: true
arp: true
rdns: true
dhcp: true
hosts: true
```
The value for `clients.runtime_sources.rdns` property is taken from `dns.resolve_clients` property. To rollback this change, remove the `runtime_sources` property, move the contents of `persistent` into the `clients` itself, the value of `clients.runtime_sources.rdns` into the `dns.resolve_clients`, and change the `schema_version` back to `13`.
- Property `local_domain_name`, which in schema versions 12 and earlier used to be a part of the `dns` object, is now a part of the `dhcp` object:
```yaml
# BEFORE:
'dns':
# …
'local_domain_name': 'lan'
# AFTER:
'dhcp':
# …
'local_domain_name': 'lan'
```
To rollback this change, move the property back into the `dns` object and change the `schema_version` back to `12`.
### Deprecated
- The `--no-etc-hosts` option. Its functionality is now controlled by `clients.runtime_sources.hosts` configuration property. v0.109.0 will remove the flag completely.
### Fixed
- Query log occasionally going into an infinite loop ([#4591]).
- Service startup on boot on systems using SysV-init ([#4480]).
- Detection of the stopped service status on macOS and Linux ([#4273]).
- Case-sensitive ClientID ([#4542]).
- Slow version update queries making other HTTP APIs unresponsive ([#4499]).
- ARP tables refreshing process causing excessive PTR requests ([#3157]).
[#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730
[#3020]: https://github.com/AdguardTeam/AdGuardHome/issues/3020
[#3142]: https://github.com/AdguardTeam/AdGuardHome/issues/3142
[#3157]: https://github.com/AdguardTeam/AdGuardHome/issues/3157
[#3367]: https://github.com/AdguardTeam/AdGuardHome/issues/3367
[#3381]: https://github.com/AdguardTeam/AdGuardHome/issues/3381
[#3503]: https://github.com/AdguardTeam/AdGuardHome/issues/3503
[#3597]: https://github.com/AdguardTeam/AdGuardHome/issues/3597
[#3978]: https://github.com/AdguardTeam/AdGuardHome/issues/3978
[#4166]: https://github.com/AdguardTeam/AdGuardHome/issues/4166
[#4213]: https://github.com/AdguardTeam/AdGuardHome/issues/4213
[#4221]: https://github.com/AdguardTeam/AdGuardHome/issues/4221
[#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238
[#4273]: https://github.com/AdguardTeam/AdGuardHome/issues/4273
[#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276
[#4480]: https://github.com/AdguardTeam/AdGuardHome/issues/4480
[#4499]: https://github.com/AdguardTeam/AdGuardHome/issues/4499
[#4503]: https://github.com/AdguardTeam/AdGuardHome/issues/4503
[#4533]: https://github.com/AdguardTeam/AdGuardHome/issues/4533
[#4542]: https://github.com/AdguardTeam/AdGuardHome/issues/4542
[#4591]: https://github.com/AdguardTeam/AdGuardHome/issues/4591
[#4592]: https://github.com/AdguardTeam/AdGuardHome/issues/4592
[CVE-2022-29526]: https://www.cvedetails.com/cve/CVE-2022-29526
[CVE-2022-29804]: https://www.cvedetails.com/cve/CVE-2022-29804
[CVE-2022-30580]: https://www.cvedetails.com/cve/CVE-2022-30580
[CVE-2022-30629]: https://www.cvedetails.com/cve/CVE-2022-30629
[CVE-2022-30634]: https://www.cvedetails.com/cve/CVE-2022-30634
[ms-v0.107.7]: https://github.com/AdguardTeam/AdGuardHome/milestone/43?closed=1
[rfc-9250]: https://datatracker.ietf.org/doc/html/rfc9250
## [v0.107.6] - 2022-04-13
See also the [v0.107.6 GitHub milestone][ms-v0.107.6].
### Security
- `User-Agent` HTTP header removed from outgoing DNS-over-HTTPS requests.
- Go version has been updated to prevent the possibility of exploiting the [CVE-2022-24675], [CVE-2022-27536], and [CVE-2022-28327] Go vulnerabilities.
### Added
- Support for SVCB/HTTPS parameter `dohpath` in filtering rules with the `dnsrewrite` modifier according to the [RFC draft][dns-draft-02] ([#4463]).
### Changed
- Filtering rules with the `dnsrewrite` modifier that create SVCB or HTTPS responses should use `ech` instead of `echconfig` to conform with the [latest drafts][svcb-draft-08].
### Deprecated
- SVCB/HTTPS parameter name `echconfig` in filtering rules with the `dnsrewrite` modifier. Use `ech` instead. v0.109.0 will remove support for the outdated name `echconfig`.
- Obsolete `--no-mem-optimization` option ([#4437]). v0.109.0 will remove the flag completely.
### Fixed
- I/O timeout errors when checking for the presence of another DHCP server.
- Network interfaces being incorrectly labeled as down during installation.
- Rules for blocking the QQ service ([#3717]).
### Removed
- Go 1.16 support, since that branch of the Go compiler has reached end of life and doesn’t receive security updates anymore.
[#3717]: https://github.com/AdguardTeam/AdGuardHome/issues/3717
[#4437]: https://github.com/AdguardTeam/AdGuardHome/issues/4437
[#4463]: https://github.com/AdguardTeam/AdGuardHome/issues/4463
[CVE-2022-24675]: https://www.cvedetails.com/cve/CVE-2022-24675
[CVE-2022-27536]: https://www.cvedetails.com/cve/CVE-2022-27536
[CVE-2022-28327]: https://www.cvedetails.com/cve/CVE-2022-28327
[dns-draft-02]: https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02#section-5.1
[ms-v0.107.6]: https://github.com/AdguardTeam/AdGuardHome/milestone/42?closed=1
[repr]: https://reproducible-builds.org/docs/source-date-epoch/
[svcb-draft-08]: https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html
## [v0.107.5] - 2022-03-04
This is a security update. There is no GitHub milestone, since no GitHub issues were resolved.
### Security
- Go version has been updated to prevent the possibility of exploiting the [CVE-2022-24921] Go vulnerability.
[CVE-2022-24921]: https://www.cvedetails.com/cve/CVE-2022-24921
## [v0.107.4] - 2022-03-01
See also the [v0.107.4 GitHub milestone][ms-v0.107.4].
### Security
- Go version has been updated to prevent the possibility of exploiting the [CVE-2022-23806], [CVE-2022-23772], and [CVE-2022-23773] Go vulnerabilities.
### Fixed
- Optimistic cache now responds with expired items even if those can’t be resolved again ([#4254]).
- Unnecessarily complex hosts-related logic leading to infinite recursion in some cases ([#4216]).
[#4216]: https://github.com/AdguardTeam/AdGuardHome/issues/4216
[#4254]: https://github.com/AdguardTeam/AdGuardHome/issues/4254
[CVE-2022-23772]: https://www.cvedetails.com/cve/CVE-2022-23772
[CVE-2022-23773]: https://www.cvedetails.com/cve/CVE-2022-23773
[CVE-2022-23806]: https://www.cvedetails.com/cve/CVE-2022-23806
[ms-v0.107.4]: https://github.com/AdguardTeam/AdGuardHome/milestone/41?closed=1
## [v0.107.3] - 2022-01-25
See also the [v0.107.3 GitHub milestone][ms-v0.107.3].
### Added
- Support for a `dnsrewrite` modifier with an empty `NOERROR` response ([#4133]).
### Fixed
- Wrong set of ports checked for duplicates during the initial setup ([#4095]).
- Incorrectly invalidated service domains ([#4120]).
- Poor testing of domain-specific upstream servers ([#4074]).
- Omitted aliases of hosts specified by another line within the OS’s hosts file ([#4079]).
[#4074]: https://github.com/AdguardTeam/AdGuardHome/issues/4074
[#4079]: https://github.com/AdguardTeam/AdGuardHome/issues/4079
[#4095]: https://github.com/AdguardTeam/AdGuardHome/issues/4095
[#4120]: https://github.com/AdguardTeam/AdGuardHome/issues/4120
[#4133]: https://github.com/AdguardTeam/AdGuardHome/issues/4133
[ms-v0.107.3]: https://github.com/AdguardTeam/AdGuardHome/milestone/40?closed=1
## [v0.107.2] - 2021-12-29
See also the [v0.107.2 GitHub milestone][ms-v0.107.2].
### Fixed
- Infinite loops when TCP connections time out ([#4042]).
[#4042]: https://github.com/AdguardTeam/AdGuardHome/issues/4042
[ms-v0.107.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/38?closed=1
## [v0.107.1] - 2021-12-29
See also the [v0.107.1 GitHub milestone][ms-v0.107.1].
### Changed
- The validation error message for duplicated allow- and blocklists in DNS settings now shows the duplicated elements ([#3975]).
### Fixed
- `ipset` initialization bugs ([#4027]).
- Legacy DNS rewrites from a wildcard pattern to a subdomain ([#4016]).
- Service not being stopped before running the `uninstall` service action ([#3868]).
- Broken `reload` service action on FreeBSD.
- Legacy DNS rewrites responding from upstream when a request other than `A` or `AAAA` is received ([#4008]).
- Panic on port availability check during installation ([#3987]).
- Incorrect application of rules from the OS’s hosts files ([#3998]).
[#3868]: https://github.com/AdguardTeam/AdGuardHome/issues/3868
[#3975]: https://github.com/AdguardTeam/AdGuardHome/issues/3975
[#3987]: https://github.com/AdguardTeam/AdGuardHome/issues/3987
[#3998]: https://github.com/AdguardTeam/AdGuardHome/issues/3998
[#4008]: https://github.com/AdguardTeam/AdGuardHome/issues/4008
[#4016]: https://github.com/AdguardTeam/AdGuardHome/issues/4016
[#4027]: https://github.com/AdguardTeam/AdGuardHome/issues/4027
[ms-v0.107.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/37?closed=1
## [v0.107.0] - 2021-12-21
See also the [v0.107.0 GitHub milestone][ms-v0.107.0].
### Added
- Upstream server information for responses from cache ([#3772]). Note that old log entries concerning cached responses won’t include that information.
- Finnish and Ukrainian localizations.
- Setting the timeout for IP address pinging in the "Fastest IP address" mode through the new `fastest_timeout` property in the configuration file ([#1992]).
- Static IP address detection on FreeBSD ([#3289]).
- Optimistic cache ([#2145]).
- New possible value of `6h` for `querylog_interval` property ([#2504]).
- Blocking access using ClientIDs ([#2624], [#3162]).
- `source` directives support in `/etc/network/interfaces` on Linux ([#3257]).
- [RFC 9000][rfc-9000] support in QUIC.
- Completely disabling statistics by setting the statistics interval to zero ([#2141]).
- The ability to completely purge DHCP leases ([#1691]).
- Settable timeouts for querying the upstream servers ([#2280]).
- Configuration file properties to change group and user ID on startup on Unix ([#2763]).
- Experimental OpenBSD support for AMD64 and 64-bit ARM CPUs ([#2439], [#3225], [#3226]).
- Support for custom port in DNS-over-HTTPS profiles for Apple’s devices ([#3172]).
- `darwin/arm64` support ([#2443]).
- `freebsd/arm64` support ([#2441]).
- Output of the default addresses of the upstreams used for resolving PTRs for private addresses ([#3136]).
- Detection and handling of recurrent PTR requests for locally-served addresses ([#3185]).
- The ability to completely disable reverse DNS resolving of IPs from locally-served networks ([#3184]).
- New flag `--local-frontend` to serve dynamically changeable frontend files from disk as opposed to the ones that were compiled into the binary.
### Changed
- Port bindings are now checked for uniqueness ([#3835]).
- The DNSSEC check now simply checks against the AD flag in the response ([#3904]).
- Client objects in the configuration file are now sorted ([#3933]).
- Responses from cache are now labeled ([#3772]).
- Better error message for ED25519 private keys, which are not widely supported ([#3737]).
- Cache now follows RFC more closely for negative answers ([#3707]).
- `dnsrewrite` rules and other DNS rewrites will now be applied even when the protection is disabled ([#1558]).
- DHCP gateway address, subnet mask, IP address range, and leases validations ([#3529]).
- The `systemd` service script will now create the `/var/log` directory when it doesn’t exist ([#3579]).
- Items in allowed clients, disallowed clients, and blocked hosts lists are now required to be unique ([#3419]).
- The TLS private key previously saved as a string isn’t shown in API responses anymore ([#1898]).
- Better OpenWrt detection ([#3435]).
- DNS-over-HTTPS queries that come from HTTP proxies in the `trusted_proxies` list now use the real IP address of the client instead of the address of the proxy ([#2799]).
- Clients who are blocked by access settings now receive a `REFUSED` response when a protocol other than DNS-over-UDP and DNSCrypt is used.
- `dns.querylog_interval` property is now formatted in hours.
- Query log search now supports internationalized domains ([#3012]).
- Internationalized domains are now shown decoded in the query log with the original encoded version shown in request details ([#3013]).
- When `/etc/hosts`-type rules have several IPs for one host, all IPs are now returned instead of only the first one ([#1381]).
- Property `rlimit_nofile` is now in the `os` object of the configuration file, together with the new `group` and `user` properties ([#2763]).
- Permissions on filter files are now `0o644` instead of `0o600` ([#3198]).
#### Configuration changes
In this release, the schema version has changed from 10 to 12.
- Property `dns.querylog_interval`, which in schema versions 11 and earlier used to be an integer number of days, is now a string with a human-readable duration:
```yaml
# BEFORE:
'dns':
# …
'querylog_interval': 90
# AFTER:
'dns':
# …
'querylog_interval': '2160h'
```
To rollback this change, convert the property back into days and change the `schema_version` back to `11`.
- Property `rlimit_nofile`, which in schema versions 10 and earlier used to be on the top level, is now moved to the new `os` object:
```yaml
# BEFORE:
'rlimit_nofile': 42
# AFTER:
'os':
'group': ''
'rlimit_nofile': 42
'user': ''
```
To rollback this change, move the property on the top level and change the `schema_version` back to `10`.
### Deprecated
- Go 1.16 support. v0.108.0 will require at least Go 1.17 to build.
### Fixed
- EDNS0 TCP keepalive option handling ([#3778]).
- Rules with the `denyallow` modifier applying to IP addresses when they shouldn’t ([#3175]).
- The length of the EDNS0 client subnet option appearing too long for some upstream servers ([#3887]).
- Invalid redirection to the HTTPS web interface after saving enabled encryption settings ([#3558]).
- Incomplete propagation of the client’s IP anonymization setting to the statistics ([#3890]).
- Incorrect results with the `dnsrewrite` modifier for entries from the operating system’s hosts file ([#3815]).
- Matching against rules with `|` at the end of the domain name ([#3371]).
- Incorrect assignment of explicitly configured DHCP options ([#3744]).
- Occasional panic during shutdown ([#3655]).
- Addition of IPs into only one as opposed to all matching ipsets on Linux ([#3638]).
- Removal of temporary filter files ([#3567]).
- Panic when an upstream server responds with an empty question section ([#3551]).
- 9GAG blocking ([#3564]).
- DHCP now follows RFCs more closely when it comes to response sending and option selection ([#3443], [#3538]).
- Occasional panics when reading old statistics databases ([#3506]).
- `reload` service action on macOS and FreeBSD ([#3457]).
- Inaccurate using of service actions in the installation script ([#3450]).
- ClientID checking ([#3437]).
- Discovering other DHCP servers on `darwin` and `freebsd` ([#3417]).
- Switching listening address to unspecified one when bound to a single specified IPv4 address on Darwin (macOS) ([#2807]).
- Incomplete HTTP response for static IP address.
- DNSCrypt queries weren’t appearing in query log ([#3372]).
- Wrong IP address for proxied DNS-over-HTTPS queries ([#2799]).
- Domain name letter case mismatches in DNS rewrites ([#3351]).
- Conflicts between IPv4 and IPv6 DNS rewrites ([#3343]).
- Letter case mismatches in `CNAME` filtering ([#3335]).
- Occasional breakages on network errors with DNS-over-HTTP upstreams ([#3217]).
- Errors when setting static IP on Linux ([#3257]).
- Treatment of domain names and FQDNs in custom rules with the `dnsrewrite` modifier that use the `PTR` type ([#3256]).
- Redundant hostname generating while loading static leases with empty hostname ([#3166]).
- Domain name case in responses ([#3194]).
- Custom upstreams selection for clients with ClientIDs in DNS-over-TLS and DNS-over-HTTP ([#3186]).
- Incorrect client-based filtering applying logic ([#2875]).
### Removed
- Go 1.15 support.
[#1381]: https://github.com/AdguardTeam/AdGuardHome/issues/1381
[#1558]: https://github.com/AdguardTeam/AdGuardHome/issues/1558
[#1691]: https://github.com/AdguardTeam/AdGuardHome/issues/1691
[#1898]: https://github.com/AdguardTeam/AdGuardHome/issues/1898
[#1992]: https://github.com/AdguardTeam/AdGuardHome/issues/1992
[#2141]: https://github.com/AdguardTeam/AdGuardHome/issues/2141
[#2145]: https://github.com/AdguardTeam/AdGuardHome/issues/2145
[#2280]: https://github.com/AdguardTeam/AdGuardHome/issues/2280
[#2439]: https://github.com/AdguardTeam/AdGuardHome/issues/2439
[#2441]: https://github.com/AdguardTeam/AdGuardHome/issues/2441
[#2443]: https://github.com/AdguardTeam/AdGuardHome/issues/2443
[#2504]: https://github.com/AdguardTeam/AdGuardHome/issues/2504
[#2624]: https://github.com/AdguardTeam/AdGuardHome/issues/2624
[#2763]: https://github.com/AdguardTeam/AdGuardHome/issues/2763
[#2799]: https://github.com/AdguardTeam/AdGuardHome/issues/2799
[#2807]: https://github.com/AdguardTeam/AdGuardHome/issues/2807
[#3012]: https://github.com/AdguardTeam/AdGuardHome/issues/3012
[#3013]: https://github.com/AdguardTeam/AdGuardHome/issues/3013
[#3136]: https://github.com/AdguardTeam/AdGuardHome/issues/3136
[#3162]: https://github.com/AdguardTeam/AdGuardHome/issues/3162
[#3166]: https://github.com/AdguardTeam/AdGuardHome/issues/3166
[#3172]: https://github.com/AdguardTeam/AdGuardHome/issues/3172
[#3175]: https://github.com/AdguardTeam/AdGuardHome/issues/3175
[#3184]: https://github.com/AdguardTeam/AdGuardHome/issues/3184
[#3185]: https://github.com/AdguardTeam/AdGuardHome/issues/3185
[#3186]: https://github.com/AdguardTeam/AdGuardHome/issues/3186
[#3194]: https://github.com/AdguardTeam/AdGuardHome/issues/3194
[#3198]: https://github.com/AdguardTeam/AdGuardHome/issues/3198
[#3217]: https://github.com/AdguardTeam/AdGuardHome/issues/3217
[#3225]: https://github.com/AdguardTeam/AdGuardHome/issues/3225
[#3226]: https://github.com/AdguardTeam/AdGuardHome/issues/3226
[#3256]: https://github.com/AdguardTeam/AdGuardHome/issues/3256
[#3257]: https://github.com/AdguardTeam/AdGuardHome/issues/3257
[#3289]: https://github.com/AdguardTeam/AdGuardHome/issues/3289
[#3335]: https://github.com/AdguardTeam/AdGuardHome/issues/3335
[#3343]: https://github.com/AdguardTeam/AdGuardHome/issues/3343
[#3351]: https://github.com/AdguardTeam/AdGuardHome/issues/3351
[#3371]: https://github.com/AdguardTeam/AdGuardHome/issues/3371
[#3372]: https://github.com/AdguardTeam/AdGuardHome/issues/3372
[#3417]: https://github.com/AdguardTeam/AdGuardHome/issues/3417
[#3419]: https://github.com/AdguardTeam/AdGuardHome/issues/3419
[#3435]: https://github.com/AdguardTeam/AdGuardHome/issues/3435
[#3437]: https://github.com/AdguardTeam/AdGuardHome/issues/3437
[#3443]: https://github.com/AdguardTeam/AdGuardHome/issues/3443
[#3450]: https://github.com/AdguardTeam/AdGuardHome/issues/3450
[#3457]: https://github.com/AdguardTeam/AdGuardHome/issues/3457
[#3506]: https://github.com/AdguardTeam/AdGuardHome/issues/3506
[#3529]: https://github.com/AdguardTeam/AdGuardHome/issues/3529
[#3538]: https://github.com/AdguardTeam/AdGuardHome/issues/3538
[#3551]: https://github.com/AdguardTeam/AdGuardHome/issues/3551
[#3558]: https://github.com/AdguardTeam/AdGuardHome/issues/3558
[#3564]: https://github.com/AdguardTeam/AdGuardHome/issues/3564
[#3567]: https://github.com/AdguardTeam/AdGuardHome/issues/3567
[#3579]: https://github.com/AdguardTeam/AdGuardHome/issues/3579
[#3638]: https://github.com/AdguardTeam/AdGuardHome/issues/3638
[#3655]: https://github.com/AdguardTeam/AdGuardHome/issues/3655
[#3707]: https://github.com/AdguardTeam/AdGuardHome/issues/3707
[#3737]: https://github.com/AdguardTeam/AdGuardHome/issues/3737
[#3744]: https://github.com/AdguardTeam/AdGuardHome/issues/3744
[#3772]: https://github.com/AdguardTeam/AdGuardHome/issues/3772
[#3778]: https://github.com/AdguardTeam/AdGuardHome/issues/3778
[#3815]: https://github.com/AdguardTeam/AdGuardHome/issues/3815
[#3835]: https://github.com/AdguardTeam/AdGuardHome/issues/3835
[#3887]: https://github.com/AdguardTeam/AdGuardHome/issues/3887
[#3890]: https://github.com/AdguardTeam/AdGuardHome/issues/3890
[#3904]: https://github.com/AdguardTeam/AdGuardHome/issues/3904
[#3933]: https://github.com/AdguardTeam/AdGuardHome/pull/3933
[ms-v0.107.0]: https://github.com/AdguardTeam/AdGuardHome/milestone/23?closed=1
[rfc-9000]: https://datatracker.ietf.org/doc/html/rfc9000
## [v0.106.3] - 2021-05-19
See also the [v0.106.3 GitHub milestone][ms-v0.106.3].
### Added
- Support for reinstall (`-r`) and uninstall (`-u`) flags in the installation script ([#2462]).
- Support for DHCP `DECLINE` and `RELEASE` message types ([#3053]).
### Changed
- Add microseconds to log output.
### Fixed
- Intermittent "Warning: ID mismatch" errors ([#3087]).
- Error when using installation script on some ARMv7 devices ([#2542]).
- DHCP leases validation ([#3107], [#3127]).
- Local PTR request recursion in Docker containers ([#3064]).
- Ignoring client-specific filtering settings when filtering is disabled in general settings ([#2875]).
- Disallowed domains are now case-insensitive ([#3115]).
[#2462]: https://github.com/AdguardTeam/AdGuardHome/issues/2462
[#2542]: https://github.com/AdguardTeam/AdGuardHome/issues/2542
[#2875]: https://github.com/AdguardTeam/AdGuardHome/issues/2875
[#3053]: https://github.com/AdguardTeam/AdGuardHome/issues/3053
[#3064]: https://github.com/AdguardTeam/AdGuardHome/issues/3064
[#3107]: https://github.com/AdguardTeam/AdGuardHome/issues/3107
[#3115]: https://github.com/AdguardTeam/AdGuardHome/issues/3115
[#3127]: https://github.com/AdguardTeam/AdGuardHome/issues/3127
[ms-v0.106.3]: https://github.com/AdguardTeam/AdGuardHome/milestone/35?closed=1
## [v0.106.2] - 2021-05-06
See also the [v0.106.2 GitHub milestone][ms-v0.106.2].
### Fixed
- Uniqueness validation for dynamic DHCP leases ([#3056]).
[#3056]: https://github.com/AdguardTeam/AdGuardHome/issues/3056
[ms-v0.106.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/34?closed=1
## [v0.106.1] - 2021-04-30
See also the [v0.106.1 GitHub milestone][ms-v0.106.1].
### Fixed
- Local domain name handling when the DHCP server is disabled ([#3028]).
- Normalization of previously-saved invalid static DHCP leases ([#3027]).
- Validation of IPv6 addresses with zones in system resolvers ([#3022]).
[#3022]: https://github.com/AdguardTeam/AdGuardHome/issues/3022
[#3027]: https://github.com/AdguardTeam/AdGuardHome/issues/3027
[#3028]: https://github.com/AdguardTeam/AdGuardHome/issues/3028
[ms-v0.106.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/33?closed=1
## [v0.106.0] - 2021-04-28
See also the [v0.106.0 GitHub milestone][ms-v0.106.0].
### Added
- The ability to block user for login after configurable number of unsuccessful attempts for configurable time ([#2826]).
- `denyallow` modifier for filters ([#2923]).
- Hostname uniqueness validation in the DHCP server ([#2952]).
- Hostname generating for DHCP clients which don’t provide their own ([#2723]).
- New flag `--no-etc-hosts` to disable client domain name lookups in the operating system’s `/etc/hosts` files ([#1947]).
- The ability to set up custom upstreams to resolve PTR queries for local addresses and to disable the automatic resolving of clients’ addresses ([#2704]).
- Logging of the client’s IP address after failed login attempts ([#2824]).
- Search by clients’ names in the query log ([#1273]).
- Verbose version output with `-v --version` ([#2416]).
- The ability to set a custom TLD or domain name for known hosts in the local network ([#2393], [#2961]).
- The ability to serve DNS queries on multiple hosts and interfaces ([#1401]).
- `ips` and `text` DHCP server options ([#2385]).
- `SRV` records support in filtering rules with the `dnsrewrite` modifier ([#2533]).
### Changed
- Our DoQ implementation is now updated to conform to the latest standard [draft][doq-draft-02] ([#2843]).
- Quality of logging ([#2954]).
- Normalization of hostnames sent by DHCP clients ([#2946], [#2952]).
- The access to the private hosts is now forbidden for users from external networks ([#2889]).
- The reverse lookup for local addresses is now performed via local resolvers ([#2704]).
- Stricter validation of the IP addresses of static leases in the DHCP server with regards to the netmask ([#2838]).
- Stricter validation of `dnsrewrite` filtering rule modifier parameters ([#2498]).
- New, more correct versioning scheme ([#2412]).
### Deprecated
- Go 1.15 support. v0.107.0 will require at least Go 1.16 to build.
### Fixed
- Multiple answers for a `dnsrewrite` rule matching requests with repeating patterns in it ([#2981]).
- Root server resolving when custom upstreams for hosts are specified ([#2994]).
- Inconsistent resolving of DHCP clients when the DHCP server is disabled ([#2934]).
- Comment handling in clients’ custom upstreams ([#2947]).
- Overwriting of DHCPv4 options when using the HTTP API ([#2927]).
- Assumption that MAC addresses always have the length of 6 octets ([#2828]).
- Support for more than one `/24` subnet in DHCP ([#2541]).
- Invalid filenames in the `mobileconfig` API responses ([#2835]).
### Removed
- Go 1.14 support.
[#1273]: https://github.com/AdguardTeam/AdGuardHome/issues/1273
[#1401]: https://github.com/AdguardTeam/AdGuardHome/issues/1401
[#1947]: https://github.com/AdguardTeam/AdGuardHome/issues/1947
[#2385]: https://github.com/AdguardTeam/AdGuardHome/issues/2385
[#2393]: https://github.com/AdguardTeam/AdGuardHome/issues/2393
[#2412]: https://github.com/AdguardTeam/AdGuardHome/issues/2412
[#2416]: https://github.com/AdguardTeam/AdGuardHome/issues/2416
[#2498]: https://github.com/AdguardTeam/AdGuardHome/issues/2498
[#2533]: https://github.com/AdguardTeam/AdGuardHome/issues/2533
[#2541]: https://github.com/AdguardTeam/AdGuardHome/issues/2541
[#2704]: https://github.com/AdguardTeam/AdGuardHome/issues/2704
[#2723]: https://github.com/AdguardTeam/AdGuardHome/issues/2723
[#2824]: https://github.com/AdguardTeam/AdGuardHome/issues/2824
[#2826]: https://github.com/AdguardTeam/AdGuardHome/issues/2826
[#2828]: https://github.com/AdguardTeam/AdGuardHome/issues/2828
[#2835]: https://github.com/AdguardTeam/AdGuardHome/issues/2835
[#2838]: https://github.com/AdguardTeam/AdGuardHome/issues/2838
[#2843]: https://github.com/AdguardTeam/AdGuardHome/issues/2843
[#2889]: https://github.com/AdguardTeam/AdGuardHome/issues/2889
[#2923]: https://github.com/AdguardTeam/AdGuardHome/issues/2923
[#2927]: https://github.com/AdguardTeam/AdGuardHome/issues/2927
[#2934]: https://github.com/AdguardTeam/AdGuardHome/issues/2934
[#2946]: https://github.com/AdguardTeam/AdGuardHome/issues/2946
[#2947]: https://github.com/AdguardTeam/AdGuardHome/issues/2947
[#2952]: https://github.com/AdguardTeam/AdGuardHome/issues/2952
[#2954]: https://github.com/AdguardTeam/AdGuardHome/issues/2954
[#2961]: https://github.com/AdguardTeam/AdGuardHome/issues/2961
[#2981]: https://github.com/AdguardTeam/AdGuardHome/issues/2981
[#2994]: https://github.com/AdguardTeam/AdGuardHome/issues/2994
[doq-draft-02]: https://tools.ietf.org/html/draft-ietf-dprive-dnsoquic-02
[ms-v0.106.0]: https://github.com/AdguardTeam/AdGuardHome/milestone/26?closed=1
## [v0.105.2] - 2021-03-10
### Security
- Session token doesn’t contain user’s information anymore ([#2470]).
See also the [v0.105.2 GitHub milestone][ms-v0.105.2].
### Fixed
- Incomplete hostnames with trailing zero-bytes handling ([#2582]).
- Wrong DNS-over-TLS ALPN configuration ([#2681]).
- Inconsistent responses for messages with EDNS0 and AD when DNS caching is enabled ([#2600]).
- Incomplete OpenWrt detection ([#2757]).
- DHCP lease’s `expired` property incorrect time format ([#2692]).
- Incomplete DNS upstreams validation ([#2674]).
- Wrong parsing of DHCP options of the `ip` type ([#2688]).
[#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470
[#2582]: https://github.com/AdguardTeam/AdGuardHome/issues/2582
[#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600
[#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674
[#2681]: https://github.com/AdguardTeam/AdGuardHome/issues/2681
[#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688
[#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692
[#2757]: https://github.com/AdguardTeam/AdGuardHome/issues/2757
[ms-v0.105.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/32?closed=1
## [v0.105.1] - 2021-02-15
See also the [v0.105.1 GitHub milestone][ms-v0.105.1].
### Changed
- Increased HTTP API timeouts ([#2671], [#2682]).
- "Permission denied" errors when checking if the machine has a static IP no longer prevent the DHCP server from starting ([#2667]).
- The server name sent by clients of TLS APIs is not only checked when `strict_sni_check` is enabled ([#2664]).
- HTTP API request body size limit for the `POST /control/access/set` and `POST /control/filtering/set_rules` HTTP APIs is increased ([#2666], [#2675]).
### Fixed
- Error when enabling the DHCP server when AdGuard Home couldn’t determine if the machine has a static IP.
- Optical issue on custom rules ([#2641]).
- Occasional crashes during startup.
- The property `"range_start"` in the `GET /control/dhcp/status` HTTP API response is now correctly named again ([#2678]).
- DHCPv6 server’s `ra_slaac_only` and `ra_allow_slaac` properties aren’t reset to `false` on update anymore ([#2653]).
- The `Vary` header is now added along with `Access-Control-Allow-Origin` to prevent cache-related and other issues in browsers ([#2658]).
- The request body size limit is now set for HTTPS requests as well.
- Incorrect version tag in the Docker release ([#2663]).
- DNSCrypt queries weren’t marked as such in logs ([#2662]).
[#2641]: https://github.com/AdguardTeam/AdGuardHome/issues/2641
[#2653]: https://github.com/AdguardTeam/AdGuardHome/issues/2653
[#2658]: https://github.com/AdguardTeam/AdGuardHome/issues/2658
[#2662]: https://github.com/AdguardTeam/AdGuardHome/issues/2662
[#2663]: https://github.com/AdguardTeam/AdGuardHome/issues/2663
[#2664]: https://github.com/AdguardTeam/AdGuardHome/issues/2664
[#2666]: https://github.com/AdguardTeam/AdGuardHome/issues/2666
[#2667]: https://github.com/AdguardTeam/AdGuardHome/issues/2667
[#2671]: https://github.com/AdguardTeam/AdGuardHome/issues/2671
[#2675]: https://github.com/AdguardTeam/AdGuardHome/issues/2675
[#2678]: https://github.com/AdguardTeam/AdGuardHome/issues/2678
[#2682]: https://github.com/AdguardTeam/AdGuardHome/issues/2682
[ms-v0.105.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/31?closed=1
## [v0.105.0] - 2021-02-10
See also the [v0.105.0 GitHub milestone][ms-v0.105.0].
### Added
- Added more services to the "Blocked services" list ([#2224], [#2401]).
- `ipset` subdomain matching, just like `dnsmasq` does ([#2179]).
- ClientID support for DNS-over-HTTPS, DNS-over-QUIC, and DNS-over-TLS ([#1383]).
- The new `dnsrewrite` modifier for filters ([#2102]).
- The host checking API and the query logs API can now return multiple matched rules ([#2102]).
- Detecting of network interface configured to have static IP address via `/etc/network/interfaces` ([#2302]).
- DNSCrypt protocol support ([#1361]).
- A 5 second wait period until a DHCP server’s network interface gets an IP address ([#2304]).
- `dnstype` modifier for filters ([#2337]).
- HTTP API request body size limit ([#2305]).
### Changed
- `Access-Control-Allow-Origin` is now only set to the same origin as the domain, but with an HTTP scheme as opposed to `*` ([#2484]).
- `workDir` now supports symlinks.
- Stopped mounting together the directories `/opt/adguardhome/conf` and `/opt/adguardhome/work` in our Docker images ([#2589]).
- When `dns.bogus_nxdomain` option is used, the server will now transform responses if there is at least one bogus address instead of all of them ([#2394]). The new behavior is the same as in `dnsmasq`.
- Post-updating relaunch possibility is now determined OS-dependently ([#2231], [#2391]).
- Made the mobileconfig HTTP API more robust and predictable, add parameters and improve error response ([#2358]).
- Improved HTTP requests handling and timeouts ([#2343]).
- Our snap package now uses the `core20` image as its base ([#2306]).
- New build system and various internal improvements ([#2271], [#2276], [#2297], [#2509], [#2552], [#2639], [#2646]).
### Deprecated
- Go 1.14 support. v0.106.0 will require at least Go 1.15 to build.
- The `darwin/386` port. It will be removed in v0.106.0.
- The `"rule"` and `"filter_id"` property in `GET /filtering/check_host` and `GET /querylog` responses. They will be removed in v0.106.0 ([#2102]).
### Fixed
- Autoupdate bug in the Darwin (macOS) version ([#2630]).
- Unnecessary conversions from `string` to `net.IP`, and vice versa ([#2508]).
- Inability to set DNS cache TTL limits ([#2459]).
- Possible freezes on slower machines ([#2225]).
- A mitigation against records being shown in the wrong order on the query log page ([#2293]).
- A JSON parsing error in query log ([#2345]).
- Incorrect detection of the IPv6 address of an interface as well as another infinite loop in the `/dhcp/find_active_dhcp` HTTP API ([#2355]).
### Removed
- The undocumented ability to use hostnames as any of `bind_host` values in configuration. Documentation requires them to be valid IP addresses, and now the implementation makes sure that that is the case ([#2508]).
- `Dockerfile` ([#2276]). Replaced with the script `scripts/make/build-docker.sh` which uses `scripts/make/Dockerfile`.
- Support for pre-v0.99.3 format of query logs ([#2102]).
[#1361]: https://github.com/AdguardTeam/AdGuardHome/issues/1361
[#1383]: https://github.com/AdguardTeam/AdGuardHome/issue
gitextract_lq2m_xle/ ├── .codecov.yml ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug.yml │ │ ├── config.yml │ │ └── feature.yml │ ├── PULL_REQUEST_TEMPLATE │ ├── stale.yml │ └── workflows/ │ ├── build.yml │ ├── lint.yml │ └── potential-duplicates.yml ├── .gitignore ├── .markdownlint.json ├── .twosky.json ├── AGHTechDoc.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── HACKING.md ├── LICENSE.txt ├── Makefile ├── README.md ├── SECURITY.md ├── bamboo-specs/ │ ├── bamboo.yaml │ ├── release.yaml │ ├── snapcraft.yaml │ └── test.yaml ├── build/ │ └── gitkeep ├── changelog.config.js ├── client/ │ ├── .eslintrc.json │ ├── .gitattributes │ ├── .prettierrc │ ├── .stylelintrc.js │ ├── babel.config.cjs │ ├── constants.js │ ├── dev.eslintrc │ ├── global.d.ts │ ├── package.json │ ├── playwright.config.ts │ ├── prod.eslintrc │ ├── public/ │ │ ├── index.html │ │ ├── install.html │ │ └── login.html │ ├── src/ │ │ ├── __locales/ │ │ │ ├── ar.json │ │ │ ├── be.json │ │ │ ├── bg.json │ │ │ ├── cs.json │ │ │ ├── da.json │ │ │ ├── de.json │ │ │ ├── en.json │ │ │ ├── es.json │ │ │ ├── fa.json │ │ │ ├── fi.json │ │ │ ├── fr.json │ │ │ ├── hr.json │ │ │ ├── hu.json │ │ │ ├── id.json │ │ │ ├── it.json │ │ │ ├── ja.json │ │ │ ├── ko.json │ │ │ ├── nl.json │ │ │ ├── no.json │ │ │ ├── pl.json │ │ │ ├── pt-br.json │ │ │ ├── pt-pt.json │ │ │ ├── ro.json │ │ │ ├── ru.json │ │ │ ├── si-lk.json │ │ │ ├── sk.json │ │ │ ├── sl.json │ │ │ ├── sr-cs.json │ │ │ ├── sv.json │ │ │ ├── th.json │ │ │ ├── tr.json │ │ │ ├── uk.json │ │ │ ├── vi.json │ │ │ ├── zh-cn.json │ │ │ ├── zh-hk.json │ │ │ └── zh-tw.json │ │ ├── __locales-services/ │ │ │ ├── ar.json │ │ │ ├── be.json │ │ │ ├── bg.json │ │ │ ├── cs.json │ │ │ ├── da.json │ │ │ ├── de.json │ │ │ ├── en.json │ │ │ ├── es.json │ │ │ ├── fa.json │ │ │ ├── fi.json │ │ │ ├── fr.json │ │ │ ├── hr.json │ │ │ ├── hu.json │ │ │ ├── id.json │ │ │ ├── it.json │ │ │ ├── ja.json │ │ │ ├── ko.json │ │ │ ├── nl.json │ │ │ ├── no.json │ │ │ ├── pl.json │ │ │ ├── pt-br.json │ │ │ ├── pt-pt.json │ │ │ ├── ro.json │ │ │ ├── ru.json │ │ │ ├── si-lk.json │ │ │ ├── sk.json │ │ │ ├── sl.json │ │ │ ├── sr-cs.json │ │ │ ├── sv.json │ │ │ ├── th.json │ │ │ ├── tr.json │ │ │ ├── uk.json │ │ │ ├── vi.json │ │ │ ├── zh-cn.json │ │ │ ├── zh-hk.json │ │ │ └── zh-tw.json │ │ ├── __tests__/ │ │ │ └── helpers.test.ts │ │ ├── actions/ │ │ │ ├── access.ts │ │ │ ├── clients.ts │ │ │ ├── dnsConfig.ts │ │ │ ├── encryption.ts │ │ │ ├── filtering.ts │ │ │ ├── index.tsx │ │ │ ├── install.ts │ │ │ ├── login.ts │ │ │ ├── queryLogs.ts │ │ │ ├── rewrites.ts │ │ │ ├── services.ts │ │ │ ├── stats.ts │ │ │ └── toasts.ts │ │ ├── api/ │ │ │ └── Api.ts │ │ ├── components/ │ │ │ ├── App/ │ │ │ │ ├── index.css │ │ │ │ └── index.tsx │ │ │ ├── Dashboard/ │ │ │ │ ├── BlockedDomains.tsx │ │ │ │ ├── Clients.tsx │ │ │ │ ├── Counters.tsx │ │ │ │ ├── Dashboard.css │ │ │ │ ├── DomainCell.tsx │ │ │ │ ├── QueriedDomains.tsx │ │ │ │ ├── Statistics.tsx │ │ │ │ ├── StatsCard.tsx │ │ │ │ ├── UpstreamAvgTime.tsx │ │ │ │ ├── UpstreamResponses.tsx │ │ │ │ └── index.tsx │ │ │ ├── Filters/ │ │ │ │ ├── Actions.tsx │ │ │ │ ├── Check/ │ │ │ │ │ ├── Info.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── CustomRules.tsx │ │ │ │ ├── DnsAllowlist.tsx │ │ │ │ ├── DnsBlocklist.tsx │ │ │ │ ├── Examples.tsx │ │ │ │ ├── FiltersList.tsx │ │ │ │ ├── Form.tsx │ │ │ │ ├── Modal.tsx │ │ │ │ ├── Rewrites/ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ ├── Modal.tsx │ │ │ │ │ ├── Table.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── Services/ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ ├── ScheduleForm/ │ │ │ │ │ │ ├── Modal.tsx │ │ │ │ │ │ ├── TimePeriod.tsx │ │ │ │ │ │ ├── TimeSelect.tsx │ │ │ │ │ │ ├── Timezone.tsx │ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── styles.css │ │ │ │ │ ├── ServiceField.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── Table.tsx │ │ │ ├── Header/ │ │ │ │ ├── Header.css │ │ │ │ ├── Menu.tsx │ │ │ │ └── index.tsx │ │ │ ├── Logs/ │ │ │ │ ├── AnonymizerNotification.tsx │ │ │ │ ├── Cells/ │ │ │ │ │ ├── ClientCell.tsx │ │ │ │ │ ├── DateCell.tsx │ │ │ │ │ ├── DomainCell.tsx │ │ │ │ │ ├── Header.tsx │ │ │ │ │ ├── HeaderCell.tsx │ │ │ │ │ ├── IconTooltip.css │ │ │ │ │ ├── IconTooltip.tsx │ │ │ │ │ ├── ResponseCell.tsx │ │ │ │ │ ├── helpers/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.tsx │ │ │ │ ├── Disabled.tsx │ │ │ │ ├── Filters/ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ ├── SearchField.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── InfiniteTable.tsx │ │ │ │ ├── Logs.css │ │ │ │ └── index.tsx │ │ │ ├── ProtectionTimer/ │ │ │ │ └── index.ts │ │ │ ├── Settings/ │ │ │ │ ├── Clients/ │ │ │ │ │ ├── AutoClients.tsx │ │ │ │ │ ├── ClientsTable/ │ │ │ │ │ │ ├── ClientsTable.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Form/ │ │ │ │ │ │ ├── components/ │ │ │ │ │ │ │ ├── BlockedServices.tsx │ │ │ │ │ │ │ ├── ClientIds.tsx │ │ │ │ │ │ │ ├── MainSettings.tsx │ │ │ │ │ │ │ ├── ScheduleServices.tsx │ │ │ │ │ │ │ ├── UpstreamDns.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── types.ts │ │ │ │ │ ├── Modal.tsx │ │ │ │ │ ├── Service.css │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── whoisCell.tsx │ │ │ │ ├── Dhcp/ │ │ │ │ │ ├── FormDHCPv4.tsx │ │ │ │ │ ├── FormDHCPv6.tsx │ │ │ │ │ ├── Interfaces.tsx │ │ │ │ │ ├── Leases.tsx │ │ │ │ │ ├── StaticLeases/ │ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ │ ├── Modal.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── index.css │ │ │ │ │ └── index.tsx │ │ │ │ ├── Dns/ │ │ │ │ │ ├── Access/ │ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Cache/ │ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Config/ │ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Upstream/ │ │ │ │ │ │ ├── Examples.tsx │ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── Encryption/ │ │ │ │ │ ├── CertificateStatus.tsx │ │ │ │ │ ├── Form.tsx │ │ │ │ │ ├── KeyStatus.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── FiltersConfig/ │ │ │ │ │ └── index.tsx │ │ │ │ ├── FormButton.css │ │ │ │ ├── LogsConfig/ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── Settings.css │ │ │ │ ├── StatsConfig/ │ │ │ │ │ ├── Form.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── SetupGuide/ │ │ │ │ ├── Guide.css │ │ │ │ └── index.tsx │ │ │ ├── Toasts/ │ │ │ │ ├── Toast.css │ │ │ │ ├── Toast.tsx │ │ │ │ └── index.tsx │ │ │ └── ui/ │ │ │ ├── Card.css │ │ │ ├── Card.tsx │ │ │ ├── Cell.tsx │ │ │ ├── CellWrap.tsx │ │ │ ├── Controls/ │ │ │ │ ├── Checkbox/ │ │ │ │ │ ├── checkbox.css │ │ │ │ │ └── index.tsx │ │ │ │ ├── Input.tsx │ │ │ │ ├── Radio.tsx │ │ │ │ ├── Select.tsx │ │ │ │ └── Textarea.tsx │ │ │ ├── Dropdown.css │ │ │ ├── Dropdown.tsx │ │ │ ├── EncryptionTopline.tsx │ │ │ ├── Footer.css │ │ │ ├── Footer.tsx │ │ │ ├── Guide/ │ │ │ │ ├── Guide.tsx │ │ │ │ ├── MobileConfigForm.tsx │ │ │ │ └── index.ts │ │ │ ├── Icons.css │ │ │ ├── Icons.tsx │ │ │ ├── Line.css │ │ │ ├── Line.tsx │ │ │ ├── Loading.css │ │ │ ├── Loading.tsx │ │ │ ├── LogsSearchLink.tsx │ │ │ ├── Modal.css │ │ │ ├── Overlay.css │ │ │ ├── PageTitle.css │ │ │ ├── PageTitle.tsx │ │ │ ├── ReactTable.css │ │ │ ├── Select.css │ │ │ ├── Status.tsx │ │ │ ├── Tab.tsx │ │ │ ├── Tabler.css │ │ │ ├── Tabs.css │ │ │ ├── Tabs.tsx │ │ │ ├── Tooltip.css │ │ │ ├── Tooltip.tsx │ │ │ ├── Topline.css │ │ │ ├── Topline.tsx │ │ │ ├── UpdateOverlay.tsx │ │ │ ├── UpdateTopline.tsx │ │ │ ├── Version.css │ │ │ ├── Version.tsx │ │ │ ├── svg/ │ │ │ │ └── logo.tsx │ │ │ └── texareaCommentsHighlight.css │ │ ├── configureStore.ts │ │ ├── containers/ │ │ │ ├── Clients.ts │ │ │ ├── CustomRules.ts │ │ │ ├── Dashboard.ts │ │ │ ├── Dhcp.ts │ │ │ ├── Dns.ts │ │ │ ├── DnsAllowlist.ts │ │ │ ├── DnsBlocklist.ts │ │ │ ├── DnsRewrites.ts │ │ │ ├── Encryption.ts │ │ │ ├── Settings.ts │ │ │ └── SetupGuide.ts │ │ ├── helpers/ │ │ │ ├── constants.ts │ │ │ ├── filters/ │ │ │ │ └── filters.ts │ │ │ ├── form.tsx │ │ │ ├── helpers.tsx │ │ │ ├── highlightTextareaComments.tsx │ │ │ ├── localStorageHelper.ts │ │ │ ├── renderFormattedClientCell.tsx │ │ │ ├── trackers/ │ │ │ │ ├── trackers.json │ │ │ │ ├── trackers.ts │ │ │ │ └── whotracksme_web.json │ │ │ ├── twosky.ts │ │ │ ├── useDebounce.ts │ │ │ ├── validators.ts │ │ │ └── version.ts │ │ ├── i18n.ts │ │ ├── index.tsx │ │ ├── initialState.ts │ │ ├── install/ │ │ │ ├── Setup/ │ │ │ │ ├── AddressList.tsx │ │ │ │ ├── Auth.tsx │ │ │ │ ├── Controls.tsx │ │ │ │ ├── Devices.tsx │ │ │ │ ├── Greeting.tsx │ │ │ │ ├── Progress.tsx │ │ │ │ ├── Settings.tsx │ │ │ │ ├── Setup.css │ │ │ │ ├── Submit.tsx │ │ │ │ └── index.tsx │ │ │ └── index.tsx │ │ ├── login/ │ │ │ ├── Login/ │ │ │ │ ├── Form.tsx │ │ │ │ ├── Login.css │ │ │ │ └── index.tsx │ │ │ └── index.tsx │ │ ├── reducers/ │ │ │ ├── access.ts │ │ │ ├── clients.ts │ │ │ ├── dashboard.ts │ │ │ ├── dhcp.ts │ │ │ ├── dnsConfig.ts │ │ │ ├── encryption.ts │ │ │ ├── filtering.ts │ │ │ ├── index.ts │ │ │ ├── install.ts │ │ │ ├── login.ts │ │ │ ├── queryLogs.ts │ │ │ ├── rewrites.ts │ │ │ ├── services.ts │ │ │ ├── settings.ts │ │ │ ├── stats.ts │ │ │ └── toasts.ts │ │ └── types.d.ts │ ├── tests/ │ │ ├── constants.ts │ │ ├── e2e/ │ │ │ ├── control-panel.spec.ts │ │ │ ├── dhcp.spec.ts │ │ │ ├── dns-settings.spec.ts │ │ │ ├── filtering.spec.ts │ │ │ ├── general-settings.spec.ts │ │ │ ├── globalSetup.ts │ │ │ ├── globalTeardown.ts │ │ │ ├── login.spec.ts │ │ │ ├── querylog.spec.ts │ │ │ └── rewrites.spec.ts │ │ └── helpers/ │ │ └── network.ts │ ├── tsconfig.json │ ├── vitest.config.ts │ ├── webpack.common.js │ ├── webpack.dev.js │ └── webpack.prod.js ├── docker/ │ ├── build.Dockerfile │ ├── build.Dockerfile.dockerignore │ ├── ci.Dockerfile │ ├── ci.Dockerfile.dockerignore │ ├── frontend.Dockerfile │ ├── frontend.Dockerfile.dockerignore │ ├── snapcraft.Dockerfile │ └── snapcraft.Dockerfile.dockerignore ├── go.mod ├── go.sum ├── internal/ │ ├── agh/ │ │ └── agh.go │ ├── aghalg/ │ │ ├── aghalg.go │ │ ├── nullbool.go │ │ ├── nullbool_test.go │ │ ├── sortedmap.go │ │ └── sortedmap_test.go │ ├── aghhttp/ │ │ ├── aghhttp.go │ │ ├── header.go │ │ ├── json.go │ │ ├── json_test.go │ │ └── registrar.go │ ├── aghnet/ │ │ ├── addr.go │ │ ├── dhcp.go │ │ ├── dhcp_unix.go │ │ ├── dhcp_windows.go │ │ ├── hostgen.go │ │ ├── hostgen_test.go │ │ ├── hostscontainer.go │ │ ├── hostscontainer_internal_test.go │ │ ├── hostscontainer_test.go │ │ ├── ignore.go │ │ ├── ignore_test.go │ │ ├── interfaces.go │ │ ├── interfaces_bsd.go │ │ ├── interfaces_linux.go │ │ ├── interfaces_test.go │ │ ├── ipmut.go │ │ ├── ipmut_test.go │ │ ├── net.go │ │ ├── net_bsd.go │ │ ├── net_darwin.go │ │ ├── net_darwin_internal_test.go │ │ ├── net_freebsd.go │ │ ├── net_freebsd_internal_test.go │ │ ├── net_internal_test.go │ │ ├── net_linux.go │ │ ├── net_linux_internal_test.go │ │ ├── net_openbsd.go │ │ ├── net_openbsd_internal_test.go │ │ ├── net_test.go │ │ ├── net_unix.go │ │ ├── net_windows.go │ │ ├── upstream.go │ │ └── upstream_test.go │ ├── aghos/ │ │ ├── filewalker.go │ │ ├── filewalker_internal_test.go │ │ ├── filewalker_test.go │ │ ├── fswatcher.go │ │ ├── os.go │ │ ├── os_bsd.go │ │ ├── os_freebsd.go │ │ ├── os_internal_test.go │ │ ├── os_linux.go │ │ ├── os_unix.go │ │ ├── os_windows.go │ │ ├── service.go │ │ ├── service_darwin.go │ │ ├── service_others.go │ │ ├── syslog.go │ │ ├── syslog_others.go │ │ ├── syslog_windows.go │ │ ├── user.go │ │ ├── user_unix.go │ │ └── user_windows.go │ ├── aghrenameio/ │ │ ├── renameio.go │ │ ├── renameio_test.go │ │ ├── renameio_unix.go │ │ └── renameio_windows.go │ ├── aghslog/ │ │ └── aghslog.go │ ├── aghtest/ │ │ ├── aghtest.go │ │ ├── interface.go │ │ ├── interface_test.go │ │ └── upstream.go │ ├── aghtls/ │ │ ├── aghtls.go │ │ ├── aghtls_test.go │ │ ├── defaultmanager.go │ │ ├── manager.go │ │ ├── root.go │ │ ├── root_linux.go │ │ └── root_others.go │ ├── aghuser/ │ │ ├── aghuser.go │ │ ├── aghuser_test.go │ │ ├── db.go │ │ ├── db_test.go │ │ ├── session.go │ │ ├── sessionstorage.go │ │ ├── sessionstorage_test.go │ │ └── user.go │ ├── arpdb/ │ │ ├── arpdb.go │ │ ├── arpdb_bsd.go │ │ ├── arpdb_bsd_internal_test.go │ │ ├── arpdb_internal_test.go │ │ ├── arpdb_linux.go │ │ ├── arpdb_linux_internal_test.go │ │ ├── arpdb_openbsd.go │ │ ├── arpdb_openbsd_internal_test.go │ │ ├── arpdb_windows.go │ │ ├── arpdb_windows_internal_test.go │ │ └── testdata/ │ │ └── proc_net_arp │ ├── client/ │ │ ├── addrproc.go │ │ ├── addrproc_test.go │ │ ├── client.go │ │ ├── client_test.go │ │ ├── index.go │ │ ├── index_internal_test.go │ │ ├── persistent.go │ │ ├── persistent_internal_test.go │ │ ├── runtimeindex.go │ │ ├── storage.go │ │ ├── storage_test.go │ │ └── upstreammanager.go │ ├── configmigrate/ │ │ ├── configmigrate.go │ │ ├── configmigrate_internal_test.go │ │ ├── configmigrate_test.go │ │ ├── migrations_internal_test.go │ │ ├── migrator.go │ │ ├── migrator_test.go │ │ ├── testdata/ │ │ │ └── TestMigrateConfig_Migrate/ │ │ │ ├── v1/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v10/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v11/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v12/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v13/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v14/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v15/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v16/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v17/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v18/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v19/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v2/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v20/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v21/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v22/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v23/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v24/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v25/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v26/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v27/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v28/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v29/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v3/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v30/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v31/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v32/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v33/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v4/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v5/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v6/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v7/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ ├── v8/ │ │ │ │ ├── input.yml │ │ │ │ └── output.yml │ │ │ └── v9/ │ │ │ ├── input.yml │ │ │ └── output.yml │ │ ├── v1.go │ │ ├── v10.go │ │ ├── v11.go │ │ ├── v12.go │ │ ├── v13.go │ │ ├── v14.go │ │ ├── v15.go │ │ ├── v16.go │ │ ├── v17.go │ │ ├── v18.go │ │ ├── v19.go │ │ ├── v2.go │ │ ├── v20.go │ │ ├── v21.go │ │ ├── v22.go │ │ ├── v23.go │ │ ├── v24.go │ │ ├── v25.go │ │ ├── v26.go │ │ ├── v27.go │ │ ├── v28.go │ │ ├── v29.go │ │ ├── v3.go │ │ ├── v30.go │ │ ├── v31.go │ │ ├── v32.go │ │ ├── v33.go │ │ ├── v4.go │ │ ├── v5.go │ │ ├── v6.go │ │ ├── v7.go │ │ ├── v8.go │ │ ├── v9.go │ │ └── yaml.go │ ├── dhcpd/ │ │ ├── README.md │ │ ├── bitset.go │ │ ├── bitset_internal_test.go │ │ ├── broadcast_bsd.go │ │ ├── broadcast_bsd_internal_test.go │ │ ├── broadcast_others.go │ │ ├── broadcast_others_internal_test.go │ │ ├── config.go │ │ ├── conn_bsd.go │ │ ├── conn_bsd_internal_test.go │ │ ├── conn_linux.go │ │ ├── conn_linux_internal_test.go │ │ ├── conn_unix.go │ │ ├── db.go │ │ ├── dhcpd.go │ │ ├── dhcpd_internal_test.go │ │ ├── dhcpd_unix_internal_test.go │ │ ├── http_unix.go │ │ ├── http_unix_internal_test.go │ │ ├── http_windows.go │ │ ├── http_windows_internal_test.go │ │ ├── iprange.go │ │ ├── iprange_internal_test.go │ │ ├── migrate.go │ │ ├── migrate_internal_test.go │ │ ├── options_unix.go │ │ ├── options_unix_internal_test.go │ │ ├── routeradv.go │ │ ├── routeradv_internal_test.go │ │ ├── v46_windows.go │ │ ├── v4_unix.go │ │ ├── v4_unix_internal_test.go │ │ ├── v6_unix.go │ │ └── v6_unix_internal_test.go │ ├── dhcpsvc/ │ │ ├── addresschecker.go │ │ ├── bitset.go │ │ ├── bitset_internal_test.go │ │ ├── config.go │ │ ├── config_test.go │ │ ├── db.go │ │ ├── db_internal_test.go │ │ ├── dhcpsvc.go │ │ ├── dhcpsvc_test.go │ │ ├── errors.go │ │ ├── handle.go │ │ ├── handler4.go │ │ ├── handler4_test.go │ │ ├── handler6.go │ │ ├── interface.go │ │ ├── iprange.go │ │ ├── iprange_internal_test.go │ │ ├── lease.go │ │ ├── lease_internal_test.go │ │ ├── leaseindex.go │ │ ├── networkdevice.go │ │ ├── networkdevice_test.go │ │ ├── options4.go │ │ ├── options4_internal_test.go │ │ ├── options4_test.go │ │ ├── server.go │ │ ├── server_test.go │ │ ├── testdata/ │ │ │ ├── TestDHCPServer_RemoveLease/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_Reset/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_ServeEther4_decline/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_ServeEther4_discover/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_ServeEther4_discoverExpired/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_ServeEther4_release/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_ServeEther4_requestInitReboot/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_ServeEther4_requestRenew/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_ServeEther4_requestSelecting/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_UpdateStaticLease/ │ │ │ │ └── leases.json │ │ │ ├── TestDHCPServer_index/ │ │ │ │ └── leases.json │ │ │ └── TestServer_Leases/ │ │ │ └── leases.json │ │ ├── v4.go │ │ └── v6.go │ ├── dnsforward/ │ │ ├── access.go │ │ ├── access_internal_test.go │ │ ├── clientid.go │ │ ├── clientid_internal_test.go │ │ ├── clientscontainer.go │ │ ├── config.go │ │ ├── config_internal_test.go │ │ ├── configvalidator.go │ │ ├── context.go │ │ ├── dialcontext.go │ │ ├── dns64.go │ │ ├── dns64_internal_test.go │ │ ├── dnsforward.go │ │ ├── dnsforward_internal_test.go │ │ ├── dnsrewrite.go │ │ ├── dnsrewrite_internal_test.go │ │ ├── filter.go │ │ ├── filter_internal_test.go │ │ ├── http.go │ │ ├── http_internal_test.go │ │ ├── ipset.go │ │ ├── ipset_internal_test.go │ │ ├── middleware.go │ │ ├── middleware_internal_test.go │ │ ├── msg.go │ │ ├── process.go │ │ ├── process_internal_test.go │ │ ├── requesthandler.go │ │ ├── requesthandler_internal_test.go │ │ ├── stats.go │ │ ├── stats_internal_test.go │ │ ├── svcbmsg.go │ │ ├── svcbmsg_internal_test.go │ │ ├── testdata/ │ │ │ ├── TestDNSForwardHTTP_handleGetConfig.json │ │ │ └── TestDNSForwardHTTP_handleSetConfig.json │ │ ├── upstreams.go │ │ └── upstreams_internal_test.go │ ├── filtering/ │ │ ├── blocked.go │ │ ├── dnsrewrite.go │ │ ├── dnsrewrite_test.go │ │ ├── filter.go │ │ ├── filter_internal_test.go │ │ ├── filtering.go │ │ ├── filtering_internal_test.go │ │ ├── filtering_test.go │ │ ├── hashprefix/ │ │ │ ├── cache.go │ │ │ ├── cache_internal_test.go │ │ │ ├── hashprefix.go │ │ │ └── hashprefix_internal_test.go │ │ ├── hosts.go │ │ ├── hosts_test.go │ │ ├── http.go │ │ ├── http_internal_test.go │ │ ├── idgenerator.go │ │ ├── idgenerator_internal_test.go │ │ ├── path.go │ │ ├── path_unix_internal_test.go │ │ ├── path_windows_internal_test.go │ │ ├── result.go │ │ ├── rewrite/ │ │ │ ├── item.go │ │ │ ├── item_internal_test.go │ │ │ ├── storage.go │ │ │ └── storage_internal_test.go │ │ ├── rewritehttp.go │ │ ├── rewritehttp_test.go │ │ ├── rewrites.go │ │ ├── rewrites_internal_test.go │ │ ├── rulelist/ │ │ │ ├── engine.go │ │ │ ├── engine_test.go │ │ │ ├── error.go │ │ │ ├── filter.go │ │ │ ├── filter_test.go │ │ │ ├── parser.go │ │ │ ├── parser_test.go │ │ │ ├── rulelist.go │ │ │ ├── rulelist_test.go │ │ │ ├── storage.go │ │ │ ├── storage_test.go │ │ │ ├── textengine.go │ │ │ └── textengine_test.go │ │ ├── safesearch/ │ │ │ ├── rules/ │ │ │ │ ├── bing.txt │ │ │ │ ├── duckduckgo.txt │ │ │ │ ├── ecosia.txt │ │ │ │ ├── google.txt │ │ │ │ ├── pixabay.txt │ │ │ │ ├── yandex.txt │ │ │ │ └── youtube.txt │ │ │ ├── rules.go │ │ │ ├── safesearch.go │ │ │ ├── safesearch_internal_test.go │ │ │ └── safesearch_test.go │ │ ├── safesearch.go │ │ ├── safesearchhttp.go │ │ ├── servicelist.go │ │ └── tests/ │ │ └── dns.txt │ ├── home/ │ │ ├── auth.go │ │ ├── auth_internal_test.go │ │ ├── authglinet.go │ │ ├── authglinet_internal_test.go │ │ ├── authhttp.go │ │ ├── authhttp_internal_test.go │ │ ├── authratelimiter.go │ │ ├── authratelimiter_internal_test.go │ │ ├── clients.go │ │ ├── clients_internal_test.go │ │ ├── clientshttp.go │ │ ├── clientshttp_internal_test.go │ │ ├── config.go │ │ ├── config_internal_test.go │ │ ├── context.go │ │ ├── control.go │ │ ├── controlinstall.go │ │ ├── controlupdate.go │ │ ├── dns.go │ │ ├── home.go │ │ ├── home_internal_test.go │ │ ├── httpclient.go │ │ ├── httpclient_internal_test.go │ │ ├── i18n.go │ │ ├── log.go │ │ ├── middlewares.go │ │ ├── middlewares_internal_test.go │ │ ├── mobileconfig.go │ │ ├── mobileconfig_internal_test.go │ │ ├── options.go │ │ ├── options_internal_test.go │ │ ├── profilehttp.go │ │ ├── profilehttp_internal_test.go │ │ ├── service.go │ │ ├── signal.go │ │ ├── tls.go │ │ ├── tls_internal_test.go │ │ └── web.go │ ├── ipset/ │ │ ├── ipset.go │ │ ├── ipset_linux.go │ │ ├── ipset_linux_internal_test.go │ │ └── ipset_others.go │ ├── next/ │ │ ├── AdGuardHome.example.yaml │ │ ├── agh/ │ │ │ └── agh.go │ │ ├── changelog.md │ │ ├── cmd/ │ │ │ ├── cmd.go │ │ │ ├── log.go │ │ │ ├── opt.go │ │ │ └── service.go │ │ ├── configmgr/ │ │ │ ├── config.go │ │ │ └── configmgr.go │ │ ├── dnssvc/ │ │ │ ├── config.go │ │ │ ├── dnssvc.go │ │ │ └── dnssvc_test.go │ │ ├── jsonpatch/ │ │ │ ├── jsonpatch.go │ │ │ └── jsonpatch_test.go │ │ └── websvc/ │ │ ├── config.go │ │ ├── dns.go │ │ ├── dns_test.go │ │ ├── http.go │ │ ├── http_test.go │ │ ├── middleware.go │ │ ├── route.go │ │ ├── server.go │ │ ├── settings.go │ │ ├── settings_test.go │ │ ├── system.go │ │ ├── system_test.go │ │ ├── websvc.go │ │ └── websvc_test.go │ ├── ossvc/ │ │ ├── action.go │ │ ├── config.go │ │ ├── config_darwin.go │ │ ├── config_freebsd.go │ │ ├── config_linux.go │ │ ├── config_openbsd.go │ │ ├── config_windows.go │ │ ├── defaultaction.go │ │ ├── defaultmanager.go │ │ ├── manager.go │ │ ├── manager_unix.go │ │ ├── manager_windows.go │ │ ├── ossvc.go │ │ ├── reloadmanager.go │ │ ├── service_linux.go │ │ ├── service_openbsd.go │ │ └── service_others.go │ ├── permcheck/ │ │ ├── check_unix.go │ │ ├── check_windows.go │ │ ├── migrate_unix.go │ │ ├── migrate_windows.go │ │ ├── permcheck.go │ │ ├── security_unix.go │ │ └── security_windows.go │ ├── querylog/ │ │ ├── client.go │ │ ├── decode.go │ │ ├── decode_internal_test.go │ │ ├── entry.go │ │ ├── http.go │ │ ├── json.go │ │ ├── qlog.go │ │ ├── qlog_internal_test.go │ │ ├── qlogfile.go │ │ ├── qlogfile_internal_test.go │ │ ├── qlogreader.go │ │ ├── qlogreader_internal_test.go │ │ ├── querylog.go │ │ ├── querylogfile.go │ │ ├── search.go │ │ ├── search_internal_test.go │ │ ├── searchcriterion.go │ │ └── searchparams.go │ ├── rdns/ │ │ ├── rdns.go │ │ └── rdns_test.go │ ├── schedule/ │ │ ├── schedule.go │ │ └── schedule_internal_test.go │ ├── stats/ │ │ ├── http.go │ │ ├── http_internal_test.go │ │ ├── stats.go │ │ ├── stats_internal_test.go │ │ ├── stats_test.go │ │ ├── unit.go │ │ └── unit_internal_test.go │ ├── updater/ │ │ ├── check.go │ │ ├── check_test.go │ │ ├── updater.go │ │ ├── updater_internal_test.go │ │ └── updater_test.go │ ├── version/ │ │ ├── norace.go │ │ ├── race.go │ │ └── version.go │ └── whois/ │ ├── whois.go │ └── whois_test.go ├── main.go ├── main_next.go ├── openapi/ │ ├── CHANGELOG.md │ ├── README.md │ ├── index.html │ ├── next.yaml │ └── openapi.yaml ├── scripts/ │ ├── README.md │ ├── blocked-services/ │ │ └── main.go │ ├── companiesdb/ │ │ └── download.sh │ ├── hooks/ │ │ ├── helper.sh │ │ ├── pre-commit │ │ └── pre-merge-commit │ ├── install.sh │ ├── make/ │ │ ├── build-docker.sh │ │ ├── build-release.sh │ │ ├── go-bench.sh │ │ ├── go-build.sh │ │ ├── go-deps.sh │ │ ├── go-fuzz.sh │ │ ├── go-lint.sh │ │ ├── go-test.sh │ │ ├── go-upd-tools.sh │ │ ├── helper.sh │ │ ├── md-lint.sh │ │ ├── sh-lint.sh │ │ ├── txt-lint.sh │ │ └── version.sh │ ├── snap/ │ │ ├── build.sh │ │ ├── download.sh │ │ └── upload.sh │ ├── translations/ │ │ ├── download.go │ │ ├── main.go │ │ ├── twosky.go │ │ └── upload.go │ └── vetted-filters/ │ └── main.go ├── snap/ │ ├── gui/ │ │ └── adguard-home-web.desktop │ ├── local/ │ │ └── adguard-home-web.sh │ └── snap.tmpl.yaml └── staticcheck.conf
Showing preview only (337K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3787 symbols across 565 files)
FILE: client/constants.js
constant BUILD_ENVS (line 1) | const BUILD_ENVS = {
constant BASE_URL (line 6) | const BASE_URL = 'control';
FILE: client/src/actions/access.ts
type AccessList (line 52) | type AccessList = {
type AccessListValues (line 58) | type AccessListValues = {
type GetNextClientAccessListArgs (line 64) | type GetNextClientAccessListArgs = {
FILE: client/src/api/Api.ts
class Api (line 10) | class Api {
method makeRequest (line 13) | async makeRequest(path: any, method = 'POST', config: any = {}) {
method getGlobalStatus (line 58) | getGlobalStatus() {
method testUpstream (line 64) | testUpstream(servers: any) {
method getGlobalVersion (line 72) | getGlobalVersion(data: any) {
method getUpdate (line 80) | getUpdate() {
method getFilteringStatus (line 103) | getFilteringStatus() {
method refreshFilters (line 109) | refreshFilters(config: any) {
method addFilter (line 118) | addFilter(config: any) {
method removeFilter (line 127) | removeFilter(config: any) {
method setRules (line 136) | setRules(rules: any) {
method setFiltersConfig (line 144) | setFiltersConfig(config: any) {
method setFilterUrl (line 152) | setFilterUrl(config: any) {
method checkHost (line 160) | checkHost(params: any) {
method getParentalStatus (line 174) | getParentalStatus() {
method enableParentalControl (line 180) | enableParentalControl() {
method disableParentalControl (line 186) | disableParentalControl() {
method getSafebrowsingStatus (line 199) | getSafebrowsingStatus() {
method enableSafebrowsing (line 205) | enableSafebrowsing() {
method disableSafebrowsing (line 211) | disableSafebrowsing() {
method getSafesearchStatus (line 222) | getSafesearchStatus() {
method updateSafesearch (line 241) | updateSafesearch(data: any) {
method changeLanguage (line 258) | async changeLanguage(config: any) {
method changeTheme (line 267) | async changeTheme(config: any) {
method getDhcpStatus (line 293) | getDhcpStatus() {
method getDhcpInterfaces (line 299) | getDhcpInterfaces() {
method setDhcpConfig (line 305) | setDhcpConfig(config: any) {
method findActiveDhcp (line 313) | findActiveDhcp(req: any) {
method addStaticLease (line 321) | addStaticLease(config: any) {
method removeStaticLease (line 329) | removeStaticLease(config: any) {
method updateStaticLease (line 337) | updateStaticLease(config: any) {
method resetDhcp (line 345) | resetDhcp() {
method resetDhcpLeases (line 351) | resetDhcpLeases() {
method getDefaultAddresses (line 364) | getDefaultAddresses() {
method setAllSettings (line 370) | setAllSettings(config: any) {
method checkConfig (line 378) | checkConfig(config: any) {
method getTlsStatus (line 393) | getTlsStatus() {
method setTlsConfig (line 399) | setTlsConfig(config: any) {
method validateTlsConfig (line 407) | validateTlsConfig(config: any) {
method getClients (line 426) | getClients() {
method addClient (line 432) | addClient(config: any) {
method deleteClient (line 440) | deleteClient(config: any) {
method updateClient (line 448) | updateClient(config: any) {
method searchClients (line 456) | searchClients(config: any) {
method getAccessList (line 469) | getAccessList() {
method setAccessList (line 475) | setAccessList(config: any) {
method getRewritesList (line 496) | getRewritesList() {
method addRewrite (line 502) | addRewrite(config: any) {
method updateRewrite (line 510) | updateRewrite(config: any) {
method updateRewriteSettings (line 518) | updateRewriteSettings(config: any) {
method deleteRewrite (line 526) | deleteRewrite(config: any) {
method getRewriteSettings (line 534) | getRewriteSettings() {
method getAllBlockedServices (line 547) | getAllBlockedServices() {
method getBlockedServices (line 553) | getBlockedServices() {
method updateBlockedServices (line 559) | updateBlockedServices(config: any) {
method getStats (line 576) | getStats() {
method getStatsConfig (line 582) | getStatsConfig() {
method setStatsConfig (line 588) | setStatsConfig(data: any) {
method resetStats (line 596) | resetStats() {
method getQueryLog (line 611) | getQueryLog(params: any) {
method getQueryLogConfig (line 620) | getQueryLogConfig() {
method setQueryLogConfig (line 626) | setQueryLogConfig(data: any) {
method clearQueryLog (line 634) | clearQueryLog() {
method login (line 643) | login(data: any) {
method getProfile (line 656) | getProfile() {
method setProfile (line 662) | setProfile(data: any) {
method getDnsConfig (line 678) | getDnsConfig() {
method setDnsConfig (line 684) | setDnsConfig(data: any) {
method setProtection (line 694) | setProtection(data: any) {
method clearCache (line 704) | clearCache() {
FILE: client/src/components/App/index.tsx
constant ROUTES (line 50) | const ROUTES = [
FILE: client/src/components/Dashboard/BlockedDomains.tsx
type BlockedDomainsProps (line 25) | interface BlockedDomainsProps {
FILE: client/src/components/Dashboard/Clients.tsx
type ClientsProps (line 150) | interface ClientsProps {
FILE: client/src/components/Dashboard/Counters.tsx
type RowProps (line 16) | interface RowProps {
type CountersProps (line 57) | interface CountersProps {
FILE: client/src/components/Dashboard/DomainCell.tsx
type renderLinkProps (line 16) | interface renderLinkProps {
type DomainCellProps (line 45) | interface DomainCellProps {
FILE: client/src/components/Dashboard/QueriedDomains.tsx
type QueriedDomainsProps (line 34) | interface QueriedDomainsProps {
FILE: client/src/components/Dashboard/Statistics.tsx
type StatisticsProps (line 13) | interface StatisticsProps {
FILE: client/src/components/Dashboard/StatsCard.tsx
type StatsCardProps (line 11) | interface StatsCardProps {
FILE: client/src/components/Dashboard/UpstreamAvgTime.tsx
type TimeCellProps (line 15) | interface TimeCellProps {
type UpstreamAvgTimeProps (line 35) | interface UpstreamAvgTimeProps {
FILE: client/src/components/Dashboard/UpstreamResponses.tsx
type UpstreamResponsesProps (line 34) | interface UpstreamResponsesProps {
FILE: client/src/components/Dashboard/index.tsx
type DashboardProps (line 26) | interface DashboardProps {
FILE: client/src/components/Filters/Actions.tsx
type ActionsProps (line 4) | interface ActionsProps {
FILE: client/src/components/Filters/Check/index.tsx
type FilteringCheckFormValues (line 15) | type FilteringCheckFormValues = {
type Props (line 21) | type Props = {
FILE: client/src/components/Filters/CustomRules.tsx
type CustomRulesProps (line 17) | interface CustomRulesProps {
class CustomRules (line 26) | class CustomRules extends Component<CustomRulesProps> {
method componentDidMount (line 29) | componentDidMount() {
method render (line 67) | render() {
FILE: client/src/components/Filters/DnsAllowlist.tsx
type DnsAllowlistProps (line 14) | interface DnsAllowlistProps {
class DnsAllowlist (line 38) | class DnsAllowlist extends Component<DnsAllowlistProps> {
method componentDidMount (line 39) | componentDidMount() {
method render (line 78) | render() {
FILE: client/src/components/Filters/DnsBlocklist.tsx
type DnsBlocklistProps (line 17) | interface DnsBlocklistProps {
class DnsBlocklist (line 30) | class DnsBlocklist extends Component<DnsBlocklistProps> {
method componentDidMount (line 31) | componentDidMount() {
method render (line 88) | render() {
FILE: client/src/components/Filters/FiltersList.tsx
type Filter (line 33) | type Filter = {
type Category (line 40) | type Category = {
type Props (line 45) | type Props = {
FILE: client/src/components/Filters/Form.tsx
type FormValues (line 11) | type FormValues = {
type Props (line 23) | type Props = {
FILE: client/src/components/Filters/Modal.tsx
constant MODAL_TYPE_TO_TITLE_TYPE_MAP (line 15) | const MODAL_TYPE_TO_TITLE_TYPE_MAP = {
type ModalProps (line 54) | interface ModalProps {
class Modal (line 70) | class Modal extends Component<ModalProps> {
method render (line 75) | render() {
FILE: client/src/components/Filters/Rewrites/Form.tsx
type RewriteFormValues (line 8) | interface RewriteFormValues {
type Props (line 13) | type Props = {
FILE: client/src/components/Filters/Rewrites/Modal.tsx
type ModalProps (line 10) | interface ModalProps {
FILE: client/src/components/Filters/Rewrites/Table.tsx
type TableProps (line 11) | interface TableProps {
class Table (line 24) | class Table extends Component<TableProps> {
method render (line 117) | render() {
FILE: client/src/components/Filters/Rewrites/index.tsx
type RewritesProps (line 15) | interface RewritesProps {
class Rewrites (line 27) | class Rewrites extends Component<RewritesProps> {
method componentDidMount (line 28) | componentDidMount() {
method render (line 68) | render() {
FILE: client/src/components/Filters/Services/Form.tsx
type BlockedService (line 9) | type BlockedService = {
type ServiceGroups (line 16) | type ServiceGroups = {
type FormValues (line 20) | type FormValues = {
type FormProps (line 24) | interface FormProps {
FILE: client/src/components/Filters/Services/ScheduleForm/Modal.tsx
constant DAYS_OF_WEEK (line 14) | const DAYS_OF_WEEK = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
constant INITIAL_START_TIME_MS (line 16) | const INITIAL_START_TIME_MS = 0;
constant INITIAL_END_TIME_MS (line 17) | const INITIAL_END_TIME_MS = 86340000;
type ModalProps (line 19) | interface ModalProps {
FILE: client/src/components/Filters/Services/ScheduleForm/TimePeriod.tsx
type TimePeriodProps (line 5) | interface TimePeriodProps {
FILE: client/src/components/Filters/Services/ScheduleForm/TimeSelect.tsx
type TimeSelectProps (line 5) | interface TimeSelectProps {
FILE: client/src/components/Filters/Services/ScheduleForm/Timezone.tsx
type TimezoneProps (line 7) | interface TimezoneProps {
FILE: client/src/components/Filters/Services/ScheduleForm/index.tsx
type ScheduleFormProps (line 12) | interface ScheduleFormProps {
FILE: client/src/components/Filters/Services/ServiceField.tsx
type Props (line 5) | type Props = ControllerRenderProps<FieldValues> & {
FILE: client/src/components/Filters/Table.tsx
type TableProps (line 15) | interface TableProps {
class Table (line 26) | class Table extends Component<TableProps> {
method render (line 140) | render() {
FILE: client/src/components/Header/Menu.tsx
constant MENU_ITEMS (line 12) | const MENU_ITEMS = [
constant SETTINGS_ITEMS (line 39) | const SETTINGS_ITEMS = [
constant FILTERS_ITEMS (line 62) | const FILTERS_ITEMS = [
type MenuProps (line 85) | interface MenuProps {
class Menu (line 92) | class Menu extends Component<MenuProps> {
method render (line 142) | render() {
FILE: client/src/components/Logs/Cells/ClientCell.tsx
type ClientCellProps (line 23) | interface ClientCellProps {
FILE: client/src/components/Logs/Cells/DateCell.tsx
type DateCellProps (line 8) | interface DateCellProps {
FILE: client/src/components/Logs/Cells/DomainCell.tsx
type DomainCellProps (line 17) | interface DomainCellProps {
FILE: client/src/components/Logs/Cells/HeaderCell.tsx
type HeaderCellProps (line 5) | interface HeaderCellProps {
FILE: client/src/components/Logs/Cells/IconTooltip.tsx
type IconTooltipProps (line 14) | interface IconTooltipProps {
FILE: client/src/components/Logs/Cells/ResponseCell.tsx
type ResponseCellProps (line 11) | interface ResponseCellProps {
FILE: client/src/components/Logs/Cells/helpers/index.ts
constant BUTTON_PREFIX (line 4) | const BUTTON_PREFIX = 'btn_';
FILE: client/src/components/Logs/Cells/index.tsx
type RowProps (line 44) | interface RowProps {
FILE: client/src/components/Logs/Filters/Form.tsx
type Props (line 25) | type Props = {
FILE: client/src/components/Logs/Filters/SearchField.tsx
type Props (line 4) | interface Props extends ComponentProps<'input'> {
FILE: client/src/components/Logs/Filters/index.tsx
type FiltersProps (line 9) | interface FiltersProps {
FILE: client/src/components/Logs/InfiniteTable.tsx
type InfiniteTableProps (line 17) | interface InfiniteTableProps {
FILE: client/src/components/Logs/index.tsx
type SearchFormValues (line 33) | type SearchFormValues = {
FILE: client/src/components/ProtectionTimer/index.ts
type ProtectionTimerProps (line 10) | interface ProtectionTimerProps {
FILE: client/src/components/Settings/Clients/AutoClients.tsx
constant COLUMN_MIN_WIDTH (line 19) | const COLUMN_MIN_WIDTH = 200;
type AutoClientsProps (line 21) | interface AutoClientsProps {
class AutoClients (line 27) | class AutoClients extends Component<AutoClientsProps> {
method render (line 80) | render() {
FILE: client/src/components/Settings/Clients/ClientsTable/ClientsTable.tsx
type ClientsTableProps (line 28) | interface ClientsTableProps {
FILE: client/src/components/Settings/Clients/Form/components/BlockedServices.tsx
type Props (line 8) | type Props = {
FILE: client/src/components/Settings/Clients/Form/components/MainSettings.tsx
type ProtectionSettings (line 9) | type ProtectionSettings = 'use_global_settings' | 'filtering_enabled' | ...
type LogsStatsSettings (line 33) | type LogsStatsSettings = 'ignore_querylog' | 'ignore_statistics';
type Props (line 46) | type Props = {
FILE: client/src/components/Settings/Clients/Form/index.tsx
type Props (line 38) | type Props = {
FILE: client/src/components/Settings/Clients/Form/types.ts
type ClientForm (line 1) | type ClientForm = {
type SubmitClientForm (line 25) | type SubmitClientForm = Omit<ClientForm, 'ids' | 'tags'> & {
FILE: client/src/components/Settings/Clients/Modal.tsx
type ModalProps (line 47) | interface ModalProps {
FILE: client/src/components/Settings/Clients/index.tsx
type ClientsProps (line 13) | interface ClientsProps {
class Clients (line 26) | class Clients extends Component<ClientsProps> {
method componentDidMount (line 27) | componentDidMount() {
method render (line 33) | render() {
FILE: client/src/components/Settings/Dhcp/FormDHCPv4.tsx
type FormDHCPv4Props (line 18) | type FormDHCPv4Props = {
FILE: client/src/components/Settings/Dhcp/FormDHCPv6.tsx
type FormDHCPv6Props (line 11) | type FormDHCPv6Props = {
FILE: client/src/components/Settings/Dhcp/Interfaces.tsx
type RenderInterfaceValuesProps (line 48) | interface RenderInterfaceValuesProps {
FILE: client/src/components/Settings/Dhcp/Leases.tsx
type LeasesProps (line 13) | interface LeasesProps {
class Leases (line 20) | class Leases extends Component<LeasesProps> {
method render (line 57) | render() {
FILE: client/src/components/Settings/Dhcp/StaticLeases/Form.tsx
type Props (line 19) | type Props = {
FILE: client/src/components/Settings/Dhcp/StaticLeases/Modal.tsx
type ModalProps (line 13) | interface ModalProps {
FILE: client/src/components/Settings/Dhcp/StaticLeases/index.tsx
type cellWrapProps (line 14) | interface cellWrapProps {
type StaticLeasesProps (line 26) | interface StaticLeasesProps {
FILE: client/src/components/Settings/Dhcp/index.tsx
type IPv4FormValues (line 43) | type IPv4FormValues = {
type IPv6FormValues (line 51) | type IPv6FormValues = {
type DhcpFormValues (line 72) | type DhcpFormValues = {
constant DEFAULT_V4_VALUES (line 78) | const DEFAULT_V4_VALUES = {
constant DEFAULT_V6_VALUES (line 86) | const DEFAULT_V6_VALUES = {
FILE: client/src/components/Settings/Dns/Access/Form.tsx
type FormData (line 10) | type FormData = {
type FormProps (line 56) | type FormProps = {
FILE: client/src/components/Settings/Dns/Cache/Form.tsx
constant INPUTS_FIELDS (line 13) | const INPUTS_FIELDS = [
type FormData (line 34) | type FormData = {
type CacheFormProps (line 42) | type CacheFormProps = {
FILE: client/src/components/Settings/Dns/Config/Form.tsx
type FormData (line 83) | type FormData = {
type Props (line 99) | type Props = {
FILE: client/src/components/Settings/Dns/Upstream/Examples.tsx
type ExamplesProps (line 5) | interface ExamplesProps {
FILE: client/src/components/Settings/Dns/Upstream/Form.tsx
constant UPSTREAM_DNS_NAME (line 22) | const UPSTREAM_DNS_NAME = 'upstream_dns';
type FormData (line 24) | type FormData = {
type FormProps (line 35) | type FormProps = {
FILE: client/src/components/Settings/Encryption/CertificateStatus.tsx
type CertificateStatusProps (line 7) | interface CertificateStatusProps {
FILE: client/src/components/Settings/Encryption/Form.tsx
type EncryptionFormValues (line 76) | type EncryptionFormValues = {
type Props (line 93) | type Props = {
FILE: client/src/components/Settings/Encryption/KeyStatus.tsx
type KeyStatusProps (line 4) | interface KeyStatusProps {
FILE: client/src/components/Settings/Encryption/index.tsx
type Props (line 12) | type Props = {
FILE: client/src/components/Settings/FiltersConfig/index.tsx
constant THREE_DAYS_INTERVAL (line 11) | const THREE_DAYS_INTERVAL = DAY * 3;
constant SEVEN_DAYS_INTERVAL (line 12) | const SEVEN_DAYS_INTERVAL = DAY * 7;
type FormValues (line 26) | type FormValues = {
type Props (line 31) | type Props = {
FILE: client/src/components/Settings/LogsConfig/Form.tsx
type FormValues (line 27) | type FormValues = {
type Props (line 36) | type Props = {
FILE: client/src/components/Settings/LogsConfig/index.tsx
type LogsConfigProps (line 9) | interface LogsConfigProps {
class LogsConfig (line 23) | class LogsConfig extends Component<LogsConfigProps> {
method render (line 54) | render() {
FILE: client/src/components/Settings/StatsConfig/Form.tsx
type FormValues (line 25) | type FormValues = {
type Props (line 41) | type Props = {
FILE: client/src/components/Settings/StatsConfig/index.tsx
type StatsConfigProps (line 9) | interface StatsConfigProps {
class StatsConfig (line 22) | class StatsConfig extends Component<StatsConfigProps> {
method render (line 51) | render() {
FILE: client/src/components/Settings/index.tsx
constant ORDER_KEY (line 23) | const ORDER_KEY = 'order';
constant SETTINGS (line 25) | const SETTINGS = {
type SettingsProps (line 42) | interface SettingsProps {
class Settings (line 83) | class Settings extends Component<SettingsProps> {
method componentDidMount (line 84) | componentDidMount() {
method render (line 154) | render() {
FILE: client/src/components/SetupGuide/index.tsx
type SetupGuideProps (line 12) | interface SetupGuideProps {
FILE: client/src/components/Toasts/Toast.tsx
type ToastProps (line 8) | interface ToastProps {
FILE: client/src/components/ui/Card.tsx
type CardProps (line 5) | interface CardProps {
FILE: client/src/components/ui/Cell.tsx
type CellProps (line 7) | interface CellProps {
FILE: client/src/components/ui/CellWrap.tsx
type CellWrapProps (line 3) | interface CellWrapProps {
FILE: client/src/components/ui/Controls/Checkbox/index.tsx
type Props (line 6) | type Props = {
FILE: client/src/components/ui/Controls/Input.tsx
type Props (line 4) | type Props = ComponentProps<'input'> & {
FILE: client/src/components/ui/Controls/Radio.tsx
type Props (line 3) | type Props<T> = {
FILE: client/src/components/ui/Controls/Select.tsx
type SelectProps (line 4) | type SelectProps = ComponentProps<'select'> & {
FILE: client/src/components/ui/Controls/Textarea.tsx
type Props (line 5) | type Props = ComponentProps<'textarea'> & {
FILE: client/src/components/ui/Dropdown.tsx
type DropdownProps (line 9) | type DropdownProps = {
type DropdownState (line 18) | type DropdownState = {
class Dropdown (line 22) | class Dropdown extends Component<DropdownProps, DropdownState> {
method render (line 41) | render() {
FILE: client/src/components/ui/EncryptionTopline.tsx
constant EXPIRATION_ENUM (line 11) | const EXPIRATION_ENUM = {
constant EXPIRATION_STATE (line 17) | const EXPIRATION_STATE = {
FILE: client/src/components/ui/Guide/Guide.tsx
type renderLiProps (line 13) | interface renderLiProps {
type renderDnsPrivacyListProps (line 161) | interface renderDnsPrivacyListProps {
type renderContentProps (line 320) | interface renderContentProps {
type GuideProps (line 345) | interface GuideProps {
FILE: client/src/components/ui/Guide/MobileConfigForm.tsx
type FormValues (line 44) | type FormValues = {
type Props (line 51) | type Props = {
FILE: client/src/components/ui/Line.tsx
type LineProps (line 15) | interface LineProps {
FILE: client/src/components/ui/Loading.tsx
type LoadingProps (line 6) | interface LoadingProps {
FILE: client/src/components/ui/LogsSearchLink.tsx
type LogsSearchLinkProps (line 9) | interface LogsSearchLinkProps {
FILE: client/src/components/ui/PageTitle.tsx
type PageTitleProps (line 5) | interface PageTitleProps {
FILE: client/src/components/ui/Status.tsx
type StatusProps (line 6) | interface StatusProps {
FILE: client/src/components/ui/Tab.tsx
type TabProps (line 5) | interface TabProps {
FILE: client/src/components/ui/Tabs.tsx
type TabsProps (line 7) | interface TabsProps {
FILE: client/src/components/ui/Tooltip.tsx
type TooltipProps (line 10) | interface TooltipProps {
type renderTooltipProps (line 23) | interface renderTooltipProps {
type renderTriggerProps (line 28) | interface renderTriggerProps {
FILE: client/src/components/ui/Topline.tsx
type ToplineProps (line 5) | interface ToplineProps {
FILE: client/src/components/ui/svg/logo.tsx
type Props (line 3) | type Props = {
FILE: client/src/configureStore.ts
function configureStore (line 6) | function configureStore<T>(
FILE: client/src/containers/Clients.ts
type DispatchProps (line 19) | type DispatchProps = {
FILE: client/src/containers/CustomRules.ts
type DispatchProps (line 13) | type DispatchProps = {
FILE: client/src/containers/Dashboard.ts
type DispatchProps (line 16) | type DispatchProps = {
FILE: client/src/containers/DnsRewrites.ts
type DispatchProps (line 13) | type DispatchProps = {
FILE: client/src/helpers/constants.ts
constant R_URL_REQUIRES_PROTOCOL (line 1) | const R_URL_REQUIRES_PROTOCOL = /^https?:\/\/[^/\s]+(\/.*)?$/;
constant R_HOST (line 4) | const R_HOST = /^(\*\.)?[\w.-]+$/;
constant R_IPV4 (line 6) | const R_IPV4 = /^(?:(?:^|\.)(?:2(?:5[0-5]|[0-4]\d)|1?\d?\d)){4}$/;
constant R_IPV6 (line 8) | const R_IPV6 =
constant R_CIDR (line 11) | const R_CIDR =
constant R_MAC (line 14) | const R_MAC =
constant R_MAC_WITHOUT_COLON (line 16) | const R_MAC_WITHOUT_COLON = /^([a-fA-F0-9]{2}){5}([a-fA-F0-9]{2})$|^([a-...
constant R_CIDR_IPV6 (line 18) | const R_CIDR_IPV6 =
constant R_DOMAIN (line 21) | const R_DOMAIN = /^([a-zA-Z0-9][a-zA-Z0-9-_]*\.)*[a-zA-Z0-9]*[a-zA-Z0-9-...
constant R_PATH_LAST_PART (line 23) | const R_PATH_LAST_PART = /\/[^/]*$/;
constant R_UNIX_ABSOLUTE_PATH (line 26) | const R_UNIX_ABSOLUTE_PATH = /^(\/[^/\x00]+)+$/;
constant R_WIN_ABSOLUTE_PATH (line 29) | const R_WIN_ABSOLUTE_PATH = /^([a-zA-Z]:)?(\\|\/)(?:[^\\/:*?"<>|\x00]+\\...
constant R_CLIENT_ID (line 31) | const R_CLIENT_ID = /^[a-z0-9-]{1,63}$/;
constant R_IPV4_SUBNET (line 33) | const R_IPV4_SUBNET = /^([0-9]|[1-2][0-9]|3[0-2])?$/;
constant R_IPV6_SUBNET (line 35) | const R_IPV6_SUBNET = /^([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])?$/;
constant MIN_PASSWORD_LENGTH (line 37) | const MIN_PASSWORD_LENGTH = 8;
constant MAX_PASSWORD_LENGTH (line 38) | const MAX_PASSWORD_LENGTH = 72;
constant HTML_PAGES (line 40) | const HTML_PAGES = {
constant STATS_NAMES (line 46) | const STATS_NAMES = {
constant STATUS_COLORS (line 55) | const STATUS_COLORS = {
constant REPOSITORY (line 62) | const REPOSITORY = {
constant CLIENT_ID_LINK (line 68) | const CLIENT_ID_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/...
constant MANUAL_UPDATE_LINK (line 69) | const MANUAL_UPDATE_LINK = 'https://github.com/AdguardTeam/AdGuardHome/w...
constant PORT_53_FAQ_LINK (line 70) | const PORT_53_FAQ_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wik...
constant PRIVACY_POLICY_LINK (line 71) | const PRIVACY_POLICY_LINK = 'https://link.adtidy.org/forward.html?action...
constant UPSTREAM_CONFIGURATION_WIKI_LINK (line 72) | const UPSTREAM_CONFIGURATION_WIKI_LINK =
constant FILTERS_RELATIVE_LINK (line 75) | const FILTERS_RELATIVE_LINK = '#filters';
constant ADDRESS_IN_USE_TEXT (line 77) | const ADDRESS_IN_USE_TEXT = 'address already in use';
constant INSTALL_FIRST_STEP (line 79) | const INSTALL_FIRST_STEP = 1;
constant INSTALL_TOTAL_STEPS (line 80) | const INSTALL_TOTAL_STEPS = 5;
constant SETTINGS_NAMES (line 82) | const SETTINGS_NAMES = {
constant STANDARD_DNS_PORT (line 89) | const STANDARD_DNS_PORT = 53;
constant STANDARD_WEB_PORT (line 90) | const STANDARD_WEB_PORT = 80;
constant STANDARD_HTTPS_PORT (line 91) | const STANDARD_HTTPS_PORT = 443;
constant DNS_OVER_TLS_PORT (line 92) | const DNS_OVER_TLS_PORT = 853;
constant DNS_OVER_QUIC_PORT (line 93) | const DNS_OVER_QUIC_PORT = 853;
constant MIN_PORT (line 94) | const MIN_PORT = 1;
constant MAX_PORT (line 95) | const MAX_PORT = 65535;
constant EMPTY_DATE (line 97) | const EMPTY_DATE = '0001-01-01T00:00:00Z';
constant DEBOUNCE_TIMEOUT (line 99) | const DEBOUNCE_TIMEOUT = 300;
constant DEBOUNCE_FILTER_TIMEOUT (line 100) | const DEBOUNCE_FILTER_TIMEOUT = 500;
constant CHECK_TIMEOUT (line 101) | const CHECK_TIMEOUT = 1000;
constant HIDE_TOOLTIP_DELAY (line 102) | const HIDE_TOOLTIP_DELAY = 300;
constant SHOW_TOOLTIP_DELAY (line 103) | const SHOW_TOOLTIP_DELAY = 200;
constant MODAL_OPEN_TIMEOUT (line 104) | const MODAL_OPEN_TIMEOUT = 150;
constant UNSAFE_PORTS (line 106) | const UNSAFE_PORTS = [
constant ALL_INTERFACES_IP (line 112) | const ALL_INTERFACES_IP = '0.0.0.0';
constant STATUS_RESPONSE (line 114) | const STATUS_RESPONSE = {
constant MODAL_TYPE (line 120) | const MODAL_TYPE = {
constant CLIENT_ID (line 133) | const CLIENT_ID = {
constant MENU_URLS (line 138) | const MENU_URLS = {
constant SETTINGS_URLS (line 144) | const SETTINGS_URLS = {
constant FILTERS_URLS (line 152) | const FILTERS_URLS = {
constant ENCRYPTION_SOURCE (line 160) | const ENCRYPTION_SOURCE = {
constant FILTERED (line 165) | const FILTERED = 'Filtered';
constant NOT_FILTERED (line 166) | const NOT_FILTERED = 'NotFiltered';
constant DISABLED_STATS_INTERVAL (line 168) | const DISABLED_STATS_INTERVAL = 0;
constant HOUR (line 170) | const HOUR = 60 * 60 * 1000;
constant DAY (line 172) | const DAY = HOUR * 24;
constant STATS_INTERVALS_DAYS (line 174) | const STATS_INTERVALS_DAYS = [DAY, DAY * 7, DAY * 30, DAY * 90];
constant QUERY_LOG_INTERVALS_DAYS (line 176) | const QUERY_LOG_INTERVALS_DAYS = [HOUR * 6, DAY, DAY * 7, DAY * 30, DAY ...
constant RETENTION_CUSTOM (line 178) | const RETENTION_CUSTOM = 1;
constant RETENTION_CUSTOM_INPUT (line 180) | const RETENTION_CUSTOM_INPUT = 'custom_retention_input';
constant CUSTOM_INTERVAL (line 182) | const CUSTOM_INTERVAL = 'customInterval';
constant FILTERS_INTERVALS_HOURS (line 184) | const FILTERS_INTERVALS_HOURS = [0, 1, 12, 24, 72, 168];
constant BLOCKING_MODES (line 188) | const BLOCKING_MODES = {
constant THEMES (line 198) | const THEMES = {
constant WHOIS_ICONS (line 204) | const WHOIS_ICONS = {
constant DEFAULT_LOGS_FILTER (line 211) | const DEFAULT_LOGS_FILTER = {
constant DEFAULT_LANGUAGE (line 216) | const DEFAULT_LANGUAGE = 'en';
constant QUERY_LOGS_PAGE_LIMIT (line 218) | const QUERY_LOGS_PAGE_LIMIT = 20;
constant LEASES_TABLE_DEFAULT_PAGE_SIZE (line 220) | const LEASES_TABLE_DEFAULT_PAGE_SIZE = 20;
constant FILTERED_STATUS (line 222) | const FILTERED_STATUS = {
constant RESPONSE_FILTER (line 235) | const RESPONSE_FILTER = {
constant RESPONSE_FILTER_QUERIES (line 278) | const RESPONSE_FILTER_QUERIES = Object.values(RESPONSE_FILTER).reduce(
constant QUERY_STATUS_COLORS (line 293) | const QUERY_STATUS_COLORS = {
constant FILTERED_STATUS_TO_META_MAP (line 301) | const FILTERED_STATUS_TO_META_MAP = {
constant DEFAULT_TIME_FORMAT (line 344) | const DEFAULT_TIME_FORMAT = 'HH:mm:ss';
constant LONG_TIME_FORMAT (line 346) | const LONG_TIME_FORMAT = 'HH:mm:ss.SSS';
constant DEFAULT_SHORT_DATE_FORMAT_OPTIONS (line 348) | const DEFAULT_SHORT_DATE_FORMAT_OPTIONS = {
constant DEFAULT_DATE_FORMAT_OPTIONS (line 355) | const DEFAULT_DATE_FORMAT_OPTIONS = {
constant DETAILED_DATE_FORMAT_OPTIONS (line 364) | const DETAILED_DATE_FORMAT_OPTIONS = {
constant SPECIAL_FILTER_ID (line 369) | const SPECIAL_FILTER_ID = {
constant BLOCK_ACTIONS (line 378) | const BLOCK_ACTIONS = {
constant SCHEME_TO_PROTOCOL_MAP (line 383) | const SCHEME_TO_PROTOCOL_MAP = {
constant DNS_REQUEST_OPTIONS (line 391) | const DNS_REQUEST_OPTIONS = {
constant DHCP_FORM_NAMES (line 397) | const DHCP_FORM_NAMES = {
constant FORM_NAME (line 403) | const FORM_NAME = {
constant SMALL_SCREEN_SIZE (line 425) | const SMALL_SCREEN_SIZE = 767;
constant MEDIUM_SCREEN_SIZE (line 426) | const MEDIUM_SCREEN_SIZE = 1024;
constant SECONDS_IN_DAY (line 428) | const SECONDS_IN_DAY = 60 * 60 * 24;
constant UINT32_RANGE (line 430) | const UINT32_RANGE = {
constant RETENTION_RANGE (line 435) | const RETENTION_RANGE = {
constant DHCP_VALUES_PLACEHOLDERS (line 440) | const DHCP_VALUES_PLACEHOLDERS = {
constant DHCP_DESCRIPTION_PLACEHOLDERS (line 452) | const DHCP_DESCRIPTION_PLACEHOLDERS = {
constant TOAST_TRANSITION_TIMEOUT (line 467) | const TOAST_TRANSITION_TIMEOUT = 500;
constant TOAST_TYPES (line 469) | const TOAST_TYPES = {
constant SUCCESS_TOAST_TIMEOUT (line 475) | const SUCCESS_TOAST_TIMEOUT = 5000;
constant ONE_SECOND_IN_MS (line 477) | const ONE_SECOND_IN_MS = 1000;
constant FAILURE_TOAST_TIMEOUT (line 478) | const FAILURE_TOAST_TIMEOUT = 30000;
constant TOAST_TIMEOUTS (line 480) | const TOAST_TIMEOUTS = {
constant ADDRESS_TYPES (line 486) | const ADDRESS_TYPES = {
constant CACHE_CONFIG_FIELDS (line 493) | const CACHE_CONFIG_FIELDS = {
constant COMMENT_LINE_DEFAULT_TOKEN (line 500) | const COMMENT_LINE_DEFAULT_TOKEN = '#';
constant MOBILE_CONFIG_LINKS (line 502) | const MOBILE_CONFIG_LINKS = {
constant DISABLE_PROTECTION_TIMINGS (line 508) | const DISABLE_PROTECTION_TIMINGS = {
constant LOCAL_TIMEZONE_VALUE (line 516) | const LOCAL_TIMEZONE_VALUE = 'Local';
constant TABLES_MIN_ROWS (line 518) | const TABLES_MIN_ROWS = 5;
constant DASHBOARD_TABLES_DEFAULT_PAGE_SIZE (line 520) | const DASHBOARD_TABLES_DEFAULT_PAGE_SIZE = 100;
constant TIME_UNITS (line 522) | const TIME_UNITS = {
constant DNS_RECORD_TYPES (line 527) | const DNS_RECORD_TYPES = [
FILE: client/src/helpers/helpers.tsx
type NestedObject (line 759) | type NestedObject = {
type Filter (line 860) | type Filter = {
type Rule (line 869) | type Rule = {
FILE: client/src/helpers/localStorageHelper.ts
constant LOCAL_STORAGE_KEYS (line 1) | const LOCAL_STORAGE_KEYS = {
method setItem (line 11) | setItem(key: any, value: any) {
method getItem (line 19) | getItem(key: any) {
method removeItem (line 29) | removeItem(key: any) {
method clear (line 37) | clear() {
FILE: client/src/helpers/twosky.ts
constant LANGUAGES (line 4) | const LANGUAGES = twosky[0].languages;
constant BASE_LOCALE (line 5) | const BASE_LOCALE = twosky[0].base_locale;
FILE: client/src/initialState.ts
type InstallInterface (line 12) | type InstallInterface = {
type InstallData (line 20) | type InstallData = {
type EncryptionData (line 46) | type EncryptionData = {
type Client (line 80) | type Client = {
type AutoClient (line 109) | type AutoClient = {
type DashboardData (line 116) | type DashboardData = {
type SettingsData (line 145) | type SettingsData = {
type RewritesData (line 166) | type RewritesData = {
type NormalizedTopClients (line 188) | type NormalizedTopClients = {
type StatsData (line 193) | type StatsData = {
type ClientsData (line 225) | type ClientsData = {
type AccessData (line 235) | type AccessData = {
type DhcpInterface (line 243) | type DhcpInterface = {
type DhcpData (line 253) | type DhcpData = {
type DnsConfigData (line 306) | type DnsConfigData = {
type FilteringData (line 339) | type FilteringData = {
type QueryLogsData (line 360) | type QueryLogsData = {
type ServicesData (line 379) | type ServicesData = {
type RootState (line 388) | type RootState = {
type InstallState (line 406) | type InstallState = {
type LoginState (line 411) | type LoginState = {
FILE: client/src/install/Setup/AddressList.tsx
type renderItemProps (line 7) | interface renderItemProps {
type AddressListProps (line 30) | interface AddressListProps {
FILE: client/src/install/Setup/Auth.tsx
type AuthFormValues (line 8) | type AuthFormValues = {
type Props (line 14) | type Props = {
FILE: client/src/install/Setup/Controls.tsx
type ControlsProps (line 7) | interface ControlsProps {
class Controls (line 28) | class Controls extends Component<ControlsProps> {
method renderPrevButton (line 29) | renderPrevButton(step: any) {
method renderNextButton (line 47) | renderNextButton(step: any) {
method render (line 97) | render() {
FILE: client/src/install/Setup/Devices.tsx
type Props (line 13) | type Props = {
FILE: client/src/install/Setup/Progress.tsx
type Props (line 8) | type Props = {
FILE: client/src/install/Setup/Settings.tsx
type WebConfig (line 34) | type WebConfig = {
type DnsConfig (line 39) | type DnsConfig = {
type SettingsFormValues (line 44) | type SettingsFormValues = {
type StaticIpType (line 49) | type StaticIpType = {
type ConfigType (line 54) | type ConfigType = {
type Props (line 70) | type Props = {
FILE: client/src/install/Setup/Submit.tsx
type Props (line 8) | type Props = {
FILE: client/src/login/Login/Form.tsx
type LoginFormValues (line 7) | type LoginFormValues = {
type LoginFormProps (line 12) | type LoginFormProps = {
FILE: client/src/reducers/dnsConfig.ts
constant DEFAULT_BLOCKING_IPV4 (line 6) | const DEFAULT_BLOCKING_IPV4 = ALL_INTERFACES_IP;
constant DEFAULT_BLOCKING_IPV6 (line 7) | const DEFAULT_BLOCKING_IPV6 = '::';
FILE: client/src/types.d.ts
type Window (line 2) | interface Window {
FILE: client/tests/constants.ts
constant ADMIN_USERNAME (line 1) | const ADMIN_USERNAME = 'admin';
constant ADMIN_PASSWORD (line 2) | const ADMIN_PASSWORD = 'superpassword';
constant PORT (line 3) | const PORT = 3000;
constant CONFIG_FILE_PATH (line 4) | const CONFIG_FILE_PATH = '/tmp/AdGuard.e2e.yaml';
FILE: client/tests/e2e/dhcp.spec.ts
constant INTERFACE_NAME (line 6) | const INTERFACE_NAME = dhcpConfig.interfaceName;
constant RANGE_START (line 7) | const RANGE_START = dhcpConfig.rangeStart;
constant RANGE_END (line 8) | const RANGE_END = dhcpConfig.rangeEnd;
constant SUBNET_MASK (line 9) | const SUBNET_MASK = dhcpConfig.subnetMask;
constant LEASE_TIME (line 10) | const LEASE_TIME = '86400';
FILE: client/tests/e2e/globalSetup.ts
constant BASE_URL (line 5) | const BASE_URL = `http://127.0.0.1:${PORT}`;
function checkServerAvailable (line 7) | async function checkServerAvailable(): Promise<boolean> {
function globalSetup (line 16) | async function globalSetup(config: FullConfig) {
FILE: client/tests/e2e/globalTeardown.ts
function globalTeardown (line 4) | async function globalTeardown() {
FILE: client/tests/e2e/rewrites.spec.ts
constant EXAMPLE_DOMAIN (line 4) | const EXAMPLE_DOMAIN = `example.org`;
constant EXAMPLE_UPDATED_DOMAIN (line 5) | const EXAMPLE_UPDATED_DOMAIN = `updated.org`;
constant EXAMPLE_ANSWER (line 6) | const EXAMPLE_ANSWER = '192.168.1.1';
FILE: client/tests/helpers/network.ts
type DHCPConfig (line 4) | interface DHCPConfig {
constant DEFAULT_SUBNET_MASK (line 11) | const DEFAULT_SUBNET_MASK = '255.255.255.0';
constant DEFAULT_SUBNET_MASK_OCTETS (line 12) | const DEFAULT_SUBNET_MASK_OCTETS = DEFAULT_SUBNET_MASK.split('.').map(Nu...
function checkIsIPv4 (line 14) | function checkIsIPv4(addr: NetworkInterfaceInfo): boolean {
function calculateNetwork (line 18) | function calculateNetwork(ip: number[], mask: number[]): number[] {
function calculateBroadcast (line 24) | function calculateBroadcast(network: number[], mask: number[]): number[] {
function getDHCPConfig (line 30) | function getDHCPConfig(): DHCPConfig {
FILE: client/webpack.common.js
constant RESOURCES_PATH (line 12) | const RESOURCES_PATH = path.resolve(__dirname);
constant ENTRY_REACT (line 13) | const ENTRY_REACT = path.resolve(RESOURCES_PATH, 'src/index.tsx');
constant ENTRY_INSTALL (line 14) | const ENTRY_INSTALL = path.resolve(RESOURCES_PATH, 'src/install/index.ts...
constant ENTRY_LOGIN (line 15) | const ENTRY_LOGIN = path.resolve(RESOURCES_PATH, 'src/login/index.tsx');
constant HTML_PATH (line 16) | const HTML_PATH = path.resolve(RESOURCES_PATH, 'public/index.html');
constant HTML_INSTALL_PATH (line 17) | const HTML_INSTALL_PATH = path.resolve(RESOURCES_PATH, 'public/install.h...
constant HTML_LOGIN_PATH (line 18) | const HTML_LOGIN_PATH = path.resolve(RESOURCES_PATH, 'public/login.html');
constant ASSETS_PATH (line 19) | const ASSETS_PATH = path.resolve(RESOURCES_PATH, 'public/assets');
constant PUBLIC_PATH (line 21) | const PUBLIC_PATH = path.resolve(__dirname, '../build/static');
constant PUBLIC_ASSETS_PATH (line 22) | const PUBLIC_ASSETS_PATH = path.resolve(PUBLIC_PATH, 'assets');
constant BUILD_ENV (line 24) | const BUILD_ENV = BUILD_ENVS[process.env.BUILD_ENV];
FILE: client/webpack.dev.js
constant ZERO_HOST (line 7) | const ZERO_HOST = '0.0.0.0';
constant LOCALHOST (line 8) | const LOCALHOST = '127.0.0.1';
constant DEFAULT_PORT (line 9) | const DEFAULT_PORT = 80;
FILE: internal/agh/agh.go
constant DefaultOutputLimit (line 16) | DefaultOutputLimit = 512
type ConfigModifier (line 19) | type ConfigModifier interface
type EmptyConfigModifier (line 26) | type EmptyConfigModifier struct
method Apply (line 32) | func (em EmptyConfigModifier) Apply(ctx context.Context) {}
type exitErr (line 38) | type exitErr struct
method Error (line 51) | func (e exitErr) Error() (s string) {
method ExitCode (line 56) | func (e exitErr) ExitCode() (code osutil.ExitCode) {
function newExitErr (line 43) | func newExitErr(code osutil.ExitCode) (err exitErr) {
type ExternalCommand (line 61) | type ExternalCommand struct
function keyCommand (line 76) | func keyCommand(path string, args []string) (k string) {
function parseCommand (line 85) | func parseCommand(s string) (path string, args []string) {
function NewMultipleCommandConstructor (line 100) | func NewMultipleCommandConstructor(cmds ...ExternalCommand) (cs executil...
function NewCommandConstructor (line 139) | func NewCommandConstructor(
FILE: internal/aghalg/aghalg.go
function CoalesceSlice (line 15) | func CoalesceSlice[E any, S []E](values ...S) (res S) {
type UniqChecker (line 29) | type UniqChecker
method Add (line 32) | func (uc UniqChecker[T]) Add(elems ...T) {
method Merge (line 39) | func (uc UniqChecker[T]) Merge(other UniqChecker[T]) (merged UniqChecker...
method Validate (line 53) | func (uc UniqChecker[T]) Validate() (err error) {
FILE: internal/aghalg/nullbool.go
type NullBool (line 13) | type NullBool
method String (line 23) | func (nb NullBool) String() (s string) {
method MarshalJSON (line 45) | func (nb NullBool) MarshalJSON() (b []byte, err error) {
method UnmarshalJSON (line 53) | func (nb *NullBool) UnmarshalJSON(b []byte) (err error) {
constant NBNull (line 17) | NBNull NullBool = iota
constant NBTrue (line 18) | NBTrue
constant NBFalse (line 19) | NBFalse
function BoolToNullBool (line 37) | func BoolToNullBool(cond bool) (nb NullBool) {
FILE: internal/aghalg/nullbool_test.go
function TestNullBool_MarshalJSON (line 13) | func TestNullBool_MarshalJSON(t *testing.T) {
function TestNullBool_UnmarshalJSON (line 59) | func TestNullBool_UnmarshalJSON(t *testing.T) {
FILE: internal/aghalg/sortedmap.go
type SortedMap (line 10) | type SortedMap struct
function NewSortedMap (line 17) | func NewSortedMap[K cmp.Ordered, V any]() (m *SortedMap[K, V]) {
function NewSortedMapFunc (line 23) | func NewSortedMapFunc[K comparable, V any](cmpFunc func(a, b K) (res int...
method Set (line 31) | func (m *SortedMap[K, V]) Set(key K, val V) {
method Get (line 43) | func (m *SortedMap[K, V]) Get(key K) (val V, ok bool) {
method Del (line 56) | func (m *SortedMap[K, V]) Del(key K) {
method Clear (line 71) | func (m *SortedMap[K, V]) Clear() {
method Range (line 82) | func (m *SortedMap[K, V]) Range(cb func(K, V) (cont bool)) {
FILE: internal/aghalg/sortedmap_test.go
function TestNewSortedMap (line 10) | func TestNewSortedMap(t *testing.T) {
function TestNewSortedMap_nil (line 65) | func TestNewSortedMap_nil(t *testing.T) {
FILE: internal/aghhttp/aghhttp.go
type RegisterFunc (line 20) | type RegisterFunc
function OK (line 23) | func OK(ctx context.Context, l *slog.Logger, w http.ResponseWriter) {
function ErrorAndLog (line 31) | func ErrorAndLog(
function UserAgent (line 57) | func UserAgent() (ua string) {
constant textPlainDeprMsg (line 63) | textPlainDeprMsg = `using this api with the text/plain content-type is d...
function WriteTextPlainDeprecated (line 69) | func WriteTextPlainDeprecated(
FILE: internal/aghhttp/header.go
constant HdrValApplicationJSON (line 7) | HdrValApplicationJSON = "application/json"
constant HdrValStrictTransportSecurity (line 8) | HdrValStrictTransportSecurity = "max-age=31536000; includeSubDomains"
constant HdrValTextPlain (line 9) | HdrValTextPlain = "text/plain"
FILE: internal/aghhttp/json.go
constant nsecPerMsec (line 19) | nsecPerMsec = float64(time.Millisecond / time.Nanosecond)
type JSONDuration (line 23) | type JSONDuration
method MarshalJSON (line 30) | func (d JSONDuration) MarshalJSON() (b []byte, err error) {
method UnmarshalJSON (line 41) | func (d *JSONDuration) UnmarshalJSON(b []byte) (err error) {
type JSONTime (line 58) | type JSONTime
method MarshalJSON (line 65) | func (t JSONTime) MarshalJSON() (b []byte, err error) {
method UnmarshalJSON (line 76) | func (t *JSONTime) UnmarshalJSON(b []byte) (err error) {
function WriteJSONResponse (line 94) | func WriteJSONResponse(
function WriteJSONResponseOK (line 123) | func WriteJSONResponseOK(
type ErrorCode (line 135) | type ErrorCode
constant ErrorCodeTMP000 (line 142) | ErrorCodeTMP000 = ""
type HTTPAPIErrorResp (line 148) | type HTTPAPIErrorResp struct
function WriteJSONResponseError (line 156) | func WriteJSONResponseError(
FILE: internal/aghhttp/json_test.go
constant testJSONTimeStr (line 18) | testJSONTimeStr = "1234567890123.456"
function TestJSONTime_MarshalJSON (line 20) | func TestJSONTime_MarshalJSON(t *testing.T) {
function TestJSONTime_UnmarshalJSON (line 66) | func TestJSONTime_UnmarshalJSON(t *testing.T) {
FILE: internal/aghhttp/registrar.go
type Registrar (line 10) | type Registrar interface
type EmptyRegistrar (line 15) | type EmptyRegistrar struct
method Register (line 21) | func (EmptyRegistrar) Register(_, _ string, _ http.HandlerFunc) {}
type WrapFunc (line 24) | type WrapFunc
type DefaultRegistrar (line 28) | type DefaultRegistrar struct
method Register (line 46) | func (r *DefaultRegistrar) Register(method, path string, h http.Handle...
function NewDefaultRegistrar (line 35) | func NewDefaultRegistrar(mux *http.ServeMux, wrap WrapFunc) (r *DefaultR...
FILE: internal/aghnet/addr.go
function NormalizeDomain (line 12) | func NormalizeDomain(host string) (norm string) {
FILE: internal/aghnet/dhcp.go
function CheckOtherDHCP (line 10) | func CheckOtherDHCP(
FILE: internal/aghnet/dhcp_unix.go
constant defaultDiscoverTime (line 26) | defaultDiscoverTime = 3 * time.Second
function checkOtherDHCP (line 28) | func checkOtherDHCP(
function ifaceIPv4Subnet (line 49) | func ifaceIPv4Subnet(iface *net.Interface) (subnet netip.Prefix, err err...
function checkOtherDHCPv4 (line 80) | func checkOtherDHCPv4(
function discover4 (line 107) | func discover4(
function tryConn4 (line 162) | func tryConn4(
function checkOtherDHCPv6 (line 220) | func checkOtherDHCPv6(
function discover6 (line 256) | func discover6(
function tryConn6 (line 299) | func tryConn6(
FILE: internal/aghnet/dhcp_windows.go
function checkOtherDHCP (line 12) | func checkOtherDHCP(
FILE: internal/aghnet/hostgen.go
function GenerateHostname (line 18) | func GenerateHostname(ip netip.Addr) (hostname string) {
FILE: internal/aghnet/hostgen_test.go
function TestGenerateHostName (line 11) | func TestGenerateHostName(t *testing.T) {
FILE: internal/aghnet/hostscontainer.go
constant hostsContainerPrefix (line 22) | hostsContainerPrefix = "hosts container"
type HostsContainer (line 26) | type HostsContainer struct
method Close (line 128) | func (hc *HostsContainer) Close() (err error) {
method Upd (line 143) | func (hc *HostsContainer) Upd() (updates <-chan *hostsfile.DefaultStor...
method ByAddr (line 151) | func (hc *HostsContainer) ByAddr(addr netip.Addr) (names []string) {
method ByName (line 156) | func (hc *HostsContainer) ByName(name string) (addrs []netip.Addr) {
method handleEvents (line 187) | func (hc *HostsContainer) handleEvents(ctx context.Context) {
method sendUpd (line 213) | func (hc *HostsContainer) sendUpd(ctx context.Context, recs *hostsfile...
method refresh (line 234) | func (hc *HostsContainer) refresh(ctx context.Context) (err error) {
constant ErrNoHostsPaths (line 54) | ErrNoHostsPaths errors.Error = "no valid paths to hosts files provided"
function NewHostsContainer (line 64) | func NewHostsContainer(
function pathsToPatterns (line 161) | func pathsToPatterns(fsys fs.FS, paths []string) (patterns []string, err...
FILE: internal/aghnet/hostscontainer_internal_test.go
constant nl (line 16) | nl = "\n"
function TestHostsContainer_PathsToPatterns (line 18) | func TestHostsContainer_PathsToPatterns(t *testing.T) {
FILE: internal/aghnet/hostscontainer_test.go
function TestNewHostsContainer (line 24) | func TestNewHostsContainer(t *testing.T) {
function TestHostsContainer_refresh (line 137) | func TestHostsContainer_refresh(t *testing.T) {
FILE: internal/aghnet/ignore.go
type IgnoreEngine (line 15) | type IgnoreEngine struct
method Has (line 50) | func (e *IgnoreEngine) Has(host string) (ignore bool) {
method Values (line 61) | func (e *IgnoreEngine) Values() (ignored []string) {
method IsEnabled (line 66) | func (e *IgnoreEngine) IsEnabled() (enabled bool) {
function NewIgnoreEngine (line 30) | func NewIgnoreEngine(ignored []string, enabled bool) (e *IgnoreEngine, e...
FILE: internal/aghnet/ignore_test.go
function TestIgnoreEngine_Has (line 10) | func TestIgnoreEngine_Has(t *testing.T) {
FILE: internal/aghnet/interfaces.go
constant IPVersion4 (line 17) | IPVersion4 IPVersion = 4
constant IPVersion6 (line 18) | IPVersion6 IPVersion = 6
type NetIface (line 22) | type NetIface interface
function IfaceIPAddrs (line 27) | func IfaceIPAddrs(iface NetIface, ipv IPVersion) (ips []net.IP, err erro...
function ipFromAddr (line 50) | func ipFromAddr(addr net.Addr, ipv IPVersion) (ip net.IP) {
function IfaceDNSIPAddrs (line 81) | func IfaceDNSIPAddrs(
type interfaceName (line 134) | type interfaceName
FILE: internal/aghnet/interfaces_bsd.go
function reuseAddrCtrl (line 17) | func reuseAddrCtrl(_, _ string, c syscall.RawConn) (err error) {
function listenPacketReusable (line 33) | func listenPacketReusable(_, network, address string) (c net.PacketConn,...
FILE: internal/aghnet/interfaces_linux.go
function listenPacketReusable (line 14) | func listenPacketReusable(ifaceName, network, address string) (c net.Pac...
FILE: internal/aghnet/interfaces_test.go
type fakeIface (line 16) | type fakeIface struct
method Addrs (line 22) | func (iface *fakeIface) Addrs() (addrs []net.Addr, err error) {
function TestIfaceIPAddrs (line 33) | func TestIfaceIPAddrs(t *testing.T) {
type waitingFakeIface (line 120) | type waitingFakeIface struct
method Addrs (line 130) | func (iface *waitingFakeIface) Addrs() (addrs []net.Addr, err error) {
function TestIfaceDNSIPAddrs (line 144) | func TestIfaceDNSIPAddrs(t *testing.T) {
FILE: internal/aghnet/ipmut.go
type IPMutFunc (line 10) | type IPMutFunc
function nopIPMutFunc (line 13) | func nopIPMutFunc(net.IP) {}
type IPMut (line 16) | type IPMut struct
method Store (line 33) | func (m *IPMut) Store(f IPMutFunc) {
method Load (line 41) | func (m *IPMut) Load() (f IPMutFunc) {
function NewIPMut (line 22) | func NewIPMut(f IPMutFunc) (m *IPMut) {
FILE: internal/aghnet/ipmut_test.go
function TestIPMut (line 12) | func TestIPMut(t *testing.T) {
FILE: internal/aghnet/net.go
constant ErrNoStaticIPInfo (line 40) | ErrNoStaticIPInfo errors.Error = "no information about static ip"
function IfaceHasStaticIP (line 45) | func IfaceHasStaticIP(
function IfaceSetStaticIP (line 55) | func IfaceSetStaticIP(
function GatewayIP (line 69) | func GatewayIP(
function CanBindPrivilegedPorts (line 109) | func CanBindPrivilegedPorts(ctx context.Context, l *slog.Logger) (can bo...
type NetInterface (line 114) | type NetInterface struct
method MarshalJSON (line 126) | func (iface NetInterface) MarshalJSON() ([]byte, error) {
function NetInterfaceFrom (line 142) | func NetInterfaceFrom(iface *net.Interface) (niface *NetInterface, err e...
function populateAddrs (line 166) | func populateAddrs(addr net.Addr, niface *NetInterface) (err error) {
function ipNetFromAddr (line 198) | func ipNetFromAddr(addr net.Addr) (ip *net.IPNet, err error) {
function isLinkLocalV4 (line 214) | func isLinkLocalV4(ip netip.Addr) (ok bool) {
function GetValidNetInterfacesForWeb (line 223) | func GetValidNetInterfacesForWeb() (nifaces []*NetInterface, err error) {
function InterfaceByIP (line 251) | func InterfaceByIP(ip netip.Addr) (ifaceName string) {
function GetSubnet (line 272) | func GetSubnet(ctx context.Context, l *slog.Logger, ifaceName string) (p...
function CheckPort (line 291) | func CheckPort(network string, ipp netip.AddrPort) (err error) {
function IsAddrInUse (line 311) | func IsAddrInUse(err error) (ok bool) {
function CollectAllIfacesAddrs (line 322) | func CollectAllIfacesAddrs() (addrs []netip.Addr, err error) {
function ParseAddrPort (line 346) | func ParseAddrPort(s string, defaultPort uint16) (ipp netip.AddrPort, er...
function ParseSubnet (line 369) | func ParseSubnet(s string) (p netip.Prefix, err error) {
function ParseBootstraps (line 391) | func ParseBootstraps(
function BroadcastFromPref (line 410) | func BroadcastFromPref(p netip.Prefix) (bc netip.Addr) {
FILE: internal/aghnet/net_bsd.go
function canBindPrivilegedPorts (line 12) | func canBindPrivilegedPorts(_ context.Context, _ *slog.Logger) (can bool...
FILE: internal/aghnet/net_darwin.go
type hardwarePortInfo (line 21) | type hardwarePortInfo struct
function ifaceHasStaticIP (line 31) | func ifaceHasStaticIP(
function getCurrentHardwarePortInfo (line 46) | func getCurrentHardwarePortInfo(
function getNetworkSetupHardwareReports (line 71) | func getNetworkSetupHardwareReports(
function getHardwarePortInfo (line 96) | func getHardwarePortInfo(
function ifaceSetStaticIP (line 121) | func ifaceSetStaticIP(
function getEtcResolvConfServers (line 177) | func getEtcResolvConfServers() (addrs []string, err error) {
FILE: internal/aghnet/net_darwin_internal_test.go
function TestIfaceHasStaticIP (line 18) | func TestIfaceHasStaticIP(t *testing.T) {
function TestIfaceSetStaticIP (line 114) | func TestIfaceSetStaticIP(t *testing.T) {
FILE: internal/aghnet/net_freebsd.go
function ifaceHasStaticIP (line 18) | func ifaceHasStaticIP(
method rcConfStaticConfig (line 32) | func (n interfaceName) rcConfStaticConfig(r io.Reader) (_ []string, cont...
function ifaceSetStaticIP (line 62) | func ifaceSetStaticIP(
FILE: internal/aghnet/net_freebsd_internal_test.go
function TestIfaceHasStaticIP (line 15) | func TestIfaceHasStaticIP(t *testing.T) {
FILE: internal/aghnet/net_internal_test.go
constant testTimeout (line 23) | testTimeout = 1 * time.Second
function substRootDirFS (line 33) | func substRootDirFS(tb testing.TB, fsys fs.FS) {
type RunCmdFunc (line 42) | type RunCmdFunc
type ifaceAddrsFunc (line 45) | type ifaceAddrsFunc
function substNetInterfaceAddrs (line 49) | func substNetInterfaceAddrs(tb testing.TB, f ifaceAddrsFunc) {
function TestGatewayIP (line 57) | func TestGatewayIP(t *testing.T) {
function TestInterfaceByIP (line 99) | func TestInterfaceByIP(t *testing.T) {
function TestBroadcastFromIPNet (line 116) | func TestBroadcastFromIPNet(t *testing.T) {
function TestCheckPort (line 159) | func TestCheckPort(t *testing.T) {
function TestCollectAllIfacesAddrs (line 205) | func TestCollectAllIfacesAddrs(t *testing.T) {
function TestIsAddrInUse (line 260) | func TestIsAddrInUse(t *testing.T) {
function TestNetInterface_MarshalJSON (line 277) | func TestNetInterface_MarshalJSON(t *testing.T) {
FILE: internal/aghnet/net_linux.go
constant dhcpcdConf (line 25) | dhcpcdConf = "etc/dhcpcd.conf"
function canBindPrivilegedPorts (line 27) | func canBindPrivilegedPorts(ctx context.Context, l *slog.Logger) (can bo...
method dhcpcdStaticConfig (line 57) | func (n interfaceName) dhcpcdStaticConfig(r io.Reader) (subsources []str...
method ifacesStaticConfig (line 83) | func (n interfaceName) ifacesStaticConfig(r io.Reader) (sub []string, co...
function ifaceHasStaticIP (line 114) | func ifaceHasStaticIP(
function findIfaceLine (line 149) | func findIfaceLine(s *bufio.Scanner, name string) (ok bool) {
function ifaceSetStaticIP (line 163) | func ifaceSetStaticIP(
function dhcpcdConfIface (line 193) | func dhcpcdConfIface(ifaceName string, subnet netip.Prefix, gateway neti...
FILE: internal/aghnet/net_linux_internal_test.go
function TestHasStaticIP (line 14) | func TestHasStaticIP(t *testing.T) {
FILE: internal/aghnet/net_openbsd.go
function ifaceHasStaticIP (line 18) | func ifaceHasStaticIP(
function hostnameIfStaticConfig (line 30) | func hostnameIfStaticConfig(r io.Reader) (_ []string, ok bool, err error) {
function ifaceSetStaticIP (line 49) | func ifaceSetStaticIP(
FILE: internal/aghnet/net_openbsd_internal_test.go
function TestIfaceHasStaticIP (line 16) | func TestIfaceHasStaticIP(t *testing.T) {
FILE: internal/aghnet/net_test.go
constant testTimeout (line 18) | testTimeout = 1 * time.Second
function TestMain (line 23) | func TestMain(m *testing.M) {
function TestParseAddrPort (line 27) | func TestParseAddrPort(t *testing.T) {
FILE: internal/aghnet/net_unix.go
function closePortChecker (line 13) | func closePortChecker(c io.Closer) (err error) {
function isAddrInUse (line 17) | func isAddrInUse(err syscall.Errno) (ok bool) {
FILE: internal/aghnet/net_windows.go
function canBindPrivilegedPorts (line 18) | func canBindPrivilegedPorts(_ context.Context, _ *slog.Logger) (can bool...
function ifaceHasStaticIP (line 22) | func ifaceHasStaticIP(
function ifaceSetStaticIP (line 30) | func ifaceSetStaticIP(
function closePortChecker (line 40) | func closePortChecker(c io.Closer) (err error) {
function isAddrInUse (line 55) | func isAddrInUse(err syscall.Errno) (ok bool) {
FILE: internal/aghnet/upstream.go
function UpstreamHTTPVersions (line 7) | func UpstreamHTTPVersions(http3 bool) (v []upstream.HTTPVersion) {
function IsCommentOrEmpty (line 22) | func IsCommentOrEmpty(s string) (ok bool) {
FILE: internal/aghnet/upstream_test.go
function TestIsCommentOrEmpty (line 10) | func TestIsCommentOrEmpty(t *testing.T) {
FILE: internal/aghos/filewalker.go
type FileWalker (line 22) | type FileWalker
method Walk (line 87) | func (fw FileWalker) Walk(fsys fs.FS, initial ...string) (ok bool, err...
function checkFile (line 26) | func checkFile(
function handlePatterns (line 57) | func handlePatterns(
FILE: internal/aghos/filewalker_internal_test.go
type errFS (line 16) | type errFS struct
method Open (line 23) | func (efs *errFS) Open(name string) (fsys fs.File, err error) {
constant errFSOpen (line 19) | errFSOpen errors.Error = "test open error"
function TestWalkerFunc_CheckFile (line 27) | func TestWalkerFunc_CheckFile(t *testing.T) {
FILE: internal/aghos/filewalker_test.go
constant attribute (line 18) | attribute = "000"
constant nl (line 19) | nl = "\n"
function newFileWalker (line 24) | func newFileWalker() (fw aghos.FileWalker) {
function TestFileWalker_Walk (line 42) | func TestFileWalker_Walk(t *testing.T) {
FILE: internal/aghos/fswatcher.go
type FSWatcher (line 25) | type FSWatcher interface
type OSWatcherConfig (line 44) | type OSWatcherConfig struct
type OSWatcher (line 53) | type OSWatcher struct
method Start (line 98) | func (w *OSWatcher) Start(ctx context.Context) (err error) {
method Shutdown (line 106) | func (w *OSWatcher) Shutdown(_ context.Context) (err error) {
method Events (line 111) | func (w *OSWatcher) Events() (e <-chan Event) {
method Add (line 119) | func (w *OSWatcher) Add(name string) (err error) {
method Remove (line 157) | func (w *OSWatcher) Remove(name string) (err error) {
method handleEvents (line 196) | func (w *OSWatcher) handleEvents(ctx context.Context) {
method isTrackedEvent (line 220) | func (w *OSWatcher) isTrackedEvent(e fsnotify.Event) (isDir bool) {
method handleErrors (line 258) | func (w *OSWatcher) handleErrors(ctx context.Context) {
constant osWatcherPref (line 73) | osWatcherPref = "os_watcher"
function NewOSWatcher (line 77) | func NewOSWatcher(c *OSWatcherConfig) (w *OSWatcher, err error) {
function skipDuplicates (line 245) | func skipDuplicates(ch <-chan fsnotify.Event) {
type EmptyFSWatcher (line 268) | type EmptyFSWatcher struct
method Start (line 275) | func (EmptyFSWatcher) Start(_ context.Context) (err error) {
method Shutdown (line 281) | func (EmptyFSWatcher) Shutdown(_ context.Context) (err error) {
method Events (line 287) | func (EmptyFSWatcher) Events() (e <-chan Event) {
method Add (line 293) | func (EmptyFSWatcher) Add(_ string) (err error) {
method Remove (line 299) | func (EmptyFSWatcher) Remove(_ string) (err error) {
FILE: internal/aghos/os.go
constant DefaultPermDir (line 29) | DefaultPermDir fs.FileMode = 0o700
constant DefaultPermExe (line 30) | DefaultPermExe fs.FileMode = 0o700
constant DefaultPermFile (line 31) | DefaultPermFile fs.FileMode = 0o600
function Unsupported (line 35) | func Unsupported(op string) (err error) {
function SetRlimit (line 42) | func SetRlimit(val uint64) (err error) {
function HaveAdminRights (line 47) | func HaveAdminRights() (bool, error) {
constant MaxCmdOutputSize (line 53) | MaxCmdOutputSize = 64 * 1024
function RunCommand (line 59) | func RunCommand(
function PIDByCommand (line 106) | func PIDByCommand(
function parsePSOutput (line 169) | func parsePSOutput(r io.Reader, cmdName string, ignore []int) (largest, ...
function IsOpenWrt (line 193) | func IsOpenWrt() (ok bool) {
function SendShutdownSignal (line 198) | func SendShutdownSignal(c chan<- os.Signal) {
function RootDir (line 205) | func RootDir() (dir string) {
FILE: internal/aghos/os_bsd.go
function setRlimit (line 10) | func setRlimit(val uint64) (err error) {
function haveAdminRights (line 18) | func haveAdminRights() (bool, error) {
function isOpenWrt (line 22) | func isOpenWrt() (ok bool) {
FILE: internal/aghos/os_freebsd.go
function setRlimit (line 10) | func setRlimit(val uint64) (err error) {
function haveAdminRights (line 18) | func haveAdminRights() (bool, error) {
function isOpenWrt (line 22) | func isOpenWrt() (ok bool) {
FILE: internal/aghos/os_internal_test.go
function TestLargestLabeled (line 12) | func TestLargestLabeled(t *testing.T) {
FILE: internal/aghos/os_linux.go
function setRlimit (line 14) | func setRlimit(val uint64) (err error) {
function haveAdminRights (line 22) | func haveAdminRights() (bool, error) {
function isOpenWrt (line 28) | func isOpenWrt() (ok bool) {
FILE: internal/aghos/os_unix.go
function sendShutdownSignal (line 9) | func sendShutdownSignal(_ chan<- os.Signal) {
function rootDir (line 13) | func rootDir() (dir string) {
FILE: internal/aghos/os_windows.go
function setRlimit (line 12) | func setRlimit(_ uint64) (err error) {
function haveAdminRights (line 16) | func haveAdminRights() (bool, error) {
function isOpenWrt (line 37) | func isOpenWrt() (ok bool) {
function sendShutdownSignal (line 41) | func sendShutdownSignal(c chan<- os.Signal) {
function rootDir (line 45) | func rootDir() (dir string) {
FILE: internal/aghos/service.go
function PreCheckActionStart (line 4) | func PreCheckActionStart() (err error) {
FILE: internal/aghos/service_darwin.go
function preCheckActionStart (line 16) | func preCheckActionStart() (err error) {
FILE: internal/aghos/service_others.go
function preCheckActionStart (line 6) | func preCheckActionStart() (err error) {
FILE: internal/aghos/syslog.go
function ConfigureSyslog (line 4) | func ConfigureSyslog(serviceName string) (err error) {
FILE: internal/aghos/syslog_others.go
function configureSyslog (line 12) | func configureSyslog(serviceName string) (err error) {
FILE: internal/aghos/syslog_windows.go
type eventLogWriter (line 13) | type eventLogWriter struct
method Write (line 18) | func (w *eventLogWriter) Write(b []byte) (int, error) {
function configureSyslog (line 23) | func configureSyslog(serviceName string) (err error) {
FILE: internal/aghos/user.go
function SetGroup (line 4) | func SetGroup(groupName string) (err error) {
function SetUser (line 9) | func SetUser(userName string) (err error) {
FILE: internal/aghos/user_unix.go
function setGroup (line 12) | func setGroup(groupName string) (err error) {
function setUser (line 31) | func setUser(userName string) (err error) {
FILE: internal/aghos/user_windows.go
function setGroup (line 8) | func setGroup(_ string) (err error) {
function setUser (line 12) | func setUser(_ string) (err error) {
FILE: internal/aghrenameio/renameio.go
type PendingFile (line 20) | type PendingFile interface
function NewPendingFile (line 39) | func NewPendingFile(filePath string, mode fs.FileMode) (f PendingFile, e...
function WithDeferredCleanup (line 45) | func WithDeferredCleanup(returned error, file PendingFile) (err error) {
FILE: internal/aghrenameio/renameio_test.go
constant testPerm (line 17) | testPerm fs.FileMode = 0o644
function TestPendingFile (line 25) | func TestPendingFile(t *testing.T) {
function newInitialFile (line 46) | func newInitialFile(tb testing.TB) (targetPath string) {
function TestWithDeferredCleanup (line 58) | func TestWithDeferredCleanup(t *testing.T) {
FILE: internal/aghrenameio/renameio_unix.go
type pendingFile (line 13) | type pendingFile struct
method Cleanup (line 21) | func (f pendingFile) Cleanup() (err error) {
method CloseReplace (line 26) | func (f pendingFile) CloseReplace() (err error) {
method Write (line 31) | func (f pendingFile) Write(b []byte) (n int, err error) {
function newPendingFile (line 38) | func newPendingFile(filePath string, mode fs.FileMode) (f PendingFile, e...
FILE: internal/aghrenameio/renameio_windows.go
type pendingFile (line 16) | type pendingFile struct
method Cleanup (line 25) | func (f *pendingFile) Cleanup() (err error) {
method CloseReplace (line 35) | func (f *pendingFile) CloseReplace() (err error) {
method Write (line 50) | func (f *pendingFile) Write(b []byte) (n int, err error) {
function newPendingFile (line 57) | func newPendingFile(filePath string, mode fs.FileMode) (f PendingFile, e...
FILE: internal/aghslog/aghslog.go
constant PrefixDNSProxy (line 11) | PrefixDNSProxy = "dnsproxy"
constant KeyClientName (line 15) | KeyClientName = "client_name"
constant KeyUpstreamType (line 19) | KeyUpstreamType = "upstream_type"
constant UpstreamTypeBootstrap (line 24) | UpstreamTypeBootstrap = "bootstrap"
constant UpstreamTypeCustom (line 27) | UpstreamTypeCustom = "custom"
constant UpstreamTypeFallback (line 30) | UpstreamTypeFallback = "fallback"
constant UpstreamTypeMain (line 33) | UpstreamTypeMain = "main"
constant UpstreamTypeLocal (line 37) | UpstreamTypeLocal = "local"
constant UpstreamTypeService (line 41) | UpstreamTypeService = "service"
constant UpstreamTypeTest (line 45) | UpstreamTypeTest = "test"
function NewForUpstream (line 50) | func NewForUpstream(baseLogger *slog.Logger, typ string) (l *slog.Logger) {
FILE: internal/aghtest/aghtest.go
constant ReqHost (line 22) | ReqHost = "www.host.example"
constant ReqFQDN (line 25) | ReqFQDN = ReqHost + "."
function HostToIPs (line 29) | func HostToIPs(host string) (ipv4, ipv6 netip.Addr) {
function StartHTTPServer (line 37) | func StartHTTPServer(tb testing.TB, data []byte) (c *http.Client, u *url...
constant testTimeout (line 54) | testTimeout = 1 * time.Second
function StartLocalhostUpstream (line 58) | func StartLocalhostUpstream(tb testing.TB, h dns.Handler) (addr *url.URL) {
FILE: internal/aghtest/interface.go
type FSWatcher (line 21) | type FSWatcher struct
method Start (line 44) | func (w *FSWatcher) Start(ctx context.Context) (err error) {
method Shutdown (line 49) | func (w *FSWatcher) Shutdown(ctx context.Context) (err error) {
method Events (line 54) | func (w *FSWatcher) Events() (e <-chan aghos.Event) {
method Add (line 59) | func (w *FSWatcher) Add(name string) (err error) {
method Remove (line 64) | func (w *FSWatcher) Remove(name string) (err error) {
function NewFSWatcher (line 30) | func NewFSWatcher() (w *FSWatcher) {
type ServiceWithConfig (line 70) | type ServiceWithConfig struct
method Start (line 81) | func (s *ServiceWithConfig[_]) Start(ctx context.Context) (err error) {
method Shutdown (line 87) | func (s *ServiceWithConfig[_]) Shutdown(ctx context.Context) (err error) {
method Config (line 93) | func (s *ServiceWithConfig[ConfigType]) Config() (c ConfigType) {
type AddressProcessor (line 99) | type AddressProcessor struct
method Process (line 106) | func (p *AddressProcessor) Process(ctx context.Context, ip netip.Addr) {
method Close (line 112) | func (p *AddressProcessor) Close() (err error) {
type AddressUpdater (line 117) | type AddressUpdater struct
method UpdateAddress (line 123) | func (p *AddressUpdater) UpdateAddress(
type Exchanger (line 133) | type Exchanger struct
method Exchange (line 141) | func (e *Exchanger) Exchange(
type UpstreamMock (line 152) | type UpstreamMock struct
method Address (line 162) | func (u *UpstreamMock) Address() (addr string) {
method Exchange (line 167) | func (u *UpstreamMock) Exchange(req *dns.Msg) (resp *dns.Msg, err erro...
method Close (line 172) | func (u *UpstreamMock) Close() (err error) {
type ConfigModifier (line 177) | type ConfigModifier struct
method Apply (line 185) | func (m *ConfigModifier) Apply(ctx context.Context) {
type Registrar (line 190) | type Registrar struct
method Register (line 198) | func (m *Registrar) Register(method, path string, h http.HandlerFunc) {
FILE: internal/aghtest/upstream.go
type Upstream (line 21) | type Upstream struct
method Exchange (line 35) | func (u *Upstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
method Address (line 75) | func (u *Upstream) Address() string {
method Close (line 80) | func (u *Upstream) Close() (err error) {
function MatchedResponse (line 101) | func MatchedResponse(req *dns.Msg, qt uint16, targ, answer string) (resp...
function mustAnsA (line 139) | func mustAnsA(respHdr dns.RR_Header, s string) (ans []dns.RR) {
function mustAnsAAAA (line 153) | func mustAnsAAAA(respHdr dns.RR_Header, s string) (ans []dns.RR) {
function NewUpstreamMock (line 168) | func NewUpstreamMock(onExc func(req *dns.Msg) (resp *dns.Msg, err error)...
function NewBlockUpstream (line 180) | func NewBlockUpstream(hostname string, shouldBlock bool) (u *UpstreamMoc...
constant ErrUpstream (line 215) | ErrUpstream errors.Error = "test upstream error"
function NewErrorUpstream (line 219) | func NewErrorUpstream() (u *UpstreamMock) {
FILE: internal/aghtls/aghtls.go
function Init (line 20) | func Init(ctx context.Context, l *slog.Logger) {
function ParseCiphers (line 35) | func ParseCiphers(cipherNames []string) (cipherIDs []uint16, err error) {
function SaferCipherSuites (line 55) | func SaferCipherSuites() (safe []uint16) {
function CertificateHasIP (line 81) | func CertificateHasIP(cert *x509.Certificate) (ok bool) {
FILE: internal/aghtls/aghtls_test.go
constant testTimeout (line 15) | testTimeout time.Duration = 1 * time.Second
function TestParseCiphers (line 17) | func TestParseCiphers(t *testing.T) {
FILE: internal/aghtls/defaultmanager.go
type DefaultManagerConfig (line 15) | type DefaultManagerConfig struct
type DefaultManager (line 28) | type DefaultManager struct
method Set (line 52) | func (mgr *DefaultManager) Set(ctx context.Context, certKey TLSPair) (...
method appendUnwatchErr (line 74) | func (mgr *DefaultManager) appendUnwatchErr(errs []error, what, p stri...
method appendWatchErr (line 89) | func (mgr *DefaultManager) appendWatchErr(errs []error, what, p string...
method Refresh (line 103) | func (mgr *DefaultManager) Refresh(ctx context.Context) (err error) {
method Start (line 117) | func (mgr *DefaultManager) Start(ctx context.Context) (err error) {
method Shutdown (line 129) | func (mgr *DefaultManager) Shutdown(ctx context.Context) (err error) {
method Updates (line 141) | func (mgr *DefaultManager) Updates(ctx context.Context) (updates <-cha...
method handleEvents (line 147) | func (mgr *DefaultManager) handleEvents(ctx context.Context) {
function NewDefaultManager (line 37) | func NewDefaultManager(c *DefaultManagerConfig) (mgr *DefaultManager) {
FILE: internal/aghtls/manager.go
type TLSPair (line 10) | type TLSPair struct
type UpdateSignal (line 21) | type UpdateSignal struct
type Manager (line 24) | type Manager interface
type EmptyManager (line 41) | type EmptyManager struct
method Start (line 48) | func (EmptyManager) Start(_ context.Context) (err error) { return nil }
method Shutdown (line 52) | func (EmptyManager) Shutdown(_ context.Context) (err error) { return n...
method Refresh (line 56) | func (EmptyManager) Refresh(_ context.Context) (err error) { return nil }
method Set (line 60) | func (EmptyManager) Set(_ context.Context, _ TLSPair) (err error) { re...
method Updates (line 64) | func (EmptyManager) Updates(_ context.Context) (updates <-chan UpdateS...
FILE: internal/aghtls/root.go
function SystemRootCAs (line 14) | func SystemRootCAs(ctx context.Context, l *slog.Logger) (roots *x509.Cer...
FILE: internal/aghtls/root_linux.go
function rootCAs (line 16) | func rootCAs(ctx context.Context, l *slog.Logger) (roots *x509.CertPool) {
function addCertsFromDir (line 36) | func addCertsFromDir(
FILE: internal/aghtls/root_others.go
function rootCAs (line 11) | func rootCAs(_ context.Context, _ *slog.Logger) (roots *x509.CertPool) {
FILE: internal/aghuser/aghuser.go
type Login (line 11) | type Login
function NewLogin (line 17) | func NewLogin(s string) (l Login, err error) {
type Password (line 27) | type Password interface
type DefaultPassword (line 37) | type DefaultPassword struct
method Authenticate (line 52) | func (p *DefaultPassword) Authenticate(ctx context.Context, passwd str...
method Hash (line 57) | func (p *DefaultPassword) Hash() (b []byte) {
function NewDefaultPassword (line 42) | func NewDefaultPassword(hash string) (p *DefaultPassword) {
FILE: internal/aghuser/aghuser_test.go
constant testTimeout (line 6) | testTimeout = 1 * time.Second
FILE: internal/aghuser/db.go
type DB (line 20) | type DB interface
type DefaultDB (line 46) | type DefaultDB struct
method All (line 75) | func (db *DefaultDB) All(ctx context.Context) (users []*User, err erro...
method ByLogin (line 95) | func (db *DefaultDB) ByLogin(ctx context.Context, login Login) (u *Use...
method ByUUID (line 114) | func (db *DefaultDB) ByUUID(ctx context.Context, id UserID) (u *User, ...
method Create (line 127) | func (db *DefaultDB) Create(ctx context.Context, u *User) (err error) {
function NewDefaultDB (line 63) | func NewDefaultDB() (db *DefaultDB) {
FILE: internal/aghuser/db_test.go
function TestDB (line 14) | func TestDB(t *testing.T) {
FILE: internal/aghuser/session.go
constant SessionTokenLength (line 9) | SessionTokenLength = 16
type SessionToken (line 12) | type SessionToken
function NewSessionToken (line 17) | func NewSessionToken() (t SessionToken) {
type Session (line 24) | type Session struct
FILE: internal/aghuser/sessionstorage.go
type SessionStorage (line 23) | type SessionStorage interface
type DefaultSessionStorageConfig (line 43) | type DefaultSessionStorageConfig struct
type DefaultSessionStorage (line 66) | type DefaultSessionStorage struct
method loadSessions (line 128) | func (ds *DefaultSessionStorage) loadSessions(ctx context.Context) (er...
method processSessions (line 175) | func (ds *DefaultSessionStorage) processSessions(
method bboltSessionHandler (line 204) | func (ds *DefaultSessionStorage) bboltSessionHandler(
method New (line 304) | func (ds *DefaultSessionStorage) New(ctx context.Context, u *User) (s ...
method store (line 326) | func (ds *DefaultSessionStorage) store(s *Session) (err error) {
method FindByToken (line 359) | func (ds *DefaultSessionStorage) FindByToken(ctx context.Context, t Se...
method DeleteByToken (line 383) | func (ds *DefaultSessionStorage) DeleteByToken(ctx context.Context, t ...
method deleteByToken (line 393) | func (ds *DefaultSessionStorage) deleteByToken(ctx context.Context, t ...
method remove (line 407) | func (ds *DefaultSessionStorage) remove(ctx context.Context, t Session...
method Close (line 442) | func (ds *DefaultSessionStorage) Close() (err error) {
function NewDefaultSessionStorage (line 92) | func NewDefaultSessionStorage(
constant bboltBucketSessions (line 249) | bboltBucketSessions = "sessions-2"
constant bboltSessionExpireLen (line 254) | bboltSessionExpireLen = 4
constant bboltSessionNameLen (line 258) | bboltSessionNameLen = 2
function bboltDecode (line 262) | func bboltDecode(data []byte) (s *Session, err error) {
function bboltEncode (line 285) | func bboltEncode(s *Session) (data []byte) {
FILE: internal/aghuser/sessionstorage_test.go
function addSession (line 19) | func addSession(
function TestDefaultSessionStorage (line 44) | func TestDefaultSessionStorage(t *testing.T) {
FILE: internal/aghuser/user.go
type UserID (line 12) | type UserID
function NewUserID (line 16) | func NewUserID() (uid UserID, err error) {
function MustNewUserID (line 24) | func MustNewUserID() (uid UserID) {
type User (line 34) | type User struct
FILE: internal/arpdb/arpdb.go
type Interface (line 31) | type Interface interface
function New (line 41) | func New(logger *slog.Logger) (arp Interface) {
type Empty (line 46) | type Empty struct
method Refresh (line 53) | func (Empty) Refresh(_ context.Context) (err error) { return nil }
method Neighbors (line 57) | func (Empty) Neighbors() (ns []Neighbor) { return nil }
type Neighbor (line 60) | type Neighbor struct
method Clone (line 97) | func (n Neighbor) Clone() (clone Neighbor) {
function newNeighbor (line 74) | func newNeighbor(host, ipStr, macStr string) (n *Neighbor, err error) {
function validatedHostname (line 107) | func validatedHostname(logger *slog.Logger, h string) (host string) {
type neighs (line 120) | type neighs struct
method len (line 126) | func (ns *neighs) len() (l int) {
method clone (line 135) | func (ns *neighs) clone() (cloned []Neighbor) {
method reset (line 149) | func (ns *neighs) reset(with []Neighbor) {
type parseNeighsFunc (line 161) | type parseNeighsFunc
type cmdARPDB (line 165) | type cmdARPDB struct
method Refresh (line 178) | func (arp *cmdARPDB) Refresh(ctx context.Context) (err error) {
method Neighbors (line 212) | func (arp *cmdARPDB) Neighbors() (ns []Neighbor) {
type arpdbs (line 218) | type arpdbs struct
method Refresh (line 240) | func (arp *arpdbs) Refresh(ctx context.Context) (err error) {
method Neighbors (line 262) | func (arp *arpdbs) Neighbors() (ns []Neighbor) {
function newARPDBs (line 226) | func newARPDBs(arps ...Interface) (arp *arpdbs) {
FILE: internal/arpdb/arpdb_bsd.go
function newARPDB (line 15) | func newARPDB(logger *slog.Logger, cmdCons executil.CommandConstructor) ...
function parseArpA (line 38) | func parseArpA(logger *slog.Logger, sc *bufio.Scanner, lenHint int) (ns ...
FILE: internal/arpdb/arpdb_bsd_internal_test.go
constant arpAOutput (line 10) | arpAOutput = `
FILE: internal/arpdb/arpdb_internal_test.go
constant testTimeout (line 22) | testTimeout = 1 * time.Second
type RunCmdFunc (line 28) | type RunCmdFunc
function Test_New (line 30) | func Test_New(t *testing.T) {
type TestARPDB (line 40) | type TestARPDB struct
method Refresh (line 49) | func (arp *TestARPDB) Refresh(ctx context.Context) (err error) {
method Neighbors (line 54) | func (arp *TestARPDB) Neighbors() (ns []Neighbor) {
function Test_NewARPDBs (line 58) | func Test_NewARPDBs(t *testing.T) {
function TestCmdARPDB_arpa (line 174) | func TestCmdARPDB_arpa(t *testing.T) {
function TestEmptyARPDB (line 222) | func TestEmptyARPDB(t *testing.T) {
FILE: internal/arpdb/arpdb_linux.go
function newARPDB (line 22) | func newARPDB(logger *slog.Logger, cmdCons executil.CommandConstructor) ...
type fsysARPDB (line 70) | type fsysARPDB struct
method Refresh (line 80) | func (arp *fsysARPDB) Refresh(_ context.Context) (err error) {
method Neighbors (line 132) | func (arp *fsysARPDB) Neighbors() (ns []Neighbor) {
function parseNeighbor (line 109) | func parseNeighbor(line string) (n *Neighbor) {
function parseArpAWrt (line 141) | func parseArpAWrt(logger *slog.Logger, sc *bufio.Scanner, lenHint int) (...
function parseArpA (line 173) | func parseArpA(logger *slog.Logger, sc *bufio.Scanner, lenHint int) (ns ...
function parseIPNeigh (line 206) | func parseIPNeigh(logger *slog.Logger, sc *bufio.Scanner, lenHint int) (...
FILE: internal/arpdb/arpdb_linux_internal_test.go
constant arpAOutputWrt (line 19) | arpAOutputWrt = `
constant arpAOutput (line 26) | arpAOutput = `
constant ipNeighOutput (line 33) | ipNeighOutput = `
function TestFSysARPDB (line 47) | func TestFSysARPDB(t *testing.T) {
function TestCmdARPDB_linux (line 66) | func TestCmdARPDB_linux(t *testing.T) {
FILE: internal/arpdb/arpdb_openbsd.go
function newARPDB (line 15) | func newARPDB(logger *slog.Logger, cmdCons executil.CommandConstructor) ...
function parseArpA (line 39) | func parseArpA(logger *slog.Logger, sc *bufio.Scanner, lenHint int) (ns ...
FILE: internal/arpdb/arpdb_openbsd_internal_test.go
constant arpAOutput (line 10) | arpAOutput = `
FILE: internal/arpdb/arpdb_windows.go
function newARPDB (line 15) | func newARPDB(logger *slog.Logger, cmdCons executil.CommandConstructor) ...
function parseArpA (line 36) | func parseArpA(logger *slog.Logger, sc *bufio.Scanner, lenHint int) (ns ...
FILE: internal/arpdb/arpdb_windows_internal_test.go
constant arpAOutput (line 10) | arpAOutput = `
FILE: internal/client/addrproc.go
constant ErrClosed (line 20) | ErrClosed errors.Error = "use of closed address processor"
type AddressProcessor (line 23) | type AddressProcessor interface
type EmptyAddrProc (line 29) | type EmptyAddrProc struct
method Process (line 35) | func (EmptyAddrProc) Process(_ context.Context, _ netip.Addr) {}
method Close (line 38) | func (EmptyAddrProc) Close() (_ error) { return nil }
type DefaultAddrProcConfig (line 41) | type DefaultAddrProcConfig struct
type AddressUpdater (line 89) | type AddressUpdater interface
type DefaultAddrProc (line 97) | type DefaultAddrProc struct
method Process (line 219) | func (p *DefaultAddrProc) Process(ctx context.Context, ip netip.Addr) {
method process (line 237) | func (p *DefaultAddrProc) process(ctx context.Context, catchPanics boo...
method processRDNS (line 256) | func (p *DefaultAddrProc) processRDNS(ctx context.Context, ip netip.Ad...
method shouldResolve (line 284) | func (p *DefaultAddrProc) shouldResolve(ip netip.Addr) (ok bool) {
method processWHOIS (line 291) | func (p *DefaultAddrProc) processWHOIS(ctx context.Context, ip netip.A...
method Close (line 315) | func (p *DefaultAddrProc) Close() (err error) {
constant defaultQueueSize (line 132) | defaultQueueSize = 255
constant defaultCacheSize (line 136) | defaultCacheSize = 10_000
constant defaultIPTTL (line 140) | defaultIPTTL = 1 * time.Hour
function NewDefaultAddrProc (line 145) | func NewDefaultAddrProc(c *DefaultAddrProcConfig) (p *DefaultAddrProc) {
function newWHOIS (line 184) | func newWHOIS(logger *slog.Logger, dialFunc aghnet.DialContextFunc) (w w...
FILE: internal/client/addrproc_test.go
function TestEmptyAddrProc (line 23) | func TestEmptyAddrProc(t *testing.T) {
function TestDefaultAddrProc_Process_rDNS (line 39) | func TestDefaultAddrProc_Process_rDNS(t *testing.T) {
function newOnUpdateAddress (line 154) | func newOnUpdateAddress(
function TestDefaultAddrProc_Process_WHOIS (line 171) | func TestDefaultAddrProc_Process_WHOIS(t *testing.T) {
function TestDefaultAddrProc_Close (line 267) | func TestDefaultAddrProc_Close(t *testing.T) {
FILE: internal/client/client.go
type ClientID (line 22) | type ClientID
function ValidateClientID (line 27) | func ValidateClientID(id string) (err error) {
function isValidClientID (line 38) | func isValidClientID(id string) (ok bool) {
type Source (line 44) | type Source
method String (line 60) | func (cs Source) String() (s string) {
method MarshalText (line 81) | func (cs Source) MarshalText() (text []byte, err error) {
constant SourceWHOIS (line 48) | SourceWHOIS Source = iota + 1
constant SourceARP (line 49) | SourceARP
constant SourceRDNS (line 50) | SourceRDNS
constant SourceDHCP (line 51) | SourceDHCP
constant SourceHostsFile (line 52) | SourceHostsFile
constant SourcePersistent (line 53) | SourcePersistent
type Runtime (line 86) | type Runtime struct
method Info (line 124) | func (r *Runtime) Info() (cs Source, host string) {
method setInfo (line 149) | func (r *Runtime) setInfo(cs Source, hosts []string) {
method WHOIS (line 168) | func (r *Runtime) WHOIS() (info *whois.Info) {
method setWHOIS (line 173) | func (r *Runtime) setWHOIS(info *whois.Info) {
method unset (line 178) | func (r *Runtime) unset(cs Source) {
method isEmpty (line 194) | func (r *Runtime) isEmpty() (ok bool) {
method Addr (line 203) | func (r *Runtime) Addr() (ip netip.Addr) {
method clone (line 208) | func (r *Runtime) clone() (c *Runtime) {
function NewRuntime (line 117) | func NewRuntime(ip netip.Addr) (r *Runtime) {
FILE: internal/client/client_test.go
function TestMain (line 11) | func TestMain(m *testing.M) {
constant testHost (line 16) | testHost = "client.example"
constant testTimeout (line 19) | testTimeout = 1 * time.Second
constant testWHOISCity (line 22) | testWHOISCity = "Brussels"
FILE: internal/client/index.go
type macKey (line 15) | type macKey
function macToKey (line 19) | func macToKey(mac net.HardwareAddr) (key macKey) {
type index (line 33) | type index struct
method add (line 67) | func (ci *index) add(c *Persistent) {
method clashesUID (line 96) | func (ci *index) clashesUID(c *Persistent) (err error) {
method clashes (line 107) | func (ci *index) clashes(c *Persistent) (err error) {
method clashesName (line 141) | func (ci *index) clashesName(c *Persistent) (existing *Persistent) {
method clashesIP (line 156) | func (ci *index) clashesIP(c *Persistent) (p *Persistent, ip netip.Add...
method clashesSubnet (line 169) | func (ci *index) clashesSubnet(c *Persistent) (p *Persistent, s netip....
method clashesMAC (line 195) | func (ci *index) clashesMAC(c *Persistent) (p *Persistent, mac net.Har...
method find (line 209) | func (ci *index) find(id string) (c *Persistent, ok bool) {
method findByClientID (line 233) | func (ci *index) findByClientID(clientID ClientID) (c *Persistent, ok ...
method findByName (line 243) | func (ci *index) findByName(name string) (c *Persistent, found bool) {
method findByIP (line 253) | func (ci *index) findByIP(ip netip.Addr) (c *Persistent, found bool) {
method findByCIDR (line 281) | func (ci *index) findByCIDR(subnet netip.Prefix) (c *Persistent, ok bo...
method findByMAC (line 299) | func (ci *index) findByMAC(mac net.HardwareAddr) (c *Persistent, found...
method findByIPWithoutZone (line 315) | func (ci *index) findByIPWithoutZone(ip netip.Addr) (c *Persistent) {
method remove (line 331) | func (ci *index) remove(c *Persistent) {
method size (line 355) | func (ci *index) size() (n int) {
method rangeByName (line 361) | func (ci *index) rangeByName(f func(c *Persistent) (cont bool)) {
function newIndex (line 54) | func newIndex() (ci *index) {
FILE: internal/client/index_internal_test.go
function newIDIndex (line 15) | func newIDIndex(m []*Persistent) (ci *index) {
function TestClientIndex_Find (line 27) | func TestClientIndex_Find(t *testing.T) {
function TestClientIndex_Clashes (line 128) | func TestClientIndex_Clashes(t *testing.T) {
function TestMACToKey (line 185) | func TestMACToKey(t *testing.T) {
function TestIndex_FindByIPWithoutZone (line 243) | func TestIndex_FindByIPWithoutZone(t *testing.T) {
function TestClientIndex_RangeByName (line 292) | func TestClientIndex_RangeByName(t *testing.T) {
function TestIndex_FindByName (line 343) | func TestIndex_FindByName(t *testing.T) {
function TestIndex_FindByMAC (line 399) | func TestIndex_FindByMAC(t *testing.T) {
FILE: internal/client/persistent.go
type UID (line 23) | type UID
method MarshalText (line 47) | func (uid UID) MarshalText() ([]byte, error) {
method UnmarshalText (line 55) | func (uid *UID) UnmarshalText(data []byte) error {
function NewUID (line 27) | func NewUID() (uid UID, err error) {
function MustNewUID (line 34) | func MustNewUID() (uid UID) {
type Persistent (line 60) | type Persistent struct
method validate (line 136) | func (c *Persistent) validate(ctx context.Context, l *slog.Logger, all...
method SetIDs (line 173) | func (c *Persistent) SetIDs(ids []string) (err error) {
method setID (line 215) | func (c *Persistent) setID(id string) (err error) {
method Identifiers (line 254) | func (c *Persistent) Identifiers() (ids []string) {
method idendifiersLen (line 277) | func (c *Persistent) idendifiersLen() (n int) {
method EqualIDs (line 283) | func (c *Persistent) EqualIDs(prev *Persistent) (equal bool) {
method ShallowClone (line 292) | func (c *Persistent) ShallowClone() (clone *Persistent) {
function subnetCompare (line 196) | func subnetCompare(x, y netip.Prefix) (cmp int) {
FILE: internal/client/persistent_internal_test.go
function TestPersistent_EqualIDs (line 10) | func TestPersistent_EqualIDs(t *testing.T) {
FILE: internal/client/runtimeindex.go
type runtimeIndex (line 6) | type runtimeIndex struct
method client (line 20) | func (ri *runtimeIndex) client(ip netip.Addr) (rc *Runtime) {
method add (line 26) | func (ri *runtimeIndex) add(rc *Runtime) {
method rangeClients (line 32) | func (ri *runtimeIndex) rangeClients(f func(rc *Runtime) (cont bool)) {
method setInfo (line 42) | func (ri *runtimeIndex) setInfo(ip netip.Addr, cs Source, hosts []stri...
method clearSource (line 55) | func (ri *runtimeIndex) clearSource(src Source) {
method removeEmpty (line 63) | func (ri *runtimeIndex) removeEmpty() (n int) {
function newRuntimeIndex (line 12) | func newRuntimeIndex() (ri *runtimeIndex) {
FILE: internal/client/storage.go
type DHCP (line 53) | type DHCP interface
type EmptyDHCP (line 69) | type EmptyDHCP struct
method Leases (line 75) | func (EmptyDHCP) Leases() (leases []*dhcpsvc.Lease) { return nil }
method HostByIP (line 78) | func (EmptyDHCP) HostByIP(_ netip.Addr) (host string) { return "" }
method MACByIP (line 81) | func (EmptyDHCP) MACByIP(_ netip.Addr) (mac net.HardwareAddr) { return...
type HostsContainer (line 85) | type HostsContainer interface
type StorageConfig (line 90) | type StorageConfig struct
type Storage (line 127) | type Storage struct
method Start (line 206) | func (s *Storage) Start(ctx context.Context) (err error) {
method Shutdown (line 216) | func (s *Storage) Shutdown(_ context.Context) (err error) {
method periodicARPUpdate (line 224) | func (s *Storage) periodicARPUpdate(ctx context.Context) {
method ReloadARP (line 240) | func (s *Storage) ReloadARP(ctx context.Context) {
method addFromSystemARP (line 248) | func (s *Storage) addFromSystemARP(ctx context.Context) {
method handleHostsUpdates (line 285) | func (s *Storage) handleHostsUpdates(ctx context.Context) {
method addFromHostsFile (line 308) | func (s *Storage) addFromHostsFile(ctx context.Context, hosts *hostsfi...
method UpdateAddress (line 340) | func (s *Storage) UpdateAddress(ctx context.Context, ip netip.Addr, ho...
method UpdateDHCP (line 359) | func (s *Storage) UpdateDHCP(ctx context.Context) {
method setWHOISInfo (line 386) | func (s *Storage) setWHOISInfo(ctx context.Context, ip netip.Addr, wi ...
method Add (line 410) | func (s *Storage) Add(ctx context.Context, p *Persistent) (err error) {
method Find (line 529) | func (s *Storage) Find(params *FindParams) (p *Persistent, ok bool) {
method findByIP (line 564) | func (s *Storage) findByIP(addr netip.Addr) (p *Persistent, ok bool) {
method FindLoose (line 587) | func (s *Storage) FindLoose(ip netip.Addr, id string) (p *Persistent, ...
method RemoveByName (line 611) | func (s *Storage) RemoveByName(ctx context.Context, name string) (ok b...
method Update (line 632) | func (s *Storage) Update(ctx context.Context, name string, p *Persiste...
method RangeByName (line 670) | func (s *Storage) RangeByName(f func(c *Persistent) (cont bool)) {
method Size (line 678) | func (s *Storage) Size() (n int) {
method ClientRuntime (line 687) | func (s *Storage) ClientRuntime(ip netip.Addr) (rc *Runtime) {
method RangeRuntime (line 715) | func (s *Storage) RangeRuntime(f func(rc *Runtime) (cont bool)) {
method AllowedTags (line 724) | func (s *Storage) AllowedTags() (tags []string) {
method CustomUpstreamConfig (line 730) | func (s *Storage) CustomUpstreamConfig(
method UpdateCommonUpstreamConfig (line 751) | func (s *Storage) UpdateCommonUpstreamConfig(conf *CommonUpstreamConfi...
method ClearUpstreamCache (line 760) | func (s *Storage) ClearUpstreamCache() {
method ApplyClientFiltering (line 770) | func (s *Storage) ApplyClientFiltering(id string, addr netip.Addr, set...
function NewStorage (line 172) | func NewStorage(ctx context.Context, conf *StorageConfig) (s *Storage, e...
type FindParams (line 450) | type FindParams struct
method Set (line 481) | func (p *FindParams) Set(id string) (err error) {
constant ErrBadIdentifier (line 472) | ErrBadIdentifier errors.Error = "bad client identifier"
FILE: internal/client/storage_test.go
function newTestStorage (line 35) | func newTestStorage(tb testing.TB, clock timeutil.Clock) (s *client.Stor...
type testHostsContainer (line 54) | type testHostsContainer struct
method Upd (line 62) | func (c *testHostsContainer) Upd() (updates <-chan *hostsfile.DefaultS...
type Interface (line 68) | type Interface interface
type testARPDB (line 78) | type testARPDB struct
method Refresh (line 87) | func (c *testARPDB) Refresh(ctx context.Context) (err error) {
method Neighbors (line 92) | func (c *testARPDB) Neighbors() (ns []arpdb.Neighbor) {
type testDHCP (line 97) | type testDHCP struct
method Leases (line 107) | func (t *testDHCP) Leases() (leases []*dhcpsvc.Lease) { return t.OnLea...
method HostByIP (line 110) | func (t *testDHCP) HostByIP(ip netip.Addr) (host string) { return t.On...
method MACByIP (line 113) | func (t *testDHCP) MACByIP(ip netip.Addr) (mac net.HardwareAddr) { ret...
function compareRuntimeInfo (line 117) | func compareRuntimeInfo(rc *client.Runtime, src client.Source, host stri...
function TestStorage_Add_hostsfile (line 128) | func TestStorage_Add_hostsfile(t *testing.T) {
function TestStorage_Add_arp (line 202) | func TestStorage_Add_arp(t *testing.T) {
function TestStorage_Add_whois (line 278) | func TestStorage_Add_whois(t *testing.T) {
function TestClientsDHCP (line 336) | func TestClientsDHCP(t *testing.T) {
function TestClientsAddExisting (line 549) | func TestClientsAddExisting(t *testing.T) {
function newStorage (line 640) | func newStorage(tb testing.TB, m []*client.Persistent) (s *client.Storag...
function TestStorage_Add (line 661) | func TestStorage_Add(t *testing.T) {
function TestStorage_RemoveByName (line 804) | func TestStorage_RemoveByName(t *testing.T) {
function TestStorage_Find (line 850) | func TestStorage_Find(t *testing.T) {
function TestStorage_FindLoose (line 959) | func TestStorage_FindLoose(t *testing.T) {
function TestStorage_Update (line 1020) | func TestStorage_Update(t *testing.T) {
function TestStorage_RangeByName (line 1109) | func TestStorage_RangeByName(t *testing.T) {
function TestStorage_CustomUpstreamConfig (line 1160) | func TestStorage_CustomUpstreamConfig(t *testing.T) {
function BenchmarkFindParams_Set (line 1295) | func BenchmarkFindParams_Set(b *testing.B) {
function BenchmarkStorage_Find (line 1371) | func BenchmarkStorage_Find(b *testing.B) {
FILE: internal/client/upstreammanager.go
type CommonUpstreamConfig (line 21) | type CommonUpstreamConfig struct
type customUpstreamConfig (line 31) | type customUpstreamConfig struct
type upstreamManager (line 59) | type upstreamManager struct
method updateCommonUpstreamConfig (line 95) | func (m *upstreamManager) updateCommonUpstreamConfig(conf *CommonUpstr...
method updateCustomUpstreamConfig (line 104) | func (m *upstreamManager) updateCustomUpstreamConfig(c *Persistent) {
method customUpstreamConfig (line 122) | func (m *upstreamManager) customUpstreamConfig(
method isConfigChanged (line 160) | func (m *upstreamManager) isConfigChanged(cliConf *customUpstreamConfi...
method clearUpstreamCache (line 166) | func (m *upstreamManager) clearUpstreamCache() {
method remove (line 176) | func (m *upstreamManager) remove(uid UID) (err error) {
method close (line 193) | func (m *upstreamManager) close() (err error) {
function newUpstreamManager (line 84) | func newUpstreamManager(baseLogger *slog.Logger, clock timeutil.Clock) (...
function newCustomUpstreamConfig (line 209) | func newCustomUpstreamConfig(
FILE: internal/configmigrate/configmigrate.go
constant LastSchemaVersion (line 5) | LastSchemaVersion uint = 33
FILE: internal/configmigrate/configmigrate_internal_test.go
constant testTimeout (line 10) | testTimeout = 1 * time.Second
FILE: internal/configmigrate/configmigrate_test.go
constant testTimeout (line 10) | testTimeout = 1 * time.Second
FILE: internal/configmigrate/migrations_internal_test.go
function emptyMigrator (line 17) | func emptyMigrator() (m *Migrator) {
function TestUpgradeSchema1to2 (line 25) | func TestUpgradeSchema1to2(t *testing.T) {
function TestUpgradeSchema2to3 (line 53) | func TestUpgradeSchema2to3(t *testing.T) {
function TestUpgradeSchema5to6 (line 89) | func TestUpgradeSchema5to6(t *testing.T) {
function TestUpgradeSchema7to8 (line 184) | func TestUpgradeSchema7to8(t *testing.T) {
function TestUpgradeSchema8to9 (line 214) | func TestUpgradeSchema8to9(t *testing.T) {
function assertEqualExcept (line 277) | func assertEqualExcept(tb testing.TB, oldConf, newConf yobj, oldKeys, ne...
function testDiskConf (line 290) | func testDiskConf(schemaVersion int) (diskConf yobj) {
function testDNSConf (line 323) | func testDNSConf(schemaVersion int) (dnsConf yobj) {
function TestAddQUICPort (line 349) | func TestAddQUICPort(t *testing.T) {
function TestUpgradeSchema9to10 (line 433) | func TestUpgradeSchema9to10(t *testing.T) {
function TestUpgradeSchema10to11 (line 519) | func TestUpgradeSchema10to11(t *testing.T) {
function TestUpgradeSchema11to12 (line 574) | func TestUpgradeSchema11to12(t *testing.T) {
function TestUpgradeSchema12to13 (line 687) | func TestUpgradeSchema12to13(t *testing.T) {
function TestUpgradeSchema13to14 (line 739) | func TestUpgradeSchema13to14(t *testing.T) {
function TestUpgradeSchema14to15 (line 827) | func TestUpgradeSchema14to15(t *testing.T) {
function TestUpgradeSchema15to16 (line 881) | func TestUpgradeSchema15to16(t *testing.T) {
function TestUpgradeSchema16to17 (line 946) | func TestUpgradeSchema16to17(t *testing.T) {
function TestUpgradeSchema17to18 (line 1013) | func TestUpgradeSchema17to18(t *testing.T) {
function TestUpgradeSchema18to19 (line 1078) | func TestUpgradeSchema18to19(t *testing.T) {
function TestUpgradeSchema19to20 (line 1168) | func TestUpgradeSchema19to20(t *testing.T) {
function TestUpgradeSchema20to21 (line 1286) | func TestUpgradeSchema20to21(t *testing.T) {
function TestUpgradeSchema21to22 (line 1335) | func TestUpgradeSchema21to22(t *testing.T) {
function TestUpgradeSchema22to23 (line 1411) | func TestUpgradeSchema22to23(t *testing.T) {
function TestUpgradeSchema23to24 (line 1470) | func TestUpgradeSchema23to24(t *testing.T) {
function TestUpgradeSchema24to25 (line 1543) | func TestUpgradeSchema24to25(t *testing.T) {
function TestUpgradeSchema25to26 (line 1636) | func TestUpgradeSchema25to26(t *testing.T) {
function TestUpgradeSchema26to27 (line 1741) | func TestUpgradeSchema26to27(t *testing.T) {
function TestUpgradeSchema27to28 (line 1830) | func TestUpgradeSchema27to28(t *testing.T) {
FILE: internal/configmigrate/migrator.go
type Config (line 13) | type Config struct
type Migrator (line 26) | type Migrator struct
method Migrate (line 45) | func (m *Migrator) Migrate(
method upgradeConfigSchema (line 108) | func (m *Migrator) upgradeConfigSchema(
function New (line 33) | func New(c *Config) (m *Migrator) {
function validateVersion (line 89) | func validateVersion(current, target uint) (err error) {
FILE: internal/configmigrate/migrator_test.go
function getField (line 26) | func getField[T any](t require.TestingT, obj any, indexes ...any) (val T) {
function TestMigrateConfig_Migrate (line 52) | func TestMigrateConfig_Migrate(t *testing.T) {
function TestMigrateConfig_Migrate_v29 (line 242) | func TestMigrateConfig_Migrate_v29(t *testing.T) {
FILE: internal/configmigrate/v1.go
method migrateTo1 (line 23) | func (m *Migrator) migrateTo1(ctx context.Context, diskConf yobj) (err e...
FILE: internal/configmigrate/v10.go
method migrateTo10 (line 34) | func (m *Migrator) migrateTo10(_ context.Context, diskConf yobj) (err er...
function addQUICPorts (line 71) | func addQUICPorts(ups yarr, port int) (err error) {
function addQUICPort (line 85) | func addQUICPort(ups string, port int) (withPort string) {
FILE: internal/configmigrate/v11.go
method migrateTo11 (line 19) | func (m *Migrator) migrateTo11(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v12.go
method migrateTo12 (line 21) | func (m *Migrator) migrateTo12(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v13.go
method migrateTo13 (line 20) | func (m *Migrator) migrateTo13(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v14.go
method migrateTo14 (line 32) | func (m *Migrator) migrateTo14(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v15.go
method migrateTo15 (line 35) | func (m *Migrator) migrateTo15(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v16.go
method migrateTo16 (line 48) | func (m *Migrator) migrateTo16(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v17.go
method migrateTo17 (line 23) | func (m *Migrator) migrateTo17(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v18.go
method migrateTo18 (line 27) | func (m *Migrator) migrateTo18(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v19.go
method migrateTo19 (line 37) | func (m *Migrator) migrateTo19(ctx context.Context, diskConf yobj) (err ...
FILE: internal/configmigrate/v2.go
method migrateTo2 (line 25) | func (m *Migrator) migrateTo2(ctx context.Context, diskConf yobj) (err e...
FILE: internal/configmigrate/v20.go
method migrateTo20 (line 25) | func (m *Migrator) migrateTo20(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v21.go
method migrateTo21 (line 27) | func (m *Migrator) migrateTo21(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v22.go
method migrateTo22 (line 34) | func (m *Migrator) migrateTo22(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v23.go
method migrateTo23 (line 27) | func (m *Migrator) migrateTo23(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v24.go
method migrateTo24 (line 33) | func (m *Migrator) migrateTo24(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v25.go
method migrateTo25 (line 19) | func (m *Migrator) migrateTo25(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v26.go
method migrateTo26 (line 78) | func (m *Migrator) migrateTo26(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v27.go
method migrateTo27 (line 32) | func (m *Migrator) migrateTo27(_ context.Context, diskConf yobj) (err er...
function replaceDot (line 48) | func replaceDot(diskConf yobj, key string) (err error) {
FILE: internal/configmigrate/v28.go
method migrateTo28 (line 23) | func (m *Migrator) migrateTo28(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v29.go
method migrateTo29 (line 30) | func (m Migrator) migrateTo29(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v3.go
method migrateTo3 (line 19) | func (m *Migrator) migrateTo3(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v30.go
method migrateTo30 (line 19) | func (m Migrator) migrateTo30(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v31.go
method migrateTo31 (line 23) | func (m *Migrator) migrateTo31(_ context.Context, diskConf yobj) (err er...
FILE: internal/configmigrate/v32.go
method migrateTo32 (line 22) | func (m Migrator) migrateTo32(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v33.go
method migrateTo33 (line 30) | func (m Migrator) migrateTo33(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v4.go
method migrateTo4 (line 19) | func (m *Migrator) migrateTo4(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v5.go
method migrateTo5 (line 24) | func (m *Migrator) migrateTo5(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v6.go
method migrateTo6 (line 30) | func (m *Migrator) migrateTo6(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v7.go
method migrateTo7 (line 37) | func (m *Migrator) migrateTo7(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v8.go
method migrateTo8 (line 21) | func (m *Migrator) migrateTo8(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/v9.go
method migrateTo9 (line 20) | func (m *Migrator) migrateTo9(_ context.Context, diskConf yobj) (err err...
FILE: internal/configmigrate/yaml.go
function fieldVal (line 17) | func fieldVal[T any](obj yobj, key string) (v T, ok bool, err error) {
function moveVal (line 37) | func moveVal[T any](src, dst yobj, srcKey, dstKey string) (err error) {
function moveSameVal (line 50) | func moveSameVal[T any](src, dst yobj, key string) (err error) {
FILE: internal/dhcpd/bitset.go
constant bitsPerWord (line 3) | bitsPerWord = 64
type bitSet (line 6) | type bitSet struct
method isSet (line 18) | func (s *bitSet) isSet(n uint64) (ok bool) {
method set (line 33) | func (s *bitSet) set(n uint64, ok bool) {
function newBitSet (line 11) | func newBitSet() (s *bitSet) {
FILE: internal/dhcpd/bitset_internal_test.go
function TestBitSet (line 11) | func TestBitSet(t *testing.T) {
FILE: internal/dhcpd/broadcast_bsd.go
method broadcast (line 10) | func (c *dhcpConn) broadcast(respData []byte, peer *net.UDPAddr) (n int,...
FILE: internal/dhcpd/broadcast_bsd_internal_test.go
function TestDHCPConn_Broadcast (line 15) | func TestDHCPConn_Broadcast(t *testing.T) {
FILE: internal/dhcpd/broadcast_others.go
method broadcast (line 10) | func (c *dhcpConn) broadcast(respData []byte, peer *net.UDPAddr) (n int,...
FILE: internal/dhcpd/broadcast_others_internal_test.go
function TestDHCPConn_Broadcast (line 15) | func TestDHCPConn_Broadcast(t *testing.T) {
FILE: internal/dhcpd/config.go
type ServerConfig (line 21) | type ServerConfig struct
type DHCPServer (line 63) | type DHCPServer interface
type V4ServerConf (line 101) | type V4ServerConf struct
method Validate (line 172) | func (c *V4ServerConf) Validate() (err error) {
constant errNilConfig (line 155) | errNilConfig errors.Error = "nil config"
function ensureV4 (line 159) | func ensureV4(ip netip.Addr, kind string) (ip4 netip.Addr, err error) {
type V6ServerConf (line 244) | type V6ServerConf struct
FILE: internal/dhcpd/conn_bsd.go
type dhcpUnicastAddr (line 26) | type dhcpUnicastAddr struct
type dhcpConn (line 38) | type dhcpConn struct
method WriteTo (line 86) | func (c *dhcpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
method ReadFrom (line 122) | func (c *dhcpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
method unicast (line 127) | func (c *dhcpConn) unicast(respData []byte, peer *dhcpUnicastAddr) (n ...
method Close (line 138) | func (c *dhcpConn) Close() (err error) {
method LocalAddr (line 149) | func (c *dhcpConn) LocalAddr() (a net.Addr) {
method SetDeadline (line 154) | func (c *dhcpConn) SetDeadline(t time.Time) (err error) {
method SetReadDeadline (line 159) | func (c *dhcpConn) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 168) | func (c *dhcpConn) SetWriteDeadline(t time.Time) error {
method buildEtherPkt (line 184) | func (c *dhcpConn) buildEtherPkt(payload []byte, peer *dhcpUnicastAddr...
method newDHCPConn (line 54) | func (s *v4Server) newDHCPConn(iface *net.Interface) (c net.PacketConn, ...
constant ipv4DefaultTTL (line 180) | ipv4DefaultTTL = 64
method send (line 234) | func (s *v4Server) send(peer net.Addr, conn net.PacketConn, req, resp *d...
FILE: internal/dhcpd/conn_bsd_internal_test.go
function TestDHCPConn_WriteTo_common (line 20) | func TestDHCPConn_WriteTo_common(t *testing.T) {
function TestBuildEtherPkt (line 54) | func TestBuildEtherPkt(t *testing.T) {
function TestV4Server_Send (line 116) | func TestV4Server_Send(t *testing.T) {
FILE: internal/dhcpd/conn_linux.go
type dhcpUnicastAddr (line 24) | type dhcpUnicastAddr struct
type dhcpConn (line 36) | type dhcpConn struct
method WriteTo (line 84) | func (c *dhcpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
method ReadFrom (line 120) | func (c *dhcpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
method unicast (line 125) | func (c *dhcpConn) unicast(respData []byte, peer *dhcpUnicastAddr) (n ...
method Close (line 136) | func (c *dhcpConn) Close() (err error) {
method LocalAddr (line 147) | func (c *dhcpConn) LocalAddr() (a net.Addr) {
method SetDeadline (line 152) | func (c *dhcpConn) SetDeadline(t time.Time) (err error) {
method SetReadDeadline (line 157) | func (c *dhcpConn) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 166) | func (c *dhcpConn) SetWriteDeadline(t time.Time) error {
method buildEtherPkt (line 182) | func (c *dhcpConn) buildEtherPkt(payload []byte, peer *dhcpUnicastAddr...
method newDHCPConn (line 52) | func (s *v4Server) newDHCPConn(iface *net.Interface) (c net.PacketConn, ...
constant ipv4DefaultTTL (line 178) | ipv4DefaultTTL = 64
method send (line 232) | func (s *v4Server) send(peer net.Addr, conn net.PacketConn, req, resp *d...
FILE: internal/dhcpd/conn_linux_internal_test.go
function TestDHCPConn_WriteTo_common (line 18) | func TestDHCPConn_WriteTo_common(t *testing.T) {
function TestBuildEtherPkt (line 52) | func TestBuildEtherPkt(t *testing.T) {
function TestV4Server_Send (line 114) | func TestV4Server_Send(t *testing.T) {
FILE: internal/dhcpd/conn_unix.go
function wrapErrs (line 13) | func wrapErrs(action string, udpConnErr, rawConnErr error) (err error) {
FILE: internal/dhcpd/db.go
constant dataFilename (line 24) | dataFilename = "leases.json"
constant dataVersion (line 27) | dataVersion = 1
type dataLeases (line 31) | type dataLeases struct
type dbLease (line 40) | type dbLease struct
method toLease (line 69) | func (dl *dbLease) toLease() (l *dhcpsvc.Lease, err error) {
function fromLease (line 49) | func fromLease(l *dhcpsvc.Lease) (dl *dbLease) {
method dbLoad (line 93) | func (s *server) dbLoad() (err error) {
method dbStore (line 152) | func (s *server) dbStore() (err error) {
function writeDB (line 171) | func writeDB(path string, leases []*dbLease) (err error) {
FILE: internal/dhcpd/dhcpd.go
constant DefaultDHCPLeaseTTL (line 19) | DefaultDHCPLeaseTTL = uint32(timeutil.Day / time.Second)
constant DefaultDHCPTimeoutICMP (line 22) | DefaultDHCPTimeoutICMP = 1000
constant defaultMaxAttempts (line 27) | defaultMaxAttempts int = 10
constant defaultBackoff (line 28) | defaultBackoff time.Duration = 500 * time.Millisecond
type OnLeaseChangedT (line 32) | type OnLeaseChangedT
constant LeaseChangedAdded (line 36) | LeaseChangedAdded = iota
constant LeaseChangedAddedStatic (line 37) | LeaseChangedAddedStatic
constant LeaseChangedRemovedStatic (line 38) | LeaseChangedRemovedStatic
constant LeaseChangedRemovedAll (line 39) | LeaseChangedRemovedAll
constant LeaseChangedDBStore (line 41) | LeaseChangedDBStore
type GetLeasesFlags (line 45) | type GetLeasesFlags
constant LeasesDynamic (line 49) | LeasesDynamic GetLeasesFlags = 0b01
constant LeasesStatic (line 50) | LeasesStatic GetLeasesFlags = 0b10
constant LeasesAll (line 52) | LeasesAll = LeasesDynamic | LeasesStatic
type Interface (line 56) | type Interface interface
type server (line 91) | type server struct
method setServers (line 163) | func (s *server) setServers(
method Enabled (line 197) | func (s *server) Enabled() (ok bool) {
method resetLeases (line 202) | func (s *server) resetLeases() (err error) {
method onNotify (line 219) | func (s *server) onNotify(flags uint32) {
method notify (line 234) | func (s *server) notify(flags int) {
method WriteDiskConfig (line 241) | func (s *server) WriteDiskConfig(c *ServerConfig) {
method Start (line 251) | func (s *server) Start(ctx context.Context) (err error) {
method Stop (line 266) | func (s *server) Stop() (err error) {
method Leases (line 281) | func (s *server) Leases() (leases []*dhcpsvc.Lease) {
method MACByIP (line 287) | func (s *server) MACByIP(ip netip.Addr) (mac net.HardwareAddr) {
method HostByIP (line 298) | func (s *server) HostByIP(ip netip.Addr) (host string) {
method IPByHost (line 309) | func (s *server) IPByHost(host string) (ip netip.Addr) {
method AddStaticLease (line 314) | func (s *server) AddStaticLease(l *dhcpsvc.Lease) error {
function Create (line 108) | func Create(ctx context.Context, conf *ServerConfig) (s *server, err err...
FILE: internal/dhcpd/dhcpd_internal_test.go
constant testTimeout (line 10) | testTimeout = 1 * time.Second
FILE: internal/dhcpd/dhcpd_unix_internal_test.go
function TestMain (line 19) | func TestMain(m *testing.M) {
function testNotify (line 23) | func testNotify(flags uint32) {
function TestDB (line 27) | func TestDB(t *testing.T) {
function TestV4Server_badRange (line 89) | func TestV4Server_badRange(t *testing.T) {
function cloneUDPAddr (line 133) | func cloneUDPAddr(a *net.UDPAddr) (clone *net.UDPAddr) {
FILE: internal/dhcpd/http_unix.go
type v4ServerConfJSON (line 29) | type v4ServerConfJSON struct
method toServerConf (line 37) | func (j *v4ServerConfJSON) toServerConf() *V4ServerConf {
type v6ServerConfJSON (line 51) | type v6ServerConfJSON struct
function v6JSONToServerConf (line 56) | func v6JSONToServerConf(j *v6ServerConfJSON) V6ServerConf {
type dhcpStatusResponse (line 68) | type dhcpStatusResponse struct
type leaseStatic (line 78) | type leaseStatic struct
method toLease (line 100) | func (l *leaseStatic) toLease() (lease *dhcpsvc.Lease, err error) {
function leasesToStatic (line 85) | func leasesToStatic(leases []*dhcpsvc.Lease) (static []*leaseStatic) {
type leaseDynamic (line 115) | type leaseDynamic struct
function leasesToDynamic (line 123) | func leasesToDynamic(leases []*dhcpsvc.Lease) (dynamic []*leaseDynamic) {
method handleDHCPStatus (line 142) | func (s *server) handleDHCPStatus(w http.ResponseWriter, r *http.Request) {
method enableDHCP (line 178) | func (s *server) enableDHCP(ctx context.Context, ifaceName string) (code...
type dhcpServerConfigJSON (line 226) | type dhcpServerConfigJSON struct
method handleDHCPSetConfigV4 (line 233) | func (s *server) handleDHCPSetConfigV4(
method handleDHCPSetConfigV6 (line 266) | func (s *server) handleDHCPSetConfigV6(
method createServers (line 298) | func (s *server) createServers(conf *dhcpServerConfigJSON) (srv4, srv6 D...
method handleDHCPSetConfig (line 318) | func (s *server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Requ...
method setConfFromJSON (line 384) | func (s *server) setConfFromJSON(conf *dhcpServerConfigJSON, srv4, srv6 ...
type netInterfaceJSON (line 402) | type netInterfaceJSON struct
method handleDHCPInterfaces (line 413) | func (s *server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Req...
function newNetInterfaceJSON (line 462) | func newNetInterfaceJSON(
type dhcpSearchOtherResult (line 526) | type dhcpSearchOtherResult struct
type dhcpStaticIPStatus (line 533) | type dhcpStaticIPStatus struct
type dhcpSearchV4Result (line 541) | type dhcpSearchV4Result struct
type dhcpSearchV6Result (line 548) | type dhcpSearchV6Result struct
type dhcpSearchResult (line 553) | type dhcpSearchResult struct
type findActiveServerReq (line 560) | type findActiveServerReq struct
method handleDHCPFindActiveServer (line 568) | func (s *server) handleDHCPFindActiveServer(w http.ResponseWriter, r *ht...
method setOtherDHCPResult (line 624) | func (s *server) setOtherDHCPResult(
method parseLease (line 647) | func (s *server) parseLease(r io.Reader) (srv DHCPServer, lease *dhcpsvc...
method handleDHCPAddStaticLease (line 676) | func (s *server) handleDHCPAddStaticLease(w http.ResponseWriter, r *http...
method handleDHCPRemoveStaticLease (line 694) | func (s *server) handleDHCPRemoveStaticLease(w http.ResponseWriter, r *h...
method handleDHCPUpdateStaticLease (line 712) | func (s *server) handleDHCPUpdateStaticLease(w http.ResponseWriter, r *h...
method handleReset (line 728) | func (s *server) handleReset(w http.ResponseWriter, r *http.Request) {
method handleResetLeases (line 775) | func (s *server) handleResetLeases(w http.ResponseWriter, r *http.Reques...
method registerHandlers (line 787) | func (s *server) registerHandlers() {
FILE: internal/dhcpd/http_unix_internal_test.go
function defaultResponse (line 21) | func defaultResponse() *dhcpStatusResponse {
function handleLease (line 38) | func handleLease(tb testing.TB, lease *leaseStatic, handler http.Handler...
function checkStatus (line 58) | func checkStatus(t *testing.T, s *server, want *dhcpStatusResponse) {
function TestServer_handleDHCPStatus (line 74) | func TestServer_handleDHCPStatus(t *testing.T) {
function TestServer_HandleUpdateStaticLease (line 154) | func TestServer_HandleUpdateStaticLease(t *testing.T) {
function TestServer_HandleUpdateStaticLease_validation (line 252) | func TestServer_HandleUpdateStaticLease_validation(t *testing.T) {
FILE: internal/dhcpd/http_windows.go
type jsonError (line 16) | type jsonError struct
method notImplemented (line 26) | func (s *server) notImplemented(w http.ResponseWriter, r *http.Request) {
method registerHandlers (line 41) | func (s *server) registerHandlers() {
FILE: internal/dhcpd/http_windows_internal_test.go
function TestServer_notImplemented (line 16) | func TestServer_notImplemented(t *testing.T) {
FILE: internal/dhcpd/iprange.go
type ipRange (line 21) | type ipRange struct
method contains (line 58) | func (r *ipRange) contains(ip net.IP) (ok bool) {
method containsInt (line 69) | func (r *ipRange) containsInt(ipInt *big.Int) (ok bool) {
method find (line 79) | func (r *ipRange) find(p ipPredicate) (ip net.IP) {
method offset (line 98) | func (r *ipRange) offset(ip net.IP) (offset uint64, ok bool) {
method String (line 117) | func (r *ipRange) String() (s string) {
constant maxRangeLen (line 28) | maxRangeLen = math.MaxUint32
function newIPRange (line 32) | func newIPRange(start, end net.IP) (r *ipRange, err error) {
type ipPredicate (line 75) | type ipPredicate
FILE: internal/dhcpd/iprange_internal_test.go
function TestNewIPRange (line 12) | func TestNewIPRange(t *testing.T) {
function TestIPRange_Contains (line 74) | func TestIPRange_Contains(t *testing.T) {
function TestIPRange_Find (line 87) | func TestIPRange_Find(t *testing.T) {
function TestIPRange_Offset (line 105) | func TestIPRange_Offset(t *testing.T) {
FILE: internal/dhcpd/migrate.go
constant leaseExpireStatic (line 21) | leaseExpireStatic = 1
constant dbFilename (line 26) | dbFilename = "leases.db"
type leaseJSON (line 32) | type leaseJSON struct
function readOldDB (line 40) | func readOldDB(path string) (leases []*leaseJSON, err error) {
function migrateDB (line 64) | func migrateDB(conf *ServerConfig) (err error) {
function normalizeIP (line 109) | func normalizeIP(ip net.IP) (normalized net.IP) {
FILE: internal/dhcpd/migrate_internal_test.go
constant testData (line 15) | testData = `[
function TestMigrateDB (line 20) | func TestMigrateDB(t *testing.T) {
FILE: internal/dhcpd/options_unix.go
constant typDel (line 24) | typDel = "del"
constant typBool (line 25) | typBool = "bool"
constant typDur (line 26) | typDur = "dur"
constant typHex (line 27) | typHex = "hex"
constant typIP (line 28) | typIP = "ip"
constant typIPs (line 29) | typIPs = "ips"
constant typText (line 30) | typText = "text"
constant typU8 (line 31) | typU8 = "u8"
constant typU16 (line 32) | typU16 = "u16"
function parseDHCPOptionHex (line 36) | func parseDHCPOptionHex(s string) (val dhcpv4.OptionValue, err error) {
function parseDHCPOptionIP (line 47) | func parseDHCPOptionIP(s string) (val dhcpv4.OptionValue, err error) {
function parseDHCPOptionIPs (line 63) | func parseDHCPOptionIPs(s string) (val dhcpv4.OptionValue, err error) {
function parseDHCPOptionDur (line 80) | func parseDHCPOptionDur(s string) (val dhcpv4.OptionValue, err error) {
function parseDHCPOptionUint (line 92) | func parseDHCPOptionUint(s string, bitSize int) (val dhcpv4.OptionValue,...
function parseDHCPOptionBool (line 111) | func parseDHCPOptionBool(s string) (val dhcpv4.OptionValue, err error) {
function parseDHCPOptionVal (line 127) | func parseDHCPOptionVal(typ, valStr string) (val dhcpv4.OptionValue, err...
function parseDHCPOption (line 166) | func parseDHCPOption(s string) (code dhcpv4.OptionCode, val dhcpv4.Optio...
method prepareOptions (line 199) | func (s *v4Server) prepareOptions() {
FILE: internal/dhcpd/options_unix_internal_test.go
function TestParseOpt (line 17) | func TestParseOpt(t *testing.T) {
function TestPrepareOptions (line 176) | func TestPrepareOptions(t *testing.T) {
FILE: internal/dhcpd/routeradv.go
type raCtx (line 19) | type raCtx struct
method Init (line 228) | func (ra *raCtx) Init() (err error) {
method Close (line 301) | func (ra *raCtx) Close() (err error) {
type icmpv6RA (line 62) | type icmpv6RA struct
function hwAddrToLinkLayerAddr (line 77) | func hwAddrToLinkLayerAddr(hwa net.HardwareAddr) (lla []byte, err error) {
function createICMPv6RAPacket (line 125) | func createICMPv6RAPacket(params icmpv6RA) (data []byte, err error) {
FILE: internal/dhcpd/routeradv_internal_test.go
function TestCreateICMPv6RAPacket (line 13) | func TestCreateICMPv6RAPacket(t *testing.T) {
FILE: internal/dhcpd/v46_windows.go
type winServer (line 15) | type winServer struct
method ResetLeases (line 20) | func (winServer) ResetLeases(_ []*dhcpsvc.Lease) (err error) ...
method GetLeases (line 21) | func (winServer) GetLeases(_ GetLeasesFlags) (leases []*dhcpsvc.Lease)...
method getLeasesRef (line 22) | func (winServer) getLeasesRef() []*dhcpsvc.Lease ...
method AddStaticLease (line 23) | func (winServer) AddStaticLease(_ *dhcpsvc.Lease) (err error) ...
method RemoveStaticLease (line 24) | func (winServer) RemoveStaticLease(_ *dhcpsvc.Lease) (err error) ...
method UpdateStaticLease (line 25) | func (winServer) UpdateStaticLease(_ *dhcpsvc.Lease) (err error) ...
method FindMACbyIP (line 26) | func (winServer) FindMACbyIP(_ netip.Addr) (mac net.HardwareAddr) ...
method WriteDiskConfig4 (line 27) | func (winServer) WriteDiskConfig4(_ *V4ServerConf) {}
method WriteDiskConfig6 (line 28) | func (winServer) WriteDiskConfig6(_ *V6ServerConf) {}
method Start (line 29) | func (winServer) Start(_ context.Context) (err error) ...
method Stop (line 30) | func (winServer) Stop() (err error) ...
method HostByIP (line 31) | func (winServer) HostByIP(_ netip.Addr) (host string) ...
method IPByHost (line 32) | func (winServer) IPByHost(_ string) (ip netip.Addr) ...
function v4Create (line 34) | func v4Create(_ *V4ServerConf) (s DHCPServer, err error) { return winSer...
function v6Create (line 35) | func v6Create(_ V6ServerConf) (s DHCPServer, err error) { return winSer...
FILE: internal/dhcpd/v4_unix.go
type v4Server (line 32) | type v4Server struct
method enabled (line 62) | func (s *v4Server) enabled() (ok bool) {
method WriteDiskConfig4 (line 67) | func (s *v4Server) WriteDiskConfig4(c *V4ServerConf) {
method WriteDiskConfig6 (line 74) | func (s *v4Server) WriteDiskConfig6(c *V6ServerConf) {
method validHostnameForClient (line 104) | func (s *v4Server) validHostnameForClient(cliHostname string, ip netip...
method HostByIP (line 124) | func (s *v4Server) HostByIP(ip netip.Addr) (host string) {
method IPByHost (line 136) | func (s *v4Server) IPByHost(host string) (ip netip.Addr) {
method ResetLeases (line 148) | func (s *v4Server) ResetLeases(leases []*dhcpsvc.Lease) (err error) {
method getLeasesRef (line 180) | func (s *v4Server) getLeasesRef() []*dhcpsvc.Lease {
method isBlocklisted (line 187) | func (s *v4Server) isBlocklisted(l *dhcpsvc.Lease) (ok bool) {
method GetLeases (line 203) | func (s *v4Server) GetLeases(flags GetLeasesFlags) (leases []*dhcpsvc....
method FindMACbyIP (line 232) | func (s *v4Server) FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr) {
method blocklistLease (line 255) | func (s *v4Server) blocklistLease(l *dhcpsvc.Lease) {
method rmLeaseByIndex (line 262) | func (s *v4Server) rmLeaseByIndex(i int) {
method rmDynamicLease (line 291) | func (s *v4Server) rmDynamicLease(lease *dhcpsvc.Lease) (err error) {
method addLease (line 327) | func (s *v4Server) addLease(l *dhcpsvc.Lease) (err error) {
method rmLease (line 359) | func (s *v4Server) rmLease(lease *dhcpsvc.Lease) (err error) {
method AddStaticLease (line 385) | func (s *v4Server) AddStaticLease(l *dhcpsvc.Lease) (err error) {
method UpdateStaticLease (line 442) | func (s *v4Server) UpdateStaticLease(l *dhcpsvc.Lease) (err error) {
method validateStaticLease (line 481) | func (s *v4Server) validateStaticLease(l *dhcpsvc.Lease) (err error) {
method updateStaticLease (line 518) | func (s *v4Server) updateStaticLease(l *dhcpsvc.Lease) (err error) {
method RemoveStaticLease (line 536) | func (s *v4Server) RemoveStaticLease(l *dhcpsvc.Lease) (err error) {
method addrAvailable (line 572) | func (s *v4Server) addrAvailable(target net.IP) (avail bool) {
method findLease (line 613) | func (s *v4Server) findLease(mac net.HardwareAddr) (l *dhcpsvc.Lease) {
method nextIP (line 624) | func (s *v4Server) nextIP() (ip net.IP) {
method findExpiredLease (line 640) | func (s *v4Server) findExpiredLease() int {
method reserveLease (line 653) | func (s *v4Server) reserveLease(mac net.HardwareAddr) (l *dhcpsvc.Leas...
method commitLease (line 686) | func (s *v4Server) commitLease(l *dhcpsvc.Lease, hostname string) {
method allocateLease (line 716) | func (s *v4Server) allocateLease(mac net.HardwareAddr) (l *dhcpsvc.Lea...
method handleDiscover (line 735) | func (s *v4Server) handleDiscover(req, resp *dhcpv4.DHCPv4) (l *dhcpsv...
method checkLease (line 794) | func (s *v4Server) checkLease(mac net.HardwareAddr, ip net.IP) (l *dhc...
method handleSelecting (line 826) | func (s *v4Server) handleSelecting(
method handleInitReboot (line 864) | func (s *v4Server) handleInitReboot(
method handleRenew (line 909) | func (s *v4Server) handleRenew(req *dhcpv4.DHCPv4) (l *dhcpsvc.Lease, ...
method handleByRequestType (line 936) | func (s *v4Server) handleByRequestType(req *dhcpv4.DHCPv4) (lease *dhc...
method handleRequest (line 960) | func (s *v4Server) handleRequest(req, resp *dhcpv4.DHCPv4) (lease *dhc...
method handleDecline (line 1000) | func (s *v4Server) handleDecline(req, resp *dhcpv4.DHCPv4) (err error) {
method findLeaseForIP (line 1053) | func (s *v4Server) findLeaseForIP(ip net.IP, mac net.HardwareAddr) (l ...
method handleRelease (line 1071) | func (s *v4Server) handleRelease(req, resp *dhcpv4.DHCPv4) (err error) {
method handle (line 1190) | func (s *v4Server) handle(req, resp *dhcpv4.DHCPv4) (rCode int) {
method updateOptions (line 1229) | func (s *v4Server) updateOptions(req, resp *dhcpv4.DHCPv4) {
method packetHandler (line 1262) | func (s *v4Server) packetHandler(conn net.PacketConn, peer net.Addr, r...
method Start (line 1303) | func (s *v4Server) Start(ctx context.Context) (err error) {
method configureDNSIPAddrs (line 1372) | func (s *v4Server) configureDNSIPAddrs(dnsIPAddrs []net.IP) {
method Stop (line 1393) | func (s *v4Server) Stop() (err error) {
function normalizeHostname (line 79) | func normalizeHostname(hostname string) (norm string, err error) {
constant defaultHwAddrLen (line 252) | defaultHwAddrLen = 6
constant ErrDupHostname (line 319) | ErrDupHostname = errors.Error("hostname is not unique")
constant ErrDupIP (line 323) | ErrDupIP = errors.Error("ip address is not unique")
constant ErrUnconfigured (line 381) | ErrUnconfigured errors.Error = "server is unconfigured"
function OptionFQDN (line 774) | func OptionFQDN(fqdn string) (opt dhcpv4.Option) {
type messageHandler (line 1114) | type messageHandler
function v4Create (line 1414) | func v4Create(conf *V4ServerConf) (srv *v4Server, err error) {
FILE: internal/dhcpd/v4_unix_internal_test.go
function defaultV4ServerConf (line 33) | func defaultV4ServerConf() (conf *V4ServerConf) {
function defaultSrv (line 47) | func defaultSrv(tb testing.TB) (s DHCPServer) {
function TestV4Server_leasing (line 57) | func TestV4Server_leasing(t *testing.T) {
function TestV4Server_AddRemove_static (line 205) | func TestV4Server_AddRemove_static(t *testing.T) {
function TestV4_AddReplace (line 287) | func TestV4_AddReplace(t *testing.T) {
function TestV4Server_handle_optionsPriority (line 333) | func TestV4Server_handle_optionsPriority(t *testing.T) {
function TestV4Server_updateOptions (line 404) | func TestV4Server_updateOptions(t *testing.T) {
function TestV4StaticLease_Get (line 507) | func TestV4StaticLease_Get(t *testing.T) {
function TestV4DynamicLease_Get (line 599) | func TestV4DynamicLease_Get(t *testing.T) {
function TestNormalizeHostname (line 698) | func TestNormalizeHostname(t *testing.T) {
type fakePacketConn (line 757) | type fakePacketConn struct
method WriteTo (line 766) | func (fc *fakePacketConn) WriteTo(p []byte, addr net.Addr) (n int, err...
function TestV4Server_FindMACbyIP (line 770) | func TestV4Server_FindMACbyIP(t *testing.T) {
function TestV4Server_handleDecline (line 835) | func TestV4Server_handleDecline(t *testing.T) {
function TestV4Server_handleRelease (line 877) | func TestV4Server_handleRelease(t *testing.T) {
FILE: internal/dhcpd/v6_unix.go
constant valueIAID (line 25) | valueIAID = "ADGH"
type v6Server (line 30) | type v6Server struct
method WriteDiskConfig4 (line 42) | func (s *v6Server) WriteDiskConfig4(c *V4ServerConf) {
method WriteDiskConfig6 (line 46) | func (s *v6Server) WriteDiskConfig6(c *V6ServerConf) {
method HostByIP (line 64) | func (s *v6Server) HostByIP(ip netip.Addr) (host string) {
method IPByHost (line 78) | func (s *v6Server) IPByHost(host string) (ip netip.Addr) {
method ResetLeases (line 92) | func (s *v6Server) ResetLeases(leases []*dhcpsvc.Lease) (err error) {
method GetLeases (line 116) | func (s *v6Server) GetLeases(flags GetLeasesFlags) (leases []*dhcpsvc....
method getLeasesRef (line 140) | func (s *v6Server) getLeasesRef() []*dhcpsvc.Lease {
method FindMACbyIP (line 145) | func (s *v6Server) FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr) {
method leaseRemoveSwapByIndex (line 167) | func (s *v6Server) leaseRemoveSwapByIndex(i int) {
method rmDynamicLease (line 181) | func (s *v6Server) rmDynamicLease(lease *dhcpsvc.Lease) (err error) {
method AddStaticLease (line 211) | func (s *v6Server) AddStaticLease(l *dhcpsvc.Lease) (err error) {
method UpdateStaticLease (line 243) | func (s *v6Server) UpdateStaticLease(l *dhcpsvc.Lease) (err error) {
method RemoveStaticLease (line 274) | func (s *v6Server) RemoveStaticLease(l *dhcpsvc.Lease) (err error) {
method addLease (line 299) | func (s *v6Server) addLease(l *dhcpsvc.Lease) {
method rmLease (line 307) | func (s *v6Server) rmLease(lease *dhcpsvc.Lease) (err error) {
method findLease (line 325) | func (s *v6Server) findLease(mac net.HardwareAddr) (lease *dhcpsvc.Lea...
method findExpiredLease (line 336) | func (s *v6Server) findExpiredLease() int {
method findFreeIP (line 347) | func (s *v6Server) findFreeIP() net.IP {
method reserveLease (line 363) | func (s *v6Server) reserveLease(mac net.HardwareAddr) *dhcpsvc.Lease {
method commitDynamicLease (line 397) | func (s *v6Server) commitDynamicLease(l *dhcpsvc.Lease) {
method checkCID (line 407) | func (s *v6Server) checkCID(msg *dhcpv6.Message) error {
method checkSID (line 416) | func (s *v6Server) checkSID(msg *dhcpv6.Message) error {
method checkIA (line 445) | func (s *v6Server) checkIA(msg *dhcpv6.Message, lease *dhcpsvc.Lease) ...
method commitLease (line 471) | func (s *v6Server) commitLease(msg *dhcpv6.Message, lease *dhcpsvc.Lea...
method process (line 493) | func (s *v6Server) process(msg *dhcpv6.Message, req, resp dhcpv6.DHCPv...
method packetHandler (line 594) | func (s *v6Server) packetHandler(conn net.PacketConn, peer net.Addr, r...
method configureDNSIPAddrs (line 661) | func (s *v6Server) configureDNSIPAddrs(
method initRA (line 687) | func (s *v6Server) initRA(iface *net.Interface) (err error) {
method Start (line 709) | func (s *v6Server) Start(ctx context.Context) (err error) {
method Stop (line 772) | func (s *v6Server) Stop() (err error) {
function ip6InRange (line 51) | func ip6InRange(start, ip net.IP) bool {
function v6Create (line 796) | func v6Create(conf V6ServerConf) (DHCPServer, error) {
FILE: internal/dhcpd/v6_unix_internal_test.go
function notify6 (line 18) | func notify6(flags uint32) {
function TestV6_AddRemove_static (line 21) | func TestV6_AddRemove_static(t *testing.T) {
function TestV6_AddReplace (line 64) | func TestV6_AddReplace(t *testing.T) {
function TestV6GetLease (line 111) | func TestV6GetLease(t *testing.T) {
function TestV6GetDynamicLease (line 206) | func TestV6GetDynamicLease(t *testing.T) {
function TestIP6InRange (line 288) | func TestIP6InRange(t *testing.T) {
function TestV6_FindMACbyIP (line 315) | func TestV6_FindMACbyIP(t *testing.T) {
FILE: internal/dhcpsvc/addresschecker.go
type addressChecker (line 6) | type addressChecker interface
type noopAddressChecker (line 14) | type noopAddressChecker struct
method IsAvailable (line 17) | func (c noopAddressChecker) IsAvailable(ip netip.Addr) (ok bool, err e...
FILE: internal/dhcpsvc/bitset.go
constant bitsPerWord (line 3) | bitsPerWord = 64
type bitSet (line 6) | type bitSet struct
method isSet (line 18) | func (s *bitSet) isSet(n uint64) (ok bool) {
method set (line 33) | func (s *bitSet) set(n uint64, ok bool) {
function newBitSet (line 11) | func newBitSet() (s *bitSet) {
FILE: internal/dhcpsvc/bitset_internal_test.go
function TestBitSet (line 11) | func TestBitSet(t *testing.T) {
FILE: internal/dhcpsvc/config.go
type Config (line 17) | type Config struct
method Validate (line 52) | func (conf *Config) Validate() (err error) {
type InterfaceConfig (line 94) | type InterfaceConfig struct
method Validate (line 106) | func (ic *InterfaceConfig) Validate() (err error) {
FILE: internal/dhcpsvc/config_test.go
function TestIPv4Config_Validate (line 16) | func TestIPv4Config_Validate(t *testing.T) {
function TestIPv6Config_Validate (line 121) | func TestIPv6Config_Validate(t *testing.T) {
function TestConfig_Validate (line 171) | func TestConfig_Validate(t *testing.T) {
FILE: internal/dhcpsvc/db.go
constant dataVersion (line 22) | dataVersion = 1
constant databasePerm (line 25) | databasePerm fs.FileMode = 0o640
type dataLeases (line 28) | type dataLeases struct
type dbLease (line 37) | type dbLease struct
method compareNames (line 47) | func (dl *dbLease) compareNames(other *dbLease) (res int) {
method toInternal (line 72) | func (dl *dbLease) toInternal() (l *Lease, err error) {
function toDBLease (line 52) | func toDBLease(l *Lease) (dl *dbLease) {
method dbLoad (line 97) | func (idx *leaseIndex) dbLoad(
method addDBLeases (line 131) | func (idx *leaseIndex) addDBLeases(
method dbStore (line 174) | func (idx *leaseIndex) dbStore(ctx context.Context, logger *slog.Logger)...
FILE: internal/dhcpsvc/db_internal_test.go
constant DatabasePerm (line 4) | DatabasePerm = databasePerm
FILE: internal/dhcpsvc/dhcpsvc.go
constant keyInterface (line 16) | keyInterface = "iface"
constant keyFamily (line 19) | keyFamily = "family"
type Interface (line 28) | type Interface interface
type Empty (line 79) | type Empty struct
method Start (line 85) | func (Empty) Start(_ context.Context) (err error) { return nil }
method Shutdown (line 88) | func (Empty) Shutdown(_ context.Context) (err error) { return nil }
method Config (line 91) | func (Empty) Config() (conf *Config) { return nil }
method Enabled (line 97) | func (Empty) Enabled() (ok bool) { return false }
method HostByIP (line 100) | func (Empty) HostByIP(_ netip.Addr) (host string) { return "" }
method MACByIP (line 103) | func (Empty) MACByIP(_ netip.Addr) (mac net.HardwareAddr) { return nil }
method IPByHost (line 106) | func (Empty) IPByHost(_ string) (ip netip.Addr) { return netip.Addr{} }
method Leases (line 109) | func (Empty) Leases() (leases []*Lease) { return nil }
method AddLease (line 112) | func (Empty) AddLease(_ context.Context, _ *Lease) (err error) { retur...
method UpdateStaticLease (line 115) | func (Empty) UpdateStaticLease(_ context.Context, _ *Lease) (err error...
method RemoveLease (line 118) | func (Empty) RemoveLease(_ context.Context, _ *Lease) (err error) { re...
method Reset (line 121) | func (Empty) Reset(_ context.Context) (err error) { return nil }
FILE: internal/dhcpsvc/dhcpsvc_test.go
constant testLocalTLD (line 29) | testLocalTLD = "local"
constant testIfaceName (line 32) | testIfaceName = "iface0"
constant testDBLeasesFilename (line 35) | testDBLeasesFilename = "leases.json"
constant testTimeout (line 38) | testTimeout = 10 * time.Second
constant testLeaseTTL (line 41) | testLeaseTTL = 24 * time.Hour
constant testXid (line 44) | testXid = 1
constant testGatewayIPv4Str (line 66) | testGatewayIPv4Str = "192.0.2.1"
constant testSubnetMaskV4Str (line 70) | testSubnetMaskV4Str = "255.255.255.0"
constant testRangeStartV4Str (line 74) | testRangeStartV4Str = "192.0.2.100"
constant testRangeEndV4Str (line 78) | testRangeEndV4Str = "192.0.2.200"
constant testIfaceAddrV4Str (line 82) | testIfaceAddrV4Str = "192.0.2.2"
constant testAnotherGatewayIPv4Str (line 86) | testAnotherGatewayIPv4Str = "198.51.100.1"
constant testAnotherSubnetMaskV4Str (line 90) | testAnotherSubnetMaskV4Str = "255.255.255.0"
constant testAnotherRangeStartV4Str (line 94) | testAnotherRangeStartV4Str = "198.51.100.100"
constant testAnotherRangeEndV4Str (line 98) | testAnotherRangeEndV4Str = "198.51.100.200"
constant testRangeStartV6Str (line 104) | testRangeStartV6Str = "2001:db8::1"
constant testAnotherRangeStartV6Str (line 108) | testAnotherRangeStartV6Str = "2001:db9::1"
function newTempDB (line 187) | func newTempDB(tb testing.TB) (dst string) {
function newTestDHCPServer (line 203) | func newTestDHCPServer(tb testing.TB, conf *dhcpsvc.Config) (srv *dhcpsv...
FILE: internal/dhcpsvc/errors.go
function newMustErr (line 11) | func newMustErr(valName, must string, val fmt.Stringer) (err error) {
FILE: internal/dhcpsvc/handle.go
method serveEther4 (line 15) | func (srv *DHCPServer) serveEther4(ctx context.Context, iface *dhcpInter...
FILE: internal/dhcpsvc/handler4.go
method serveV4 (line 17) | func (srv *DHCPServer) serveV4(
method handleDHCPv4 (line 63) | func (iface *dhcpInterfaceV4) handleDHCPv4(
method handleRequest (line 92) | func (iface *dhcpInterfaceV4) handleRequest(
method handleDiscover (line 144) | func (iface *dhcpInterfaceV4) handleDiscover(
method handleSelecting (line 184) | func (iface *dhcpInterfaceV4) handleSelecting(
method handleInitReboot (line 236) | func (iface *dhcpInterfaceV4) handleInitReboot(
method handleRenew (line 282) | func (iface *dhcpInterfaceV4) handleRenew(
method handleDecline (line 323) | func (iface *dhcpInterfaceV4) handleDecline(ctx context.Context, req *la...
method handleRelease (line 369) | func (iface *dhcpInterfaceV4) handleRelease(ctx context.Context, req *la...
FILE: internal/dhcpsvc/handler4_test.go
function TestDHCPServer_ServeEther4_discover (line 28) | func TestDHCPServer_ServeEther4_discover(t *testing.T) {
function TestDHCPServer_ServeEther4_discoverExpired (line 129) | func TestDHCPServer_ServeEther4_discoverExpired(t *testing.T) {
function TestDHCPServer_ServeEther4_release (line 163) | func TestDHCPServer_ServeEther4_release(t *testing.T) {
function TestDHCPServer_ServeEther4_requestSelecting (line 269) | func TestDHCPServer_ServeEther4_requestSelecting(t *testing.T) {
function TestDHCPServer_ServeEther4_requestInitReboot (line 385) | func TestDHCPServer_ServeEther4_requestInitReboot(t *testing.T) {
function TestDHCPServer_ServeEther4_requestRenew (line 484) | func TestDHCPServer_ServeEther4_requestRenew(t *testing.T) {
function TestDHCPServer_ServeEther4_decline (line 593) | func TestDHCPServer_ServeEther4_decline(t *testing.T) {
type dhcpRequestConfig (line 708) | type dhcpRequestConfig struct
function newDHCPREQUEST (line 729) | func newDHCPREQUEST(tb testing.TB, conf *dhcpRequestConfig) (pkt gopacke...
function newDHCPDISCOVER (line 805) | func newDHCPDISCOVER(tb testing.TB, clientHWAddr net.HardwareAddr) (pkt ...
function newDHCPRELEASE (line 841) | func newDHCPRELEASE(
function newDHCPDECLINE (line 884) | func newDHCPDECLINE(
function newTestPacket (line 934) | func newTestPacket(
function requireEthernet (line 955) | func requireEthernet(
function assertValidOffer (line 972) | func assertValidOffer(
function assertValidACK (line 994) | func assertValidACK(
function assertValidNAK (line 1019) | func assertValidNAK(
function assertNoResponse (line 1049) | func assertNoResponse(tb testing.TB, outCh <-chan []byte, timeout time.D...
FILE: internal/dhcpsvc/handler6.go
method serveV6 (line 16) | func (srv *DHCPServer) serveV6(
method handleDHCPv6 (line 38) | func (srv *DHCPServer) handleDHCPv6(
FILE: internal/dhcpsvc/interface.go
type macKey (line 19) | type macKey
function macToKey (line 24) | func macToKey(mac net.HardwareAddr) (key macKey) {
type netInterface (line 40) | type netInterface struct
method reset (line 70) | func (iface *netInterface) reset() {
method addLease (line 76) | func (iface *netInterface) addLease(l *Lease) (err error) {
method updateLease (line 93) | func (iface *netInterface) updateLease(l *Lease) (prev *Lease, err err...
method removeLease (line 107) | func (iface *netInterface) removeLease(l *Lease) (err error) {
method blockLease (line 125) | func (iface *netInterface) blockLease(
method nextIP (line 144) | func (iface *netInterface) nextIP() (ip netip.Addr) {
method findExpiredLease (line 160) | func (iface *netInterface) findExpiredLease(now time.Time) (l *Lease) {
FILE: internal/dhcpsvc/iprange.go
type ipRange (line 17) | type ipRange struct
method contains (line 56) | func (r ipRange) contains(ip netip.Addr) (ok bool) {
method find (line 70) | func (r ipRange) find(p ipPredicate) (ip netip.Addr) {
method offset (line 82) | func (r ipRange) offset(ip netip.Addr) (offset uint64, ok bool) {
method String (line 96) | func (r ipRange) String() (s string) {
constant maxRangeLen (line 26) | maxRangeLen = math.MaxUint32
function newIPRange (line 30) | func newIPRange(start, end netip.Addr) (r ipRange, err error) {
type ipPredicate (line 64) | type ipPredicate
FILE: internal/dhcpsvc/iprange_internal_test.go
constant testRangeStartV4Str (line 16) | testRangeStartV4Str = "192.0.2.1"
constant testRangeEndV4Str (line 20) | testRangeEndV4Str = "192.0.2.5"
constant testRangeStartV6Str (line 24) | testRangeStartV6Str = "2001:db8::1"
constant testRangeEndV6Str (line 28) | testRangeEndV6Str = "2001:db8::3"
constant testRangeEndV6LargeStr (line 32) | testRangeEndV6LargeStr = "2001:db9::4"
function TestNewIPRange (line 53) | func TestNewIPRange(t *testing.T) {
function TestIPRange_Contains (line 103) | func TestIPRange_Contains(t *testing.T) {
function TestIPRange_Find (line 144) | func TestIPRange_Find(t *testing.T) {
function TestIPRange_Offset (line 195) | func TestIPRange_Offset(t *testing.T) {
FILE: internal/dhcpsvc/lease.go
type Lease (line 19) | type Lease struct
method Clone (line 38) | func (l *Lease) Clone() (clone *Lease) {
method IsBlocked (line 59) | func (l *Lease) IsBlocked() (blocked bool) {
method updateExpiry (line 65) | func (l *Lease) updateExpiry(clock timeutil.Clock, ttl time.Duration) {
constant EUI48AddrLen (line 53) | EUI48AddrLen = 6
FILE: internal/dhcpsvc/leaseindex.go
type leaseIndex (line 17) | type leaseIndex struct
method leaseByAddr (line 44) | func (idx *leaseIndex) leaseByAddr(addr netip.Addr) (l *Lease, ok bool) {
method leaseByName (line 51) | func (idx *leaseIndex) leaseByName(name string) (l *Lease, ok bool) {
method clear (line 60) | func (idx *leaseIndex) clear(ctx context.Context, logger *slog.Logger)...
method add (line 76) | func (idx *leaseIndex) add(
method remove (line 113) | func (idx *leaseIndex) remove(
method update (line 147) | func (idx *leaseIndex) update(
method rangeLeases (line 187) | func (idx *leaseIndex) rangeLeases(f func(l *Lease) (cont bool)) {
method len (line 196) | func (idx *leaseIndex) len() (l uint) {
function newLeaseIndex (line 35) | func newLeaseIndex(dbFilePath string) (idx *leaseIndex) {
FILE: internal/dhcpsvc/networkdevice.go
type NetworkDeviceConfig (line 15) | type NetworkDeviceConfig struct
method Validate (line 23) | func (conf *NetworkDeviceConfig) Validate() (err error) {
type NetworkDeviceManager (line 32) | type NetworkDeviceManager interface
type EmptyNetworkDeviceManager (line 41) | type EmptyNetworkDeviceManager struct
method Open (line 48) | func (EmptyNetworkDeviceManager) Open(
type NetworkDevice (line 60) | type NetworkDevice interface
type EmptyNetworkDevice (line 77) | type EmptyNetworkDevice struct
method ReadPacketData (line 85) | func (EmptyNetworkDevice) ReadPacketData() (data []byte, ci gopacket.C...
method Close (line 91) | func (EmptyNetworkDevice) Close() (err error) {
method Addresses (line 97) | func (EmptyNetworkDevice) Addresses() (ips []netip.Addr) {
method LinkType (line 103) | func (EmptyNetworkDevice) LinkType() (lt layers.LinkType) {
method WritePacketData (line 109) | func (EmptyNetworkDevice) WritePacketData(_ []byte) (err error) {
type frameData (line 115) | type frameData struct
FILE: internal/dhcpsvc/networkdevice_test.go
type testNetworkDeviceManager (line 21) | type testNetworkDeviceManager struct
method Open (line 33) | func (ndm *testNetworkDeviceManager) Open(
type testNetworkDevice (line 44) | type testNetworkDevice struct
method ReadPacketData (line 57) | func (nd *testNetworkDevice) ReadPacketData() (data []byte, ci gopacke...
method Close (line 62) | func (nd *testNetworkDevice) Close() (err error) {
method Addresses (line 68) | func (nd *testNetworkDevice) Addresses() (ips []netip.Addr) {
method WritePacketData (line 74) | func (nd *testNetworkDevice) WritePacketData(data []byte) (err error) {
method LinkType (line 80) | func (nd *testNetworkDevice) LinkType() (lt layers.LinkType) {
function newTestNetworkDeviceManager (line 88) | func newTestNetworkDeviceManager(
FILE: internal/dhcpsvc/options4.go
method implicitOptions (line 18) | func (c *IPv4Config) implicitOptions() (opts layers.DHCPOptions) {
method appendConfOptions (line 36) | func (c *IPv4Config) appendConfOptions(orig layers.DHCPOptions) (res lay...
function appendIPPerHostOptions (line 45) | func appendIPPerHostOptions(orig layers.DHCPOptions) (res layers.DHCPOpt...
function appendIPPerInterfaceOptions (line 105) | func appendIPPerInterfaceOptions(orig layers.DHCPOptions) (res layers.DH...
function appendLinkPerInterfaceOptions (line 163) | func appendLinkPerInterfaceOptions(orig layers.DHCPOptions) (res layers....
function appendTCPPerHostOptions (line 190) | func appendTCPPerHostOptions(orig layers.DHCPOptions) (res layers.DHCPOp...
method options (line 221) | func (c *IPv4Config) options(ctx context.Context, l *slog.Logger) (imp, ...
function compareV4OptionCodes (line 246) | func compareV4OptionCodes(a, b layers.DHCPOption) (res int) {
method updateOptions (line 254) | func (iface *dhcpInterfaceV4) updateOptions(req, resp *layers.DHCPv4) {
method appendLeaseTime (line 293) | func (iface *dhcpInterfaceV4) appendLeaseTime(resp *layers.DHCPv4, lease...
function msg4Type (line 310) | func msg4Type(msg *layers.DHCPv4) (typ layers.DHCPMsgType, ok bool) {
function requestedIPv4 (line 324) | func requestedIPv4(msg *layers.DHCPv4) (ip netip.Addr, ok bool) {
function serverID4 (line 335) | func serverID4(msg *layers.DHCPv4) (ip netip.Addr, ok bool) {
function hostname4 (line 346) | func hostname4(msg *layers.DHCPv4) (hostname string) {
function requestedOptions (line 360) | func requestedOptions(msg *layers.DHCPv4) (opts []layers.DHCPOpt) {
FILE: internal/dhcpsvc/options4_internal_test.go
constant testIPv4Str (line 16) | testIPv4Str = "192.0.2.1"
constant testAnotherIPv4Str (line 20) | testAnotherIPv4Str = "198.51.100.1"
constant broadcastIPv4Str (line 24) | broadcastIPv4Str = "255.255.255.255"
function TestIPv4Config_Options (line 30) | func TestIPv4Config_Options(t *testing.T) {
FILE: internal/dhcpsvc/options4_test.go
function newOptHostname (line 13) | func newOptHostname(tb testing.TB, hostname string) (opt layers.DHCPOpti...
function newOptLeaseTime (line 20) | func newOptLeaseTime(tb testing.TB, dur time.Duration) (opt layers.DHCPO...
function newOptMessageType (line 31) | func newOptMessageType(tb testing.TB, msgType layers.DHCPMsgType) (opt l...
function newOptServerID (line 38) | func newOptServerID(tb testing.TB, serverIP netip.Addr) (opt layers.DHCP...
FILE: internal/dhcpsvc/server.go
type DHCPServer (line 23) | type DHCPServer struct
method newInterfaces (line 99) | func (srv *DHCPServer) newInterfaces(
method Start (line 142) | func (srv *DHCPServer) Start(ctx context.Context) (err error) {
method Shutdown (line 173) | func (srv *DHCPServer) Shutdown(ctx context.Context) (err error) {
method Enabled (line 190) | func (srv *DHCPServer) Enabled() (ok bool) {
method Leases (line 195) | func (srv *DHCPServer) Leases() (leases []*Lease) {
method HostByIP (line 211) | func (srv *DHCPServer) HostByIP(ip netip.Addr) (host string) {
method MACByIP (line 223) | func (srv *DHCPServer) MACByIP(ip netip.Addr) (mac net.HardwareAddr) {
method IPByHost (line 235) | func (srv *DHCPServer) IPByHost(host string) (ip netip.Addr) {
method Reset (line 247) | func (srv *DHCPServer) Reset(ctx context.Context) (err error) {
method AddLease (line 271) | func (srv *DHCPServer) AddLease(ctx context.Context, l *Lease) (err er...
method UpdateStaticLease (line 304) | func (srv *DHCPServer) UpdateStaticLease(ctx context.Context, l *Lease...
method RemoveLease (line 335) | func (srv *DHCPServer) RemoveLease(ctx context.Context, l *Lease) (err...
method removeLeaseByAddr (line 369) | func (srv *DHCPServer) removeLeaseByAddr(ctx context.Context, addr net...
function New (line 64) | func New(ctx context.Context, conf *Config) (srv *DHCPServer, err error) {
function ifaceForAddr (line 407) | func ifaceForAddr(
FILE: internal/dhcpsvc/server_test.go
function TestDHCPServer_AddLease (line 18) | func TestDHCPServer_AddLease(t *testing.T) {
function TestDHCPServer_index (line 128) | func TestDHCPServer_index(t *testing.T) {
function TestDHCPServer_UpdateStaticLease (line 181) | func TestDHCPServer_UpdateStaticLease(t *testing.T) {
function TestDHCPServer_RemoveLease (line 285) | func TestDHCPServer_RemoveLease(t *testing.T) {
function TestDHCPServer_Reset (line 367) | func TestDHCPServer_Reset(t *testing.T) {
function TestServer_Leases (line 385) | func TestServer_Leases(t *testing.T) {
FILE: internal/dhcpsvc/v4.go
type IPv4Config (line 23) | type IPv4Config struct
method Validate (line 65) | func (c *IPv4Config) Validate() (err error) {
method validateSubnet (line 86) | func (c *IPv4Config) validateSubnet(orig []error) (errs []error) {
type dhcpInterfaceV4 (line 130) | type dhcpInterfaceV4 struct
method updateLease (line 204) | func (iface *dhcpInterfaceV4) updateLease(
method respondOffer (line 213) | func (iface *dhcpInterfaceV4) respondOffer(
method respondACK (line 232) | func (iface *dhcpInterfaceV4) respondACK(
method respondNAK (line 254) | func (iface *dhcpInterfaceV4) respondNAK(
method buildResponse (line 282) | func (iface *dhcpInterfaceV4) buildResponse(
method allocateLease (line 341) | func (iface *dhcpInterfaceV4) allocateLease(
method reserveLease (line 378) | func (iface *dhcpInterfaceV4) reserveLease(
method updateAndRespond (line 425) | func (iface *dhcpInterfaceV4) updateAndRespond(
method newDHCPInterfaceV4 (line 164) | func (srv *DHCPServer) newDHCPInterfaceV4(
type dhcpInterfacesV4 (line 321) | type dhcpInterfacesV4
method find (line 325) | func (ifaces dhcpInterfacesV4) find(ip netip.Addr) (iface4 *netInterfa...
constant IPv4DefaultTTL (line 448) | IPv4DefaultTTL = 64
constant IPProtoVersion (line 452) | IPProtoVersion = 4
constant ServerPortV4 (line 460) | ServerPortV4 layers.UDPPort = 67
constant ClientPortV4 (line 463) | ClientPortV4 layers.UDPPort = 68
function respond4 (line 467) | func respond4(fd *frameData, resp *layers.DHCPv4) (err error) {
FILE: internal/dhcpsvc/v6.go
type IPv6Config (line 18) | type IPv6Config struct
method Validate (line 48) | func (c *IPv6Config) Validate() (err error) {
method options (line 159) | func (c *IPv6Config) options(ctx context.Context, l *slog.Logger) (imp...
type dhcpInterfaceV6 (line 71) | type dhcpInterfaceV6 struct
method newDHCPInterfaceV6 (line 99) | func (srv *DHCPServer) newDHCPInterfaceV6(
type dhcpInterfacesV6 (line 130) | type dhcpInterfacesV6
method find (line 134) | func (ifaces dhcpInterfacesV6) find(ip netip.Addr) (iface6 *netInterfa...
function compareV6OptionCodes (line 180) | func compareV6OptionCodes(a, b layers.DHCPv6Option) (res int) {
FILE: internal/dnsforward/access.go
type accessManager (line 22) | type accessManager struct
method allowlistMode (line 109) | func (a *accessManager) allowlistMode() (ok bool) {
method isBlockedClientID (line 114) | func (a *accessManager) isBlockedClientID(id string) (ok bool) {
method isBlockedHost (line 130) | func (a *accessManager) isBlockedHost(host string, qt rules.RRType) (o...
method isBlockedIP (line 141) | func (a *accessManager) isBlockedIP(ip netip.Addr) (blocked bool, rule...
function processAccessClients (line 39) | func processAccessClients(
function newAccessCtx (line 66) | func newAccessCtx(allowed, blocked, blockedHosts []string) (a *accessMan...
type accessListJSON (line 169) | type accessListJSON struct
method accessListJSON (line 175) | func (s *Server) accessListJSON() (j accessListJSON) {
method handleAccessList (line 187) | func (s *Server) handleAccessList(w http.ResponseWriter, r *http.Request) {
function validateAccessSet (line 194) | func validateAccessSet(list *accessListJSON) (err error) {
function validateStrUniq (line 222) | func validateStrUniq(clients []string) (m *container.MapSet[string], err...
method handleAccessSet (line 243) | func (s *Server) handleAccessSet(w http.ResponseWriter, r *http.Request) {
FILE: internal/dnsforward/access_internal_test.go
function TestIsBlockedClientID (line 13) | func TestIsBlockedClientID(t *testing.T) {
function TestIsBlockedHost (line 28) | func TestIsBlockedHost(t *testing.T) {
function TestIsBlockedIP (line 112) | func TestIsBlockedIP(t *testing.T) {
FILE: internal/dnsforward/clientid.go
function clientIDFromClientServerName (line 21) | func clientIDFromClientServerName(
function clientIDFromDNSContextHTTPS (line 54) | func clientIDFromDNSContextHTTPS(pctx *proxy.DNSContext) (clientID strin...
type tlsConn (line 92) | type tlsConn interface
function clientServerName (line 99) | func clientServerName(
function clientServerNameFromHTTP (line 138) | func clientServerNameFromHTTP(r *http.Request) (srvName string, fromHost...
FILE: internal/dnsforward/clientid_internal_test.go
type testTLSConn (line 16) | type testTLSConn struct
method ConnectionState (line 25) | func (c testTLSConn) ConnectionState() (cs tls.ConnectionState) {
function TestServer_clientIDFromDNSContext (line 31) | func TestServer_clientIDFromDNSContext(t *testing.T) {
function newHTTPReq (line 241) | func newHTTPReq(cliSrvName string, inclTLS bool) (r *http.Request) {
function TestClientIDFromDNSContextHTTPS (line 262) | func TestClientIDFromDNSContextHTTPS(t *testing.T) {
FILE: internal/dnsforward/clientscontainer.go
type ClientsContainer (line 11) | type ClientsContainer interface
type EmptyClientsContainer (line 26) | type EmptyClientsContainer struct
method CustomUpstreamConfig (line 33) | func (EmptyClientsContainer) CustomUpstreamConfig(
method UpdateCommonUpstreamConfig (line 42) | func (EmptyClientsContainer) UpdateCommonUpstreamConfig(conf *client.C...
method ClearUpstreamCache (line 46) | func (EmptyClientsContainer) ClearUpstreamCache() {}
FILE: internal/dnsforward/config.go
type Config (line 37) | type Config struct
type EDNSClientSubnet (line 174) | type EDNSClientSubnet struct
type TLSConfig (line 188) | type TLSConfig struct
type DNSCryptConfig (line 220) | type DNSCryptConfig struct
type ServerConfig (line 240) | type ServerConfig struct
method loadUpstreams (line 525) | func (conf *ServerConfig) loadUpstreams(
method collectDNSAddrs (line 566) | func (conf *ServerConfig) collectDNSAddrs() (
method ourAddrsSet (line 650) | func (conf *ServerConfig) ourAddrsSet(ctx context.Context, l *slog.Log...
type UpstreamMode (line 316) | type UpstreamMode
constant UpstreamModeLoadBalance (line 319) | UpstreamModeLoadBalance UpstreamMode = "load_balance"
constant UpstreamModeParallel (line 320) | UpstreamModeParallel UpstreamMode = "parallel"
constant UpstreamModeFastestAddr (line 321) | UpstreamModeFastestAddr UpstreamMode = "fastest_addr"
method newProxyConfig (line 327) | func (s *Server) newProxyConfig(ctx context.Context) (conf *proxy.Config...
function newRatelimitMw (line 409) | func newRatelimitMw(
function prepareCacheConfig (line 432) | func prepareCacheConfig(
function parseBogusNXDOMAIN (line 459) | func parseBogusNXDOMAIN(confBogusNXDOMAIN []string) (subnets []netip.Pre...
method initDefaultSettings (line 475) | func (s *Server) initDefaultSettings() {
method prepareIpsetListSettings (line 503) | func (s *Server) prepareIpsetListSettings(ctx context.Context) (ipsets [...
function collectListenAddr (line 549) | func collectListenAddr(
constant defaultPlainDNSPort (line 585) | defaultPlainDNSPort uint16 = 53
type addrPortSet (line 588) | type addrPortSet interface
type emptyAddrPortSet (line 597) | type emptyAddrPortSet struct
method Has (line 600) | func (emptyAddrPortSet) Has(_ netip.AddrPort) (ok bool) { return false }
type combinedAddrPortSet (line 604) | type combinedAddrPortSet struct
method Has (line 614) | func (m *combinedAddrPortSet) Has(addrPort netip.AddrPort) (ok bool) {
function filterOutAddrs (line 620) | func filterOutAddrs(upsConf *proxy.UpstreamConfig, set addrPortSet) (err...
method prepareDNSCrypt (line 684) | func (s *Server) prepareDNSCrypt(proxyConf *proxy.Config) {
method prepareTLS (line 697) | func (s *Server) prepareTLS(ctx context.Context, proxyConf *proxy.Config...
function isWildcard (line 748) | func isWildcard(host string) (ok bool) {
function matchesDomainWildcard (line 754) | func matchesDomainWildcard(host, pat string) (ok bool) {
function anyNameMatches (line 760) | func anyNameMatches(dnsNames []string, sni string) (ok bool) {
method onGetCertificate (line 781) | func (s *Server) onGetCertificate(ch *tls.ClientHelloInfo) (*tls.Certifi...
method preparePlain (line 798) | func (s *Server) preparePlain(ctx context.Context, proxyConf *proxy.Conf...
method UpdatedProtectionStatus (line 823) | func (s *Server) UpdatedProtectionStatus(
method enableProtectionAfterPause (line 853) | func (s *Server) enableProtectionAfterPause(ctx context.Context) {
function validateCacheTTL (line 872) | func validateCacheTTL(minTTL, maxTTL uint32) (err error) {
FILE: internal/dnsforward/config_internal_test.go
function TestAnyNameMatches (line 10) | func TestAnyNameMatches(t *testing.T) {
FILE: internal/dnsforward/configvalidator.go
type upstreamConfigValidator (line 19) | type upstreamConfigValidator struct
method check (line 169) | func (cv *upstreamConfigValidator) check(ctx context.Context, l *slog....
method close (line 225) | func (cv *upstreamConfigValidator) close() {
method status (line 255) | func (cv *upstreamConfigValidator) status(
type upstreamResult (line 41) | type upstreamResult struct
type parseResult (line 54) | type parseResult struct
function newUpstreamConfigValidator (line 62) | func newUpstreamConfigValidator(
function collectErrResults (line 93) | func collectErrResults(ctx context.Context, l *slog.Logger, lines []stri...
function insertConfResults (line 136) | func insertConfResults(conf *proxy.UpstreamConfig, results map[string]*u...
function insertListResults (line 150) | func insertListResults(ups []upstream.Upstream, results map[string]*upst...
function checkSrv (line 214) | func checkSrv(ctx context.Context, l *slog.Logger, res *upstreamResult, ...
constant generalTextLabel (line 246) | generalTextLabel = "upstream_dns"
constant fallbackTextLabel (line 247) | fallbackTextLabel = "fallback_dns_title"
constant privateTextLabel (line 248) | privateTextLabel = "local_ptr_title"
function upstreamResultToStatus (line 299) | func upstreamResultToStatus(
function parseResultToStatus (line 340) | func parseResultToStatus(
type domainSpecificTestError (line 374) | type domainSpecificTestError struct
method Error (line 383) | func (err domainSpecificTestError) Error() (msg string) {
method Unwrap (line 391) | func (err domainSpecificTestError) Unwrap() (wrapped error) {
type healthchecker (line 396) | type healthchecker struct
method check (line 409) | func (h *healthchecker) check(u upstream.Upstream) (err error) {
FILE: internal/dnsforward/context.go
type ctxKey (line 9) | type ctxKey
constant ctxKeyClientID (line 13) | ctxKeyClientID ctxKey = iota
function contextWithClientID (line 17) | func contextWithClientID(parent context.Context, id string) (ctx context...
function clientIDFromContext (line 22) | func clientIDFromContext(ctx context.Context) (id string, ok bool) {
FILE: internal/dnsforward/dialcontext.go
method DialContext (line 18) | func (s *Server) DialContext(ctx context.Context, network, addr string) ...
FILE: internal/dnsforward/dns64.go
method setupDNS64 (line 17) | func (s *Server) setupDNS64() {
method mapDNS64 (line 38) | func (s *Server) mapDNS64(ip netip.Addr) (mapped net.IP) {
FILE: internal/dnsforward/dns64_internal_test.go
constant maxDNS64SynTTL (line 25) | maxDNS64SynTTL uint32 = 600
function newRR (line 30) | func newRR(tb testing.TB, name string, qtype uint16, ttl uint32, val any...
function TestServer_ServeDNS_dns64 (line 66) | func TestServer_ServeDNS_dns64(t *testing.T) {
function TestServer_dns64WithDisabledRDNS (line 323) | func TestServer_dns64WithDisabledRDNS(t *testing.T) {
FILE: internal/dnsforward/dnsforward.go
constant DefaultTimeout (line 38) | DefaultTimeout = 10 * time.Second
constant defaultLocalTimeout (line 43) | defaultLocalTimeout = 1 * time.Second
type DHCP (line 64) | type DHCP interface
type SystemResolvers (line 81) | type SystemResolvers interface
type Server (line 99) | type Server struct
method Close (line 279) | func (s *Server) Close(ctx context.Context) {
method WriteDiskConfig (line 294) | func (s *Server) WriteDiskConfig(c *Config) {
method LocalPTRResolvers (line 311) | func (s *Server) LocalPTRResolvers() (localPTRResolvers []string) {
method AddrProcConfig (line 320) | func (s *Server) AddrProcConfig() (c *client.DefaultAddrProcConfig) {
method UpstreamTimeout (line 332) | func (s *Server) UpstreamTimeout() (t time.Duration) {
method Resolve (line 342) | func (s *Server) Resolve(ctx context.Context, net, host string) (addr ...
method Exchange (line 363) | func (s *Server) Exchange(
method Start (line 463) | func (s *Server) Start(ctx context.Context) error {
method startLocked (line 472) | func (s *Server) startLocked(ctx context.Context) error {
method Prepare (line 483) | func (s *Server) Prepare(ctx context.Context, conf *ServerConfig) (err...
method prepareUpstreamSettings (line 539) | func (s *Server) prepareUpstreamSettings(ctx context.Context, boot ups...
method prepareLocalResolvers (line 602) | func (s *Server) prepareLocalResolvers(ctx context.Context) (uc *proxy...
method prepareInternalDNS (line 634) | func (s *Server) prepareInternalDNS(ctx context.Context) (err error) {
method setupFallbackDNS (line 679) | func (s *Server) setupFallbackDNS() (uc *proxy.UpstreamConfig, err err...
method setupAddrProc (line 703) | func (s *Server) setupAddrProc() {
method prepareInternalProxy (line 753) | func (s *Server) prepareInternalProxy() (err error) {
method Stop (line 780) | func (s *Server) Stop(ctx context.Context) error {
method stopLocked (line 791) | func (s *Server) stopLocked(ctx context.Context) {
method IsRunning (line 823) | func (s *Server) IsRunning() bool {
method proxy (line 838) | func (s *Server) proxy() (p *proxy.Proxy) {
method Reconfigure (line 848) | func (s *Server) Reconfigure(ctx context.Context, conf *ServerConfig) ...
method ServeHTTP (line 888) | func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
method IsBlockedClient (line 896) | func (s *Server) IsBlockedClient(ip netip.Addr, clientID string) (bloc...
constant defaultLocalDomainSuffix (line 198) | defaultLocalDomainSuffix = "lan"
type DNSCreateParams (line 201) | type DNSCreateParams struct
function NewServer (line 221) | func NewServer(p DNSCreateParams) (s *Server, err error) {
constant ErrRDNSNoData (line 352) | ErrRDNSNoData errors.Error = "no ptr data in response"
constant ErrRDNSFailed (line 356) | ErrRDNSFailed errors.Error = "failed to resolve ptr"
function hostFromPTR (line 416) | func hostFromPTR(
type PrivateRDNSError (line 586) | type PrivateRDNSError struct
method Error (line 591) | func (e *PrivateRDNSError) Error() (s string) {
method Unwrap (line 595) | func (e *PrivateRDNSError) Unwrap() (err error) {
function validateBlockingMode (line 727) | func validateBlockingMode(
function logCloserErr (line 811) | func logCloserErr(ctx context.Context, c io.Closer, msg string, l *slog....
constant srvClosedErr (line 832) | srvClosedErr errors.Error = "server is closed"
FILE: internal/dnsforward/dnsforward_internal_test.go
function TestMain (line 48) | func TestMain(m *testing.M) {
constant testTimeout (line 55) | testTimeout = 1 * time.Second
constant testQuestionTarget (line 60) | testQuestionTarget = "target.example"
constant tlsServerName (line 63) | tlsServerName = "testdns.adguard.com"
constant testMessagesCount (line 64) | testMessagesCount = 10
type clientsContainer (line 76) | type clientsContainer struct
method CustomUpstreamConfig (line 89) | func (c *clientsContainer) CustomUpstreamConfig(
method UpdateCommonUpstreamConfig (line 98) | func (c *clientsContainer) UpdateCommonUpstreamConfig(conf *client.Com...
method ClearUpstreamCache (line 104) | func (c *clientsContainer) ClearUpstreamCache() {
function startDeferStop (line 111) | func startDeferStop(tb testing.TB, s *Server) {
function applyEmptyClientFiltering (line 123) | func applyEmptyClientFiltering(_ string, _ netip.Addr, _ *filtering.Sett...
function emptyFilteringBlockedServices (line 127) | func emptyFilteringBlockedServices() (bsvc *filtering.BlockedServices) {
function createTestServer (line 136) | func createTestServer(
function createServerTLSConfig (line 185) | func createServerTLSConfig(tb testing.TB) (*tls.Config, []byte, []byte) {
function createTestTLS (line 237) | func createTestTLS(tb testing.TB, tlsConf *TLSConfig) (s *Server, certPe...
constant googleDomainName (line 268) | googleDomainName = "google-public-dns-a.google.com."
function createGoogleATestMessage (line 270) | func createGoogleATestMessage() *dns.Msg {
function newGoogleUpstream (line 274) | func newGoogleUpstream() (u upstream.Upstream) {
function createTestMessage (line 287) | func createTestMessage(host string) *dns.Msg {
function createTestMessageWithType (line 301) | func createTestMessageWithType(host string, qtype uint16) *dns.Msg {
function newResp (line 310) | func newResp(rcode int, req *dns.Msg, ans []dns.RR) (resp *dns.Msg) {
function assertGoogleAResponse (line 319) | func assertGoogleAResponse(tb testing.TB, reply *dns.Msg) {
function assertResponse (line 325) | func assertResponse(tb testing.TB, reply *dns.Msg, ip netip.Addr) {
function sendTestMessagesAsync (line 343) | func sendTestMessagesAsync(tb testing.TB, conn *dns.Conn) {
function sendTestMessages (line 369) | func sendTestMessages(tb testing.TB, conn *dns.Conn) {
function TestServer (line 383) | func TestServer(t *testing.T) {
function TestServer_timeout (line 427) | func TestServer_timeout(t *testing.T) {
function TestServer_Prepare_fallbacks (line 472) | func TestServer_Prepare_fallbacks(t *testing.T) {
function TestServerWithProtectionDisabled (line 499) | func TestServerWithProtectionDisabled(t *testing.T) {
function TestDoTServer (line 526) | func TestDoTServer(t *testing.T) {
function TestDoQServer (line 550) | func TestDoQServer(t *testing.T) {
function TestServerRace (line 574) | func TestServerRace(t *testing.T) {
function TestSafeSearch (line 607) | func TestSafeSearch(t *testing.T) {
function TestInvalidRequest (line 729) | func TestInvalidRequest(t *testing.T) {
function TestBlockedRequest (line 763) | func TestBlockedRequest(t *testing.T) {
function TestServerCustomClientUpstream (line 797) | func TestServerCustomClientUpstream(t *testing.T) {
function TestBlockCNAMEProtectionEnabled (line 880) | func TestBlockCNAMEProtectionEnabled(t *testing.T) {
function TestBlockCNAME (line 918) | func TestBlockCNAME(t *testing.T) {
function TestClientRulesForCNAMEMatching (line 993) | func TestClientRulesForCNAMEMatching(t *testing.T) {
function TestNullBlockedRequest (line 1041) | func TestNullBlockedRequest(t *testing.T) {
function TestBlockedCustomIP (line 1095) | func TestBlockedCustomIP(t *testing.T) {
function TestBlockedByHosts (line 1181) | func TestBlockedByHosts(t *testing.T) {
function TestBlockedBySafeBrowsing (line 1234) | func TestBlockedBySafeBrowsing(t *testing.T) {
function TestRewrite (line 1291) | func TestRewrite(t *testing.T) {
function publicKey (line 1411) | func publicKey(priv any) any {
type testDHCP (line 1425) | type testDHCP struct
method HostByIP (line 1435) | func (d *testDHCP) HostByIP(ip netip.Addr) (host string) { return d.On...
method IPByHost (line 1438) | func (d *testDHCP) IPByHost(host string) (ip netip.Addr) { return d.On...
method Enabled (line 1441) | func (d *testDHCP) Enabled() (ok bool) { return d.OnEnabled() }
function TestPTRResponseFromDHCPLeases (line 1443) | func TestPTRResponseFromDHCPLeases(t *testing.T) {
function TestPTRResponseFromHosts (line 1501) | func TestPTRResponseFromHosts(t *testing.T) {
function TestNewServer (line 1601) | func TestNewServer(t *testing.T) {
function doubleTTL (line 1649) | func doubleTTL(msg *dns.Msg) (resp *dns.Msg) {
function TestServer_Exchange (line 1671) | func TestServer_Exchange(t *testing.T) {
FILE: internal/dnsforward/dnsrewrite.go
method filterDNSRewriteResponse (line 17) | func (s *Server) filterDNSRewriteResponse(
method ansFromDNSRewriteIP (line 43) | func (s *Server) ansFromDNSRewriteIP(
method ansFromDNSRewriteText (line 62) | func (s *Server) ansFromDNSRewriteText(
method ansFromDNSRewriteMX (line 81) | func (s *Server) ansFromDNSRewriteMX(
method ansFromDNSRewriteSVCB (line 100) | func (s *Server) ansFromDNSRewriteSVCB(
method ansFromDNSRewriteSRV (line 124) | func (s *Server) ansFromDNSRewriteSRV(
method filterDNSRewrite (line 143) | func (s *Server) filterDNSRewrite(
FILE: internal/dnsforward/dnsrewrite_internal_test.go
function TestServer_FilterDNSRewrite (line 17) | func TestServer_FilterDNSRewrite(t *testing.T) {
FILE: internal/dnsforward/filter.go
method clientRequestFilteringSettings (line 17) | func (s *Server) clientRequestFilteringSettings(dctx *dnsContext) (setts...
method filterDNSRequest (line 27) | func (s *Server) filterDNSRequest(
function isRewrittenCNAME (line 65) | func isRewrittenCNAME(res *filtering.Result) (ok bool) {
method checkHostRules (line 76) | func (s *Server) checkHostRules(
method filterDNSResponse (line 96) | func (s *Server) filterDNSResponse(ctx context.Context, dctx *dnsContext...
function removeIPv6Hints (line 159) | func removeIPv6Hints(rr *dns.HTTPS) {
method filterHTTPSRecords (line 170) | func (s *Server) filterHTTPSRecords(rr *dns.HTTPS, setts *filtering.Sett...
method filterSVCBHint (line 204) | func (s *Server) filterSVCBHint(
FILE: internal/dnsforward/filter_internal_test.go
function TestServer_filterDNSResponse (line 18) | func TestServer_filterDNSResponse(t *testing.T) {
function newSVCBHintsAnswer (line 182) | func newSVCBHintsAnswer(target string, hints []dns.SVCBKeyValue) (rrs []...
FILE: internal/dnsforward/http.go
type jsonDNSConfig (line 32) | type jsonDNSConfig struct
method checkBlockingMode (line 256) | func (req *jsonDNSConfig) checkBlockingMode() (err error) {
method checkUpstreamMode (line 265) | func (req *jsonDNSConfig) checkUpstreamMode() (err error) {
method validate (line 286) | func (req *jsonDNSConfig) validate(
method checkBootstrap (line 336) | func (req *jsonDNSConfig) checkBootstrap() (err error) {
method containsPrivateRDNS (line 365) | func (req *jsonDNSConfig) containsPrivateRDNS() (ok bool) {
method checkPrivateRDNS (line 372) | func (req *jsonDNSConfig) checkPrivateRDNS(
method validateUpstreamDNSServers (line 405) | func (req *jsonDNSConfig) validateUpstreamDNSServers(
method validateCacheSettings (line 449) | func (req *jsonDNSConfig) validateCacheSettings(curCacheSize uint32) (...
method validateCacheSize (line 474) | func (req *jsonDNSConfig) validateCacheSize(curCacheSize uint32) (err ...
method checkRatelimitSubnetMaskLen (line 496) | func (req *jsonDNSConfig) checkRatelimitSubnetMaskLen() (err error) {
method checkUpstreamTimeout (line 512) | func (req *jsonDNSConfig) checkUpstreamTimeout() (err error) {
type jsonUpstreamMode (line 131) | type jsonUpstreamMode
constant jsonUpstreamModeEmpty (line 138) | jsonUpstreamModeEmpty jsonUpstreamMode = ""
constant jsonUpstreamModeLoadBalance (line 140) | jsonUpstreamModeLoadBalance jsonUpstreamMode = "load_balance"
constant jsonUpstreamModeParallel (line 141) | jsonUpstreamModeParallel jsonUpstreamMode = "parallel"
constant jsonUpstreamModeFastestAddr (line 142) | jsonUpstreamModeFastestAddr jsonUpstreamMode = "fastest_addr"
method getDNSConfig (line 145) | func (s *Server) getDNSConfig(ctx context.Context) (c *jsonDNSConfig) {
method defaultLocalPTRUpstreams (line 231) | func (s *Server) defaultLocalPTRUpstreams(ctx context.Context) (ups []st...
method handleGetConfig (line 248) | func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) {
function checkInclusion (line 522) | func checkInclusion(ptr *uint, minN, maxN uint) (err error) {
method handleSetConfig (line 539) | func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
method setConfig (line 588) | func (s *Server) setConfig(dc *jsonDNSConfig) (shouldRestart bool) {
function mustParseUpstreamMode (line 620) | func mustParseUpstreamMode(mode jsonUpstreamMode) (um UpstreamMode) {
function setIfNotNil (line 636) | func setIfNotNil[T any](currentPtr, newPtr *T) (hasSet bool) {
method setConfigRestartable (line 652) | func (s *Server) setConfigRestartable(dc *jsonDNSConfig) (shouldRestart ...
type upstreamJSON (line 695) | type upstreamJSON struct
function closeBoots (line 704) | func closeBoots(ctx context.Context, l *slog.Logger, boots []*upstream.U...
method handleTestUpstreamDNS (line 712) | func (s *Server) handleTestUpstreamDNS(w http.ResponseWriter, r *http.Re...
method handleCacheClear (line 765) | func (s *Server) handleCacheClear(w http.ResponseWriter, _ *http.Request) {
type protectionJSON (line 773) | type protectionJSON struct
method handleSetProtection (line 779) | func (s *Server) handleSetProtection(w http.ResponseWriter, r *http.Requ...
method handleDoH (line 832) | func (s *Server) handleDoH(w http.ResponseWriter, r *http.Request) {
method registerHandlers (line 858) | func (s *Server) registerHandlers() {
FILE: internal/dnsforward/http_internal_test.go
type emptySysResolvers (line 40) | type emptySysResolvers struct
method Addrs (line 43) | func (emptySysResolvers) Addrs() (addrs []netip.AddrPort) {
function loadTestData (line 49) | func loadTestData(tb testing.TB, casesFileName string, cases any) {
constant jsonExt (line 62) | jsonExt = ".json"
constant testBlockedRespTTL (line 65) | testBlockedRespTTL = 10
function TestDNSForwardHTTP_handleGetConfig (line 68) | func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
function TestDNSForwardHTTP_handleSetConfig (line 154) | func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
function newLocalUpstreamListener (line 324) | func newLocalUpstreamListener(tb testing.TB, port uint16, h dns.Handler)...
function TestServer_HandleTestUpstreamDNS (line 345) | func TestServer_HandleTestUpstreamDNS(t *testing.T) {
FILE: internal/dnsforward/ipset.go
type ipsetHandler (line 18) | type ipsetHandler struct
method close (line 61) | func (h *ipsetHandler) close() (err error) {
method skipIpsetProcessing (line 81) | func (h *ipsetHandler) skipIpsetProcessing(dctx *dnsContext) (ok bool) {
method process (line 124) | func (h *ipsetHandler) process(ctx context.Context, dctx *dnsContext) ...
function newIpsetHandler (line 25) | func newIpsetHandler(
function dctxIsFilled (line 70) | func dctxIsFilled(dctx *dnsContext) (ok bool) {
function ipFromRR (line 92) | func ipFromRR(rr dns.RR) (ip net.IP) {
function ipsFromAnswer (line 104) | func ipsFromAnswer(ans []dns.RR) (ip4s, ip6s []net.IP) {
FILE: internal/dnsforward/ipset_internal_test.go
type fakeIpsetMgr (line 15) | type fakeIpsetMgr struct
method Add (line 21) | func (m *fakeIpsetMgr) Add(_ context.Context, host string, ip4s, ip6s ...
method Close (line 29) | func (*fakeIpsetMgr) Close() (err error) {
function TestIpsetCtx_process (line 33) | func TestIpsetCtx_process(t *testing.T) {
function TestIpsetCtx_SkipIpsetProcessing (line 124) | func TestIpsetCtx_SkipIpsetProcessing(t *testing.T) {
FILE: internal/dnsforward/middleware.go
method Wrap (line 24) | func (s *Server) Wrap(h proxy.Handler) (wrapped proxy.Handler) {
method serveBlockedResponse (line 57) | func (s *Server) serveBlockedResponse(pctx *proxy.DNSContext) (err error) {
method isBlockedHost (line 70) | func (s *Server) isBlockedHost(ctx context.Context, question []dns.Quest...
method clientIDFromDNSContext (line 96) | func (s *Server) clientIDFromDNSContext(
type logMiddleware (line 138) | type logMiddleware struct
method Wrap (line 163) | func (m *logMiddleware) Wrap(h proxy.Handler) (wrapped proxy.Handler) {
method attrsSlicePtr (line 185) | func (m *logMiddleware) attrsSlicePtr(r *dns.Msg) (attrsPtr *[]slog.At...
method logFinished (line 208) | func (m *logMiddleware) logFinished(ctx context.Context, l *slog.Logge...
constant logMwAttrNum (line 146) | logMwAttrNum = 3
function newLogMiddleware (line 149) | func newLogMiddleware(l *slog.Logger, lvl slog.Level) (mw *logMiddleware) {
FILE: internal/dnsforward/middleware_internal_test.go
constant blockedHost (line 20) | blockedHost = "blockedhost.org"
constant testFQDN (line 21) | testFQDN = "example.org."
constant dnsClientTimeout (line 23) | dnsClientTimeout = 200 * time.Millisecond
function TestServer_middlewareTLS (line 26) | func TestServer_middlewareTLS(t *testing.T) {
function TestServer_middlewareUDP (line 144) | func TestServer_middlewareUDP(t *testing.T) {
function newTestDNSAnswer (line 260) | func newTestDNSAnswer(fqdn string, ip net.IP) (ans []dns.RR) {
function newTestUpstream (line 274) | func newTestUpstream(tb testing.TB, answer []dns.RR) (addr string) {
function newTestTCPClient (line 288) | func newTestTCPClient(clientSrvName string) (c *dns.Client) {
function assertSuccessResponse (line 303) | func assertSuccessResponse(tb testing.TB, reply *dns.Msg, expectedAns []...
function assertRejectedResponse (line 314) | func assertRejectedResponse(tb testing.TB, reply *dns.Msg, wantRCode int) {
function assertTimeoutError (line 324) | func assertTimeoutError(tb testing.TB, err error, reply *dns.Msg) {
FILE: internal/dnsforward/msg.go
method reply (line 19) | func (*Server) reply(req *dns.Msg, code int) (resp *dns.Msg) {
method replyCompressed (line 27) | func (s *Server) replyCompressed(req *dns.Msg) (resp *dns.Msg) {
function ipsFromRules (line 36) | func ipsFromRules(resRules []*filtering.ResultRule) (ips []netip.Addr) {
method genDNSFilterMessage (line 50) | func (s *Server) genDNSFilterMessage(
method getCNAMEWithIPs (line 83) | func (s *Server) getCNAMEWithIPs(
method genForBlockingMode (line 122) | func (s *Server) genForBlockingMode(
method makeResponseCustomIP (line 151) | func (s *Server) makeResponseCustomIP(
method genARecord (line 175) | func (s *Server) genARecord(request *dns.Msg, ip netip.Addr) *dns.Msg {
method genAAAARecord (line 181) | func (s *Server) genAAAARecord(request *dns.Msg, ip netip.Addr) *dns.Msg {
method hdr (line 187) | func (s *Server) hdr(req *dns.Msg, rrType rules.RRType) (h dns.RR_Header) {
method genAnswerA (line 196) | func (s *Server) genAnswerA(req *dns.Msg, ip netip.Addr) (ans *dns.A) {
method genAnswerAAAA (line 203) | func (s *Server) genAnswerAAAA(req *dns.Msg, ip netip.Addr) (ans *dns.AA...
method genAnswerCNAME (line 210) | func (s *Server) genAnswerCNAME(req *dns.Msg, cname string) (ans *dns.CN...
method genAnswerMX (line 217) | func (s *Server) genAnswerMX(req *dns.Msg, mx *rules.DNSMX) (ans *dns.MX) {
method genAnswerPTR (line 225) | func (s *Server) genAnswerPTR(req *dns.Msg, ptr string) (ans *dns.PTR) {
method genAnswerSRV (line 232) | func (s *Server) genAnswerSRV(req *dns.Msg, srv *rules.DNSSRV) (ans *dns...
method genAnswerTXT (line 242) | func (s *Server) genAnswerTXT(req *dns.Msg, strs []string) (ans *dns.TXT) {
method genResponseWithIPs (line 253) | func (s *Server) genResponseWithIPs(
method genAnswersWithIPv4s (line 281) | func (s *Server) genAnswersWithIPv4s(
method makeResponseNullIP (line 301) | func (s *Server) makeResponseNullIP(ctx context.Context, req *dns.Msg) (...
method genBlockedHost (line 318) | func (s *Server) genBlockedHost(
method makeResponseREFUSED (line 377) | func (s *Server) makeResponseREFUSED(req *dns.Msg) *dns.Msg {
method NewMsgNXDOMAIN (line 386) | func (s *Server) NewMsgNXDOMAIN(req *dns.Msg) (resp *dns.Msg) {
method NewMsgSERVFAIL (line 395) | func (s *Server) NewMsgSERVFAIL(req *dns.Msg) (resp *dns.Msg) {
method NewMsgNOTIMPLEMENTED (line 401) | func (s *Server) NewMsgNOTIMPLEMENTED(req *dns.Msg) (resp *dns.Msg) {
method NewMsgNODATA (line 419) | func (s *Server) NewMsgNODATA(req *dns.Msg) (resp *dns.Msg) {
method genSOA (line 426) | func (s *Server) genSOA(req *dns.Msg) []dns.RR {
FILE: internal/dnsforward/process.go
type dnsContext (line 20) | type dnsContext struct
type resultCode (line 62) | type resultCode
constant resultCodeSuccess (line 67) | resultCodeSuccess resultCode = iota
constant resultCodeFinish (line 71) | resultCodeFinish
constant resultCodeError (line 75) | resultCodeError
constant ddrHostFQDN (line 80) | ddrHostFQDN = "_dns.resolver.arpa."
constant mozillaFQDN (line 86) | mozillaFQDN = "use-application-dns.net."
constant healthcheckFQDN (line 96) | healthcheckFQDN = "healthcheck.adguardhome.test."
method processInitial (line 102) | func (s *Server) processInitial(ctx context.Context, dctx *dnsContext) (...
method processClientIP (line 145) | func (s *Server) processClientIP(ctx context.Context, addr netip.Addr) {
method processDDRQuery (line 165) | func (s *Server) processDDRQuery(ctx context.Context, dctx *dnsContext) ...
method makeDDRResponse (line 191) | func (s *Server) makeDDRResponse(req *dns.Msg) (resp *dns.Msg) {
method processDHCPHosts (line 264) | func (s *Server) processDHCPHosts(ctx context.Context, dctx *dnsContext)...
method processDHCPAddrs (line 330) | func (s *Server) processDHCPAddrs(ctx context.Context, dctx *dnsContext)...
method processFilteringBeforeRequest (line 375) | func (s *Server) processFilteringBeforeRequest(
function ipStringFromAddr (line 410) | func ipStringFromAddr(addr net.Addr) (ipStr string) {
method processUpstream (line 419) | func (s *Server) processUpstream(ctx context.Context, dctx *dnsContext) ...
method setReqAD (line 474) | func (s *Server) setReqAD(req *dns.Msg) (wantsDNSSEC bool) {
function hasDO (line 495) | func hasDO(msg *dns.Msg) (do bool) {
method setRespAD (line 506) | func (s *Server) setRespAD(pctx *proxy.DNSContext, reqWantsDNSSEC bool) {
method dhcpHostFromRequest (line 515) | func (s *Server) dhcpHostFromRequest(q *dns.Question) (reqHost string) {
method setCustomUpstream (line 536) | func (s *Server) setCustomUpstream(ctx context.Context, pctx *proxy.DNSC...
method processFilteringAfterResponse (line 556) | func (s *Server) processFilteringAfterResponse(ctx context.Context, dctx...
method filterAfterResponse (line 589) | func (s *Server) filterAfterResponse(ctx context.Context, dctx *dnsConte...
FILE: internal/dnsforward/process_internal_test.go
constant ddrTestDomainName (line 23) | ddrTestDomainName = "dns.example.net"
constant ddrTestFQDN (line 24) | ddrTestFQDN = ddrTestDomainName + "."
function TestServer_ProcessInitial (line 27) | func TestServer_ProcessInitial(t *testing.T) {
function TestServer_ProcessFilteringAfterResponse (line 121) | func TestServer_ProcessFilteringAfterResponse(t *testing.T) {
function TestServer_ProcessDDRQuery (line 218) | func TestServer_ProcessDDRQuery(t *testing.T) {
function createTestDNSFilter (line 379) | func createTestDNSFilter(tb testing.TB) (f *filtering.DNSFilter) {
function TestServer_ProcessDHCPHosts_localRestriction (line 391) | func TestServer_ProcessDHCPHosts_localRestriction(t *testing.T) {
function TestServer_ProcessDHCPHosts (line 503) | func TestServer_ProcessDHCPHosts(t *testing.T) {
function TestServer_ProcessUpstream_localPTR (line 643) | func TestServer_ProcessUpstream_localPTR(t *testing.T) {
function TestIPStringFromAddr (line 725) | func TestIPStringFromAddr(t *testing.T) {
FILE: internal/dnsforward/requesthandler.go
method ServeDNS (line 17) | func (s *Server) ServeDNS(ctx context.Context, _ *proxy.Proxy, pctx *pro...
FILE: internal/dnsforward/requesthandler_internal_test.go
function TestServer_ServeDNS (line 20) | func TestServer_ServeDNS(t *testing.T) {
function TestServer_ServeDNS_restrictLocal (line 216) | func TestServer_ServeDNS_restrictLocal(t *testing.T) {
FILE: internal/dnsforward/stats.go
method processQueryLogsAndStats (line 17) | func (s *Server) processQueryLogsAndStats(ctx context.Context, dctx *dns...
method shouldLog (line 78) | func (s *Server) shouldLog(host string, qt, cl uint16, ids []string) (ok...
method shouldCountStat (line 90) | func (s *Server) shouldCountStat(host string, qt, cl uint16, ids []strin...
method logQuery (line 97) | func (s *Server) logQuery(dctx *dnsContext, ip net.IP, processingTime ti...
method updateStats (line 141) | func (s *Server) updateStats(dctx *dnsContext, clientIP string, processi...
FILE: internal/dnsforward/stats_internal_test.go
type testQueryLog (line 21) | type testQueryLog struct
method Add (line 30) | func (l *testQueryLog) Add(p *querylog.AddParams) {
method ShouldLog (line 35) | func (l *testQueryLog) ShouldLog(string, uint16, uint16, []string) bool {
type testStats (line 40) | type testStats struct
method Update (line 49) | func (l *testStats) Update(e *stats.Entry) {
method ShouldCount (line 58) | func (l *testStats) ShouldCount(string, uint16, uint16, []string) bool {
function TestServer_ProcessQueryLogsAndStats (line 62) | func TestServer_ProcessQueryLogsAndStats(t *testing.T) {
FILE: internal/dnsforward/svcbmsg.go
method genAnswerHTTPS (line 19) | func (s *Server) genAnswerHTTPS(ctx context.Context, req *dns.Msg, svcb ...
type svcbKeyHandler (line 50) | type svcbKeyHandler
method genAnswerSVCB (line 173) | func (s *Server) genAnswerSVCB(
FILE: internal/dnsforward/svcbmsg_internal_test.go
function TestGenAnswerHTTPS_andSVCB (line 14) | func TestGenAnswerHTTPS_andSVCB(t *testing.T) {
FILE: internal/dnsforward/upstreams.go
function newBootstrap (line 27) | func newBootstrap(
function newUpstreamConfig (line 60) | func newUpstreamConfig(
function newPrivateConfig (line 97) | func newPrivateConfig(
function setProxyUpstreamMode (line 143) | func setProxyUpstreamMode(
FILE: internal/dnsforward/upstreams_internal_test.go
function TestUpstreamConfigValidator (line 17) | func TestUpstreamConfigValidator(t *testing.T) {
function TestUpstreamConfigValidator_Check_once (line 163) | func TestUpstreamConfigValidator_Check_once(t *testing.T) {
FILE: internal/filtering/blocked.go
function initBlockedServices (line 29) | func initBlockedServices(ctx context.Context, l *slog.Logger) {
type BlockedServices (line 66) | type BlockedServices struct
method Clone (line 75) | func (s *BlockedServices) Clone() (c *BlockedServices) {
method FilterUnknownIDs (line 88) | func (s *BlockedServices) FilterUnknownIDs(ctx context.Context, logger...
method Validate (line 108) | func (s *BlockedServices) Validate() (err error) {
method ApplyBlockedServices (line 125) | func (d *DNSFilter) ApplyBlockedServices(setts *Settings) {
method ApplyBlockedServicesList (line 140) | func (d *DNSFilter) ApplyBlockedServicesList(setts *Settings, list []str...
method handleBlockedServicesIDs (line 156) | func (d *DNSFilter) handleBlockedServicesIDs(w http.ResponseWriter, r *h...
method handleBlockedServicesAll (line 160) | func (d *DNSFilter) handleBlockedServicesAll(w http.ResponseWriter, r *h...
method handleBlockedServicesList (line 174) | func (d *DNSFilter) handleBlockedServicesList(w http.ResponseWriter, r *...
method handleBlockedServicesSet (line 190) | func (d *DNSFilter) handleBlockedServicesSet(w http.ResponseWriter, r *h...
method handleBlockedServicesGet (line 214) | func (d *DNSFilter) handleBlockedServicesGet(w http.ResponseWriter, r *h...
method handleBlockedServicesUpdate (line 228) | func (d *DNSFilter) handleBlockedServicesUpdate(w http.ResponseWriter, r...
FILE: internal/filtering/dnsrewrite.go
type DNSRewriteResult (line 10) | type DNSRewriteResult struct
type DNSRewriteResultResponse (line 17) | type DNSRewriteResultResponse
method processDNSRewrites (line 22) | func (d *DNSFilter) processDNSRewrites(dnsr []*rules.NetworkRule) (res R...
method processDNSResultRewrites (line 75) | func (d *DNSFilter) processDNSResultRewrites(
FILE: internal/filtering/dnsrewrite_test.go
function TestDNSFilter_CheckHostRules_dnsrewrite (line 15) | func TestDNSFilter_CheckHostRules_dnsrewrite(t *testing.T) {
FILE: internal/filtering/filter.go
constant filterDir (line 27) | filterDir = "filters"
type FilterYAML (line 32) | type FilterYAML struct
method unload (line 45) | func (filter *FilterYAML) unload() {
method Path (line 51) | func (filter *FilterYAML) Path(dataDir string) string {
method ensureName (line 61) | func (filter *FilterYAML) ensureName(title string) {
constant errFilterNotExist (line 80) | errFilterNotExist errors.Error = "url doesn't exist"
constant errFilterExists (line 86) | errFilterExists errors.Error = "url already exists"
method filterSetProperties (line 92) | func (d *DNSFilter) filterSetProperties(
method filterExists (line 169) | func (d *DNSFilter) filterExists(url string) (ok bool) {
method filterExistsLocked (line 180) | func (d *DNSFilter) filterExistsLocked(url string) (ok bool) {
method filterAdd (line 198) | func (d *DNSFilter) filterAdd(flt FilterYAML) (err error) {
method loadFilters (line 221) | func (d *DNSFilter) loadFilters(ctx context.Context, array []FilterYAML) {
function deduplicateFilters (line 243) | func deduplicateFilters(filters []FilterYAML) (deduplicated []FilterYAML) {
method tryRefreshFilters (line 263) | func (d *DNSFilter) tryRefreshFilters(block, allow, force bool) (updated...
method listsToUpdate (line 275) | func (d *DNSFilter) listsToUpdate(filters *[]FilterYAML, force bool) (to...
method refreshFiltersArray (line 311) | func (d *DNSFilter) refreshFiltersArray(
method updateFilterList (line 337) | func (d *DNSFilter) updateFilterList(
method syncUpdatedFilters (line 357) | func (d *DNSFilter) syncUpdatedFilters(
method refreshFiltersIntl (line 414) | func (d *DNSFilter) refreshFiltersIntl(block, allow, force bool) (int, b...
function removeOldFilterFile (line 463) | func removeOldFilterFile(ctx context.Context, l *slog.Logger, fltPath st...
method update (line 478) | func (d *DNSFilter) update(filter *FilterYAML) (b bool, err error) {
method updateIntl (line 499) | func (d *DNSFilter) updateIntl(ctx context.Context, flt *FilterYAML) (ok...
method finalizeUpdate (line 529) | func (d *DNSFilter) finalizeUpdate(
method reader (line 571) | func (d *DNSFilter) reader(fltURL string) (r io.ReadCloser, err error) {
method readerFromURL (line 596) | func (d *DNSFilter) readerFromURL(fltURL string) (r io.ReadCloser, err e...
method load (line 611) | func (d *DNSFilter) load(ctx context.Context, flt *FilterYAML) (err erro...
method EnableFilters (line 649) | func (d *DNSFilter) EnableFilters(async bool) {
method enableFiltersLocked (line 657) | func (d *DNSFilter) enableFiltersLocked(ctx context.Context, async bool) {
method ApplyAdditionalFiltering (line 697) | func (d *DNSFilter) ApplyAdditionalFiltering(cliAddr netip.Addr, clientI...
FILE: internal/filtering/filter_internal_test.go
function serveHTTPLocally (line 20) | func serveHTTPLocally(tb testing.TB, h http.Handler) (urlStr string) {
function serveFiltersLocally (line 39) | func serveFiltersLocally(tb testing.TB, fltContent []byte) (urlStr strin...
function updateAndAssert (line 53) | func updateAndAssert(
function newDNSFilter (line 80) | func newDNSFilter(tb testing.TB) (d *DNSFilter) {
function TestDNSFilter_Update (line 95) | func TestDNSFilter_Update(t *testing.T) {
function TestFilterYAML_EnsureName (line 139) | func TestFilterYAML_EnsureName(t *testing.T) {
FILE: internal/filtering/filtering.go
type ServiceEntry (line 39) | type ServiceEntry struct
type Settings (line 47) | type Settings struct
type Resolver (line 69) | type Resolver interface
type Config (line 74) | type Config struct
type BlockingMode (line 192) | type BlockingMode
constant BlockingModeCustomIP (line 197) | BlockingModeCustomIP BlockingMode = "custom_ip"
constant BlockingModeDefault (line 202) | BlockingModeDefault BlockingMode = "default"
constant BlockingModeNullIP (line 206) | BlockingModeNullIP BlockingMode = "null_ip"
constant BlockingModeNXDOMAIN (line 209) | BlockingModeNXDOMAIN BlockingMode = "nxdomain"
constant BlockingModeREFUSED (line 212) | BlockingModeREFUSED BlockingMode = "refused"
type LookupStats (line 216) | type LookupStats struct
type Stats (line 224) | type Stats struct
type filtersInitializerParams (line 231) | type filtersInitializerParams struct
type hostChecker (line 236) | type hostChecker struct
type Checker (line 242) | type Checker interface
type DNSFilter (line 248) | type DNSFilter struct
method SetEnabled (line 314) | func (d *DNSFilter) SetEnabled(enabled bool) {
method Settings (line 319) | func (d *DNSFilter) Settings() (s *Settings) {
method WriteDiskConfig (line 332) | func (d *DNSFilter) WriteDiskConfig(c *Config) {
method setFilters (line 354) | func (d *DNSFilter) setFilters(
method Close (line 389) | func (d *DNSFilter) Close() {
method reset (line 400) | func (d *DNSFilter) reset(ctx context.Context) {
method ProtectionStatus (line 416) | func (d *DNSFilter) ProtectionStatus() (status bool, disabledUntil *ti...
method SetProtectionStatus (line 425) | func (d *DNSFilter) SetProtectionStatus(status bool, disabledUntil *ti...
method SetProtectionEnabled (line 434) | func (d *DNSFilter) SetProtectionEnabled(status bool) {
method SetBlockingMode (line 442) | func (d *DNSFilter) SetBlockingMode(mode BlockingMode, bIPv4, bIPv6 ne...
method BlockingMode (line 454) | func (d *DNSFilter) BlockingMode() (mode BlockingMode, bIPv4, bIPv6 ne...
method SetBlockedResponseTTL (line 462) | func (d *DNSFilter) SetBlockedResponseTTL(ttl uint32) {
method BlockedResponseTTL (line 470) | func (d *DNSFilter) BlockedResponseTTL() (ttl uint32) {
method SafeBrowsingBlockHost (line 478) | func (d *DNSFilter) SafeBrowsingBlockHost() (host string) {
method ParentalBlockHost (line 483) | func (d *DNSFilter) ParentalBlockHost() (host string) {
method CheckHostRules (line 494) | func (d *DNSFilter) CheckHostRules(host string, rrtype uint16, setts *...
method CheckHost (line 500) | func (d *DNSFilter) CheckHost(
method processRewrites (line 543) | func (d *DNSFilter) processRewrites(host string, qtype uint16) (res Re...
method handleRewriteLoop (line 565) | func (d *DNSFilter) handleRewriteLoop(
method matchBlockedServicesRules (line 618) | func (d *DNSFilter) matchBlockedServicesRules(
method initFiltering (line 741) | func (d *DNSFilter) initFiltering(ctx context.Context, allowFilters, b...
method matchHostProcessAllowList (line 790) | func (d *DNSFilter) matchHostProcessAllowList(
method matchHostProcessDNSResult (line 819) | func (d *DNSFilter) matchHostProcessDNSResult(
method matchHost (line 879) | func (d *DNSFilter) matchHost(
method validateSafeFSPatterns (line 1057) | func (d *DNSFilter) validateSafeFSPatterns(patterns []string) (err err...
method Start (line 1072) | func (d *DNSFilter) Start() {
method updatesLoop (line 1082) | func (d *DNSFilter) updatesLoop(ctx context.Context) {
method periodicallyRefreshFilters (line 1110) | func (d *DNSFilter) periodicallyRefreshFilters(ivl time.Duration) (nex...
method checkSafeBrowsing (line 1133) | func (d *DNSFilter) checkSafeBrowsing(
method checkParental (line 1169) | func (d *DNSFilter) checkParental(
type Filter (line 302) | type Filter struct
method Matched (line 489) | func (r Reason) Matched() bool {
function newRuleStorage (line 668) | func newRuleStorage(filters []Filter) (rs *fi
Condensed preview — 933 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8,113K chars).
[
{
"path": ".codecov.yml",
"chars": 146,
"preview": "'coverage':\n 'status':\n 'project':\n 'default':\n 'target': '40%'\n 'threshold': null\n 'patch': f"
},
{
"path": ".gitattributes",
"chars": 252,
"preview": "client/* linguist-vendored\n# This file contains a lot of inline SVG data, which often interferes with\n# grepping. Techn"
},
{
"path": ".github/ISSUE_TEMPLATE/bug.yml",
"chars": 5944,
"preview": "'body':\n - 'attributes':\n 'description': >\n Please make sure that the issue is not a duplicate or a q"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 1026,
"preview": "'blank_issues_enabled': false\n'contact_links':\n - 'about': >\n Please report filtering issues, for example advert"
},
{
"path": ".github/ISSUE_TEMPLATE/feature.yml",
"chars": 2177,
"preview": "'body':\n - 'attributes':\n 'description': >\n Please make sure that the issue is not a duplicate or a q"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE",
"chars": 828,
"preview": "Before submitting a PR please make sure that:\n\n1. You have discussed your solution in an issue and have got an\n appr"
},
{
"path": ".github/stale.yml",
"chars": 976,
"preview": "# Number of days of inactivity before an issue becomes stale.\n'daysUntilStale': 90\n# Number of days of inactivity before"
},
{
"path": ".github/workflows/build.yml",
"chars": 4393,
"preview": "'name': 'build'\n\n'env':\n 'GO_VERSION': '1.26.1'\n 'NODE_VERSION': '20'\n\n'on':\n 'push':\n 'branches':\n - '*'\n '"
},
{
"path": ".github/workflows/lint.yml",
"chars": 1633,
"preview": "'name': 'lint'\n\n'env':\n 'GO_VERSION': '1.26.1'\n\n'on':\n 'push':\n 'tags':\n - 'v*'\n 'branches':\n - '*'\n 'pul"
},
{
"path": ".github/workflows/potential-duplicates.yml",
"chars": 549,
"preview": "'name': 'potential-duplicates'\n'on':\n 'issues':\n 'types':\n - 'opened'\n'jobs':\n 'run':\n 'run"
},
{
"path": ".gitignore",
"chars": 993,
"preview": "# This comment is used to simplify checking local copies of the file. Bump\n# this number every time a significant chang"
},
{
"path": ".markdownlint.json",
"chars": 422,
"preview": "{\n \"ul-indent\": {\n \"indent\": 4\n },\n \"ul-style\": {\n \"style\": \"dash\"\n },\n \"emphasis-style\": {\n \"style\": \"ast"
},
{
"path": ".twosky.json",
"chars": 2070,
"preview": "[\n {\n \"project_id\": \"home\",\n \"base_locale\": \"en\",\n \"localizable_files\": [\n \"client/src/__locales/en.json\""
},
{
"path": "AGHTechDoc.md",
"chars": 45898,
"preview": "# AdGuard Home Technical Document\n\nThe document describes technical details and internal algorithms of AdGuard Home.\n\nCo"
},
{
"path": "CHANGELOG.md",
"chars": 141576,
"preview": "# AdGuard Home Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on ["
},
{
"path": "CONTRIBUTING.md",
"chars": 3082,
"preview": "# Contributing to AdGuard Home\n\nIf you want to contribute to AdGuard Home by filing or commenting on an issue or opening"
},
{
"path": "HACKING.md",
"chars": 3299,
"preview": "# AdGuard Home developer guidelines\n\nThis document was moved to the [AdGuard Code Guidelines repository][repo]. All sec"
},
{
"path": "LICENSE.txt",
"chars": 35149,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "Makefile",
"chars": 5410,
"preview": "# Keep the Makefile POSIX-compliant. We currently allow hyphens in target\n# names, but that may change in the future.\n#"
},
{
"path": "README.md",
"chars": 22485,
"preview": " \n<p align=\"center\">\n <picture>\n <source media=\"(prefers-color-scheme: dark)\" srcset=\"doc/adguard_home_darkmode"
},
{
"path": "SECURITY.md",
"chars": 666,
"preview": "# Security Policy\n\n## Reporting vulnerabilities\n\nPlease send your vulnerability reports to <security@adguard.com>. To m"
},
{
"path": "bamboo-specs/bamboo.yaml",
"chars": 79,
"preview": "---\n!include release.yaml\n\n---\n!include snapcraft.yaml\n\n---\n!include test.yaml\n"
},
{
"path": "bamboo-specs/release.yaml",
"chars": 9457,
"preview": "---\n'version': 2\n'plan':\n 'project-key': 'AGH'\n 'key': 'AGHBSNAPSPECS'\n 'name': 'AdGuard Home - Build and publi"
},
{
"path": "bamboo-specs/snapcraft.yaml",
"chars": 5509,
"preview": "---\n# This part of the release build is separate from the one described in\n# release.yaml, because the Snapcraft infrast"
},
{
"path": "bamboo-specs/test.yaml",
"chars": 7349,
"preview": "---\n'version': 2\n'plan':\n 'project-key': 'AGH'\n 'key': 'AHBRTSPECS'\n 'name': 'AdGuard Home - Build and run test"
},
{
"path": "build/gitkeep",
"chars": 54,
"preview": "Keep this file non-hidden for Go's embedding to work.\n"
},
{
"path": "changelog.config.js",
"chars": 891,
"preview": "module.exports = {\n \"disableEmoji\": true,\n \"list\": [\n \"+ \",\n \"* \",\n \"- \",\n ],\n \"maxMess"
},
{
"path": "client/.eslintrc.json",
"chars": 1604,
"preview": "{\n \"plugins\": [\n \"prettier\"\n ],\n \"extends\": [\n \"airbnb-base\",\n \"prettier\",\n \"eslint:recommended\",\n \"pl"
},
{
"path": "client/.gitattributes",
"chars": 17,
"preview": "*.ts text eol=lf\n"
},
{
"path": "client/.prettierrc",
"chars": 187,
"preview": "{\n \"printWidth\": 120,\n \"singleQuote\": true,\n \"trailingComma\": \"all\",\n \"bracketSpacing\": true,\n \"bracketSameLine\": t"
},
{
"path": "client/.stylelintrc.js",
"chars": 1430,
"preview": "module.exports = {\n rules: {\n \"selector-type-no-unknown\": true,\n \"block-closing-brace-empty-line-before\": \"ne"
},
{
"path": "client/babel.config.cjs",
"chars": 517,
"preview": "module.exports = (api) => {\n api.cache(false);\n return {\n presets: ['@babel/preset-env', '@babel/preset-typ"
},
{
"path": "client/constants.js",
"chars": 115,
"preview": "export const BUILD_ENVS = {\n dev: 'development',\n prod: 'production',\n};\n\nexport const BASE_URL = 'control';\n"
},
{
"path": "client/dev.eslintrc",
"chars": 82,
"preview": "{\n \"extends\": \".eslintrc\",\n \"rules\": {\n \"no-debugger\":\"warn\"\n }\n}\n"
},
{
"path": "client/global.d.ts",
"chars": 160,
"preview": "import React from 'react';\n\ndeclare module '*.svg' {\n const content: React.FunctionComponent<React.SVGAttributes<SVGE"
},
{
"path": "client/package.json",
"chars": 4119,
"preview": "{\n \"name\": \"dashboard\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"build-dev\": \"cross-env NODE_ENV=de"
},
{
"path": "client/playwright.config.ts",
"chars": 1770,
"preview": "import { defineConfig, devices } from '@playwright/test';\n\nimport path from 'path';\nimport { CONFIG_FILE_PATH } from './"
},
{
"path": "client/prod.eslintrc",
"chars": 97,
"preview": "{\n \"rules\": {\n // disallow the use of debugger\n \"no-debugger\": \"error\",\n }\n}\n"
},
{
"path": "client/public/index.html",
"chars": 1793,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width="
},
{
"path": "client/public/install.html",
"chars": 907,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width="
},
{
"path": "client/public/login.html",
"chars": 1214,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width="
},
{
"path": "client/src/__locales/ar.json",
"chars": 49495,
"preview": "{\n \"access_allowed_desc\": \"قائمة CIDRs أو عناوين IP أو <a> ClientIDs </a>. إذا كانت هذه القائمة تحتوي على إدخالات ، فسي"
},
{
"path": "client/src/__locales/be.json",
"chars": 52785,
"preview": "{\n \"access_allowed_desc\": \"Спіс CIDR, IP-адрасоў або <a>ClientID</a>. Калі ў гэтым спісе ёсць запісы, AdGuard Home будз"
},
{
"path": "client/src/__locales/bg.json",
"chars": 54712,
"preview": "{\n \"access_allowed_desc\": \"Списък от CIDR, IP адреси или <a>ClientIDs</a>. Ако този списък съдържа записи, AdGuard Home"
},
{
"path": "client/src/__locales/cs.json",
"chars": 53321,
"preview": "{\n \"access_allowed_desc\": \"Seznam CIDR, IP adres nebo <a>ID klientů</a>. Pokud tento seznam obsahuje položky, AdGuard H"
},
{
"path": "client/src/__locales/da.json",
"chars": 51888,
"preview": "{\n \"access_allowed_desc\": \"En liste over CIDR'er, IP-adresser eller <a>KlientID'er</a>. Har listen poster, accepterer A"
},
{
"path": "client/src/__locales/de.json",
"chars": 57627,
"preview": "{\n \"access_allowed_desc\": \"Eine Liste von CIDRs, IP-Adressen oder <a>Client-IDs</a>. Wenn diese Liste gefüllt ist, akze"
},
{
"path": "client/src/__locales/en.json",
"chars": 51210,
"preview": "{\n \"access_allowed_desc\": \"A list of CIDRs, IP addresses, or <a>ClientIDs</a>. If this list has entries, AdGuard Home w"
},
{
"path": "client/src/__locales/es.json",
"chars": 57488,
"preview": "{\n \"access_allowed_desc\": \"Lista de CIDR, direcciones IP o <a>ID de clientes</a>. Si esta lista tiene entradas, AdGuard"
},
{
"path": "client/src/__locales/fa.json",
"chars": 50916,
"preview": "{\n \"access_allowed_desc\": \"یک لیست از CIDR یا آدرس های IP.اگر پیکربندی شود،AdGuard Home درخواست ها را فقط از این آدرس ه"
},
{
"path": "client/src/__locales/fi.json",
"chars": 53961,
"preview": "{\n \"access_allowed_desc\": \"Lista CIDR-merkinnöistä, IP-osoitteista tai <a>ClientID</a>-tunnisteista. Jos listalla on ko"
},
{
"path": "client/src/__locales/fr.json",
"chars": 57499,
"preview": "{\n \"access_allowed_desc\": \"Une liste de CIDRs, d'adresses IP, ou de <a>ClientIDs</a>. Si cette liste comporte des entré"
},
{
"path": "client/src/__locales/hr.json",
"chars": 53692,
"preview": "{\n \"access_allowed_desc\": \"Popis CIDR-ova, IP adresa ili <a>ClientIDs</a>. Ako ovaj popis ima unose, AdGuard Home prihv"
},
{
"path": "client/src/__locales/hu.json",
"chars": 56487,
"preview": "{\n \"access_allowed_desc\": \"CIDR-ek, IP-címek vagy <a>ClientID-k</a> listája. Ha be van állítva, akkor az AdGuard Home c"
},
{
"path": "client/src/__locales/id.json",
"chars": 53670,
"preview": "{\n \"access_allowed_desc\": \"Daftar CIDR, alamat IP, atau <a>ClientID</a>. Jika daftar ini memiliki entri, AdGuard Home h"
},
{
"path": "client/src/__locales/it.json",
"chars": 56335,
"preview": "{\n \"access_allowed_desc\": \"Un elenco di CIDR, indirizzi IP, o <a>ClientID</a>. Se l'elenco conterrà elementi, AdGuard H"
},
{
"path": "client/src/__locales/ja.json",
"chars": 40403,
"preview": "{\n \"access_allowed_desc\": \"CIDR、IPアドレス、または<a>ClientID</a>のリスト。このリストに入力がある場合、AdGuard Homeはリストに入っているクライアントからのみリクエストを受け入れま"
},
{
"path": "client/src/__locales/ko.json",
"chars": 38872,
"preview": "{\n \"access_allowed_desc\": \"CIDR, IP 주소 또는 <a>ClientID</a> 목록입니다. 이 목록에 항목이 있는 경우, AdGuard Home은 이러한 클라이언트의 요청만 수락합니다.\","
},
{
"path": "client/src/__locales/nl.json",
"chars": 55235,
"preview": "{\n \"access_allowed_desc\": \"Een lijst met CIDR's, IP-adressen of <a>Client-ID's</a>. Indien geconfigureerd, accepteert A"
},
{
"path": "client/src/__locales/no.json",
"chars": 54100,
"preview": "{\n \"access_allowed_desc\": \"En liste over CIDR- eller IP-adresser. Dersom dette er satt opp, vil AdGuard Home kun aksept"
},
{
"path": "client/src/__locales/pl.json",
"chars": 55067,
"preview": "{\n \"access_allowed_desc\": \"Lista identyfikatorów CIDR, adresów IP lub <a>identyfikatorów klienta</a>. Jeśli ta lista za"
},
{
"path": "client/src/__locales/pt-br.json",
"chars": 56712,
"preview": "{\n \"access_allowed_desc\": \"Uma lista de CIDRs, endereços IP ou <a>IDs de cliente</a>. Se esta lista tiver entradas, o A"
},
{
"path": "client/src/__locales/pt-pt.json",
"chars": 56535,
"preview": "{\n \"access_allowed_desc\": \"Uma lista de CIDRs, endereços IP ou <a>IDs de cliente</a>. Se esta lista tiver entradas, o A"
},
{
"path": "client/src/__locales/ro.json",
"chars": 55167,
"preview": "{\n \"access_allowed_desc\": \"O listă de CIDR-uri, adrese IP sau <a>ClientID-uri</a>. Dacă această listă are intrări, AdGu"
},
{
"path": "client/src/__locales/ru.json",
"chars": 53484,
"preview": "{\n \"access_allowed_desc\": \"Список CIDR, IP-адресов или <a>ClientID</a>. Если в списке есть записи, AdGuard Home будет п"
},
{
"path": "client/src/__locales/si-lk.json",
"chars": 53827,
"preview": "{\n \"access_allowed_desc\": \"අන.ජා.(CIDR), අ.ජා.කෙ. ලිපින හෝ <a>අනුග්රාහක හැඳු.</a> ලේඛනයකි. මෙහි නිවේශිත ඇත්නම්, ඇඩ්ගාර"
},
{
"path": "client/src/__locales/sk.json",
"chars": 53953,
"preview": "{\n \"access_allowed_desc\": \"Zoznam CIDR, IP adries alebo <a>ClientID</a>. Ak tento zoznam obsahuje položky, AdGuard Home"
},
{
"path": "client/src/__locales/sl.json",
"chars": 54084,
"preview": "{\n \"access_allowed_desc\": \"Seznam CIDR-jev, naslovov IP ali <a>ID-jev odjemalcev</a>. Če ta seznam vsebuje vnose, bo Ad"
},
{
"path": "client/src/__locales/sr-cs.json",
"chars": 52947,
"preview": "{\n \"access_allowed_desc\": \"Spisak CIDR, IP adresa ili <a>ClientIDs</a>. Ako ova lista ima stavke, AdGuard Home će prihv"
},
{
"path": "client/src/__locales/sv.json",
"chars": 52876,
"preview": "{\n \"access_allowed_desc\": \"En lista över CIDR, IP-adresser eller <a>ClientID</a>. Om den här listan har poster accepter"
},
{
"path": "client/src/__locales/th.json",
"chars": 50157,
"preview": "{\n \"access_allowed_desc\": \"รายการ CIDR หรือที่อยู่ IP หากมีการตั้งค่าไว้ AdGuard Home จะยอมรับคำขอจากที่อยู่ IP เหล่านี"
},
{
"path": "client/src/__locales/tr.json",
"chars": 54919,
"preview": "{\n \"access_allowed_desc\": \"CIDR'lerin, IP adreslerinin veya <a>ClientIDs</a> listesi. Bu listede girişler varsa, AdGuar"
},
{
"path": "client/src/__locales/uk.json",
"chars": 53487,
"preview": "{\n \"access_allowed_desc\": \"Перелік CIDR, IP-адрес та <a>ClientIDs</a>. Якщо налаштовано, AdGuard Home прийматиме запити"
},
{
"path": "client/src/__locales/vi.json",
"chars": 52384,
"preview": "{\n \"access_allowed_desc\": \"Danh sách CIDR, địa chỉ IP hoặc <a>ClientID</a>. Nếu danh sách này có các mục nhập, AdGuard "
},
{
"path": "client/src/__locales/zh-cn.json",
"chars": 34621,
"preview": "{\n \"access_allowed_desc\": \"CIDR、IP 地址或<a>客户端 ID</a> 的列表。如已配置,则 AdGuard Home 将仅接受来自这些客户端的请求。\",\n \"access_allowed_title\":"
},
{
"path": "client/src/__locales/zh-hk.json",
"chars": 34049,
"preview": "{\n \"access_allowed_desc\": \"輸入 CIDR 或 IP 位址格式的清單,設定後 AdGuard Home 將僅接受設定的 IP 位址查詢請求。\",\n \"access_allowed_title\": \"用戶端白名單"
},
{
"path": "client/src/__locales/zh-tw.json",
"chars": 35441,
"preview": "{\n \"access_allowed_desc\": \"無類別網域間路由(CIDRs)、IP 位址或<a>用戶端 IDs</a> 之清單。如果此清單有項目,AdGuard Home 將接受僅來自這些用戶端的請求。\",\n \"access_a"
},
{
"path": "client/src/__locales-services/ar.json",
"chars": 880,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"الذكاء الاصطناعي\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"شبكا"
},
{
"path": "client/src/__locales-services/be.json",
"chars": 915,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Штучны інтэлект\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Сеткі"
},
{
"path": "client/src/__locales-services/bg.json",
"chars": 912,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Изкуствен интелект\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Мр"
},
{
"path": "client/src/__locales-services/cs.json",
"chars": 902,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Umělá inteligence\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Sít"
},
{
"path": "client/src/__locales-services/da.json",
"chars": 882,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Kunstig intelligens\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"I"
},
{
"path": "client/src/__locales-services/de.json",
"chars": 892,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Künstliche Intelligenz\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\":"
},
{
"path": "client/src/__locales-services/en.json",
"chars": 888,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Artificial intelligence\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\""
},
{
"path": "client/src/__locales-services/es.json",
"chars": 922,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Inteligencia artificial\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\""
},
{
"path": "client/src/__locales-services/fa.json",
"chars": 845,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"هوش مصنوعی\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"شبکههای ت"
},
{
"path": "client/src/__locales-services/fi.json",
"chars": 887,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Tekoäly\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Sisällönjakel"
},
{
"path": "client/src/__locales-services/fr.json",
"chars": 951,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Intelligence artificielle\"\n },\n \"servicesgroup.cdn.name\": {\n \"messag"
},
{
"path": "client/src/__locales-services/hr.json",
"chars": 895,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Umjetna inteligencija\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": "
},
{
"path": "client/src/__locales-services/hu.json",
"chars": 925,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Mesterséges intelligencia\"\n },\n \"servicesgroup.cdn.name\": {\n \"messag"
},
{
"path": "client/src/__locales-services/id.json",
"chars": 874,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Kecerdasan buatan\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Jar"
},
{
"path": "client/src/__locales-services/it.json",
"chars": 940,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Intelligenza artificiale\"\n },\n \"servicesgroup.cdn.name\": {\n \"message"
},
{
"path": "client/src/__locales-services/ja.json",
"chars": 792,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"人工知能(AI)\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"コンテンツ配信ネットワー"
},
{
"path": "client/src/__locales-services/ko.json",
"chars": 773,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"인공지능\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"콘텐츠 전송 네트워크(CDN)"
},
{
"path": "client/src/__locales-services/nl.json",
"chars": 889,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Kunstmatige intelligentie\"\n },\n \"servicesgroup.cdn.name\": {\n \"messag"
},
{
"path": "client/src/__locales-services/no.json",
"chars": 889,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Kunstig intelligens\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"N"
},
{
"path": "client/src/__locales-services/pl.json",
"chars": 909,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Sztuczna inteligencja\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": "
},
{
"path": "client/src/__locales-services/pt-br.json",
"chars": 931,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Inteligência artificial\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\""
},
{
"path": "client/src/__locales-services/pt-pt.json",
"chars": 931,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Inteligência artificial\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\""
},
{
"path": "client/src/__locales-services/ro.json",
"chars": 936,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Inteligenţă artificială\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\""
},
{
"path": "client/src/__locales-services/ru.json",
"chars": 927,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Искусственный интеллект\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\""
},
{
"path": "client/src/__locales-services/si-lk.json",
"chars": 862,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"කෘතිම බුද්ධිය\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"අන්තර්ග"
},
{
"path": "client/src/__locales-services/sk.json",
"chars": 916,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Umelá inteligencia\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Si"
},
{
"path": "client/src/__locales-services/sl.json",
"chars": 904,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Umetna inteligenca\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Om"
},
{
"path": "client/src/__locales-services/sr-cs.json",
"chars": 899,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Veštačka inteligencija\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\":"
},
{
"path": "client/src/__locales-services/sv.json",
"chars": 891,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Artificiell intelligens\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\""
},
{
"path": "client/src/__locales-services/th.json",
"chars": 879,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"ปัญญาประดิษฐ์\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"เครือข่"
},
{
"path": "client/src/__locales-services/tr.json",
"chars": 880,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Yapay zekâ\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"İçerik dağ"
},
{
"path": "client/src/__locales-services/uk.json",
"chars": 915,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Штучний інтелект\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Мере"
},
{
"path": "client/src/__locales-services/vi.json",
"chars": 877,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"Trí tuệ nhân tạo\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"Mạng"
},
{
"path": "client/src/__locales-services/zh-cn.json",
"chars": 742,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"人工智能\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"内容分发网络(CDN)\"\n }"
},
{
"path": "client/src/__locales-services/zh-hk.json",
"chars": 746,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"人工智能\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"內容傳遞網路 (CDN)\"\n "
},
{
"path": "client/src/__locales-services/zh-tw.json",
"chars": 746,
"preview": "{\n \"servicesgroup.ai.name\": {\n \"message\": \"人工智慧\"\n },\n \"servicesgroup.cdn.name\": {\n \"message\": \"內容傳遞網路(CDN)\"\n }"
},
{
"path": "client/src/__tests__/helpers.test.ts",
"chars": 14395,
"preview": "import { describe, expect, test, afterEach, vi, beforeEach, it } from 'vitest';\n\nimport { sortIp, countClientsStatistics"
},
{
"path": "client/src/actions/access.ts",
"chars": 4545,
"preview": "import { createAction } from 'redux-actions';\nimport i18next from 'i18next';\n\nimport apiClient from '../api/Api';\nimport"
},
{
"path": "client/src/actions/clients.ts",
"chars": 2372,
"preview": "import { createAction } from 'redux-actions';\nimport i18next from 'i18next';\nimport apiClient from '../api/Api';\n\nimport"
},
{
"path": "client/src/actions/dnsConfig.ts",
"chars": 3204,
"preview": "import { createAction } from 'redux-actions';\nimport i18next from 'i18next';\n\nimport apiClient from '../api/Api';\n\nimpor"
},
{
"path": "client/src/actions/encryption.ts",
"chars": 3741,
"preview": "import { createAction } from 'redux-actions';\nimport apiClient from '../api/Api';\n\nimport { redirectToCurrentProtocol } "
},
{
"path": "client/src/actions/filtering.ts",
"chars": 7752,
"preview": "import { createAction } from 'redux-actions';\nimport { showLoading, hideLoading } from 'react-redux-loading-bar';\nimport"
},
{
"path": "client/src/actions/index.tsx",
"chars": 29030,
"preview": "import { createAction } from 'redux-actions';\nimport i18next from 'i18next';\nimport axios from 'axios';\n\nimport endsWith"
},
{
"path": "client/src/actions/install.ts",
"chars": 2342,
"preview": "import { createAction } from 'redux-actions';\nimport apiClient from '../api/Api';\nimport { addErrorToast, addSuccessToas"
},
{
"path": "client/src/actions/login.ts",
"chars": 897,
"preview": "import { createAction } from 'redux-actions';\n\nimport apiClient from '../api/Api';\nimport { addErrorToast } from './toas"
},
{
"path": "client/src/actions/queryLogs.ts",
"chars": 7132,
"preview": "import { createAction } from 'redux-actions';\n\nimport apiClient from '../api/Api';\n\nimport { normalizeLogs } from '../he"
},
{
"path": "client/src/actions/rewrites.ts",
"chars": 4639,
"preview": "import { createAction } from 'redux-actions';\nimport i18next from 'i18next';\nimport apiClient from '../api/Api';\nimport "
},
{
"path": "client/src/actions/services.ts",
"chars": 2156,
"preview": "import { createAction } from 'redux-actions';\nimport apiClient from '../api/Api';\nimport { addErrorToast, addSuccessToas"
},
{
"path": "client/src/actions/stats.ts",
"chars": 3399,
"preview": "import { createAction } from 'redux-actions';\n\nimport apiClient from '../api/Api';\nimport { normalizeTopStats, secondsTo"
},
{
"path": "client/src/actions/toasts.ts",
"chars": 239,
"preview": "import { createAction } from 'redux-actions';\n\nexport const addErrorToast = createAction('ADD_ERROR_TOAST');\nexport cons"
},
{
"path": "client/src/api/Api.ts",
"chars": 19682,
"preview": "import axios from 'axios';\n\nimport { BASE_URL } from '../../constants';\n\nimport { getPathWithQueryString } from '../help"
},
{
"path": "client/src/components/App/index.css",
"chars": 3729,
"preview": ":root {\n --black: #131313;\n --bgcolor: #f5f7fb;\n --mcolor: #495057;\n --scolor: rgba(74, 74, 74, 0.7);\n --"
},
{
"path": "client/src/components/App/index.tsx",
"chars": 6331,
"preview": "import React, { useEffect } from 'react';\n\nimport { HashRouter, Route } from 'react-router-dom';\nimport LoadingBar from "
},
{
"path": "client/src/components/Dashboard/BlockedDomains.tsx",
"chars": 2502,
"preview": "import React from 'react';\n\n// @ts-expect-error FIXME: update react-table\nimport ReactTable from 'react-table';\nimport {"
},
{
"path": "client/src/components/Dashboard/Clients.tsx",
"chars": 7174,
"preview": "import React, { useState } from 'react';\n\n// @ts-expect-error FIXME: update react-table\nimport ReactTable from 'react-ta"
},
{
"path": "client/src/components/Dashboard/Counters.tsx",
"chars": 4510,
"preview": "import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport round from 'lodash/round';\nimpo"
},
{
"path": "client/src/components/Dashboard/Dashboard.css",
"chars": 1733,
"preview": ".dashboard-protection-button.btn-gray {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n border-ri"
},
{
"path": "client/src/components/Dashboard/DomainCell.tsx",
"chars": 2180,
"preview": "import React from 'react';\n\nimport { Trans } from 'react-i18next';\nimport { getSourceData, getTrackerData } from '../../"
},
{
"path": "client/src/components/Dashboard/QueriedDomains.tsx",
"chars": 2320,
"preview": "import React from 'react';\n\n// @ts-expect-error FIXME: update react-table\nimport ReactTable from 'react-table';\nimport {"
},
{
"path": "client/src/components/Dashboard/Statistics.tsx",
"chars": 3352,
"preview": "import React from 'react';\n\nimport { Link } from 'react-router-dom';\nimport { withTranslation, Trans } from 'react-i18ne"
},
{
"path": "client/src/components/Dashboard/StatsCard.tsx",
"chars": 961,
"preview": "import React from 'react';\n\nimport { STATUS_COLORS } from '../../helpers/constants';\n\nimport { formatNumber } from '../."
},
{
"path": "client/src/components/Dashboard/UpstreamAvgTime.tsx",
"chars": 2284,
"preview": "import React from 'react';\n\n// @ts-expect-error FIXME: update react-table\nimport ReactTable from 'react-table';\nimport r"
},
{
"path": "client/src/components/Dashboard/UpstreamResponses.tsx",
"chars": 2286,
"preview": "import React from 'react';\n\n// @ts-expect-error FIXME: update react-table\nimport ReactTable from 'react-table';\nimport {"
},
{
"path": "client/src/components/Dashboard/index.tsx",
"chars": 9984,
"preview": "import React, { useEffect } from 'react';\n\nimport { HashLink as Link } from 'react-router-hash-link';\nimport { Trans, us"
},
{
"path": "client/src/components/Filters/Actions.tsx",
"chars": 937,
"preview": "import React from 'react';\nimport { withTranslation, Trans } from 'react-i18next';\n\ninterface ActionsProps {\n handleA"
},
{
"path": "client/src/components/Filters/Check/Info.tsx",
"chars": 4348,
"preview": "import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport classNames from 'classnames';\n\nimport "
},
{
"path": "client/src/components/Filters/Check/index.tsx",
"chars": 4447,
"preview": "import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useSelector } from 'react-redux';\nim"
},
{
"path": "client/src/components/Filters/CustomRules.tsx",
"chars": 3582,
"preview": "import React, { Component } from 'react';\nimport { Trans, withTranslation } from 'react-i18next';\n\nimport Card from '../"
},
{
"path": "client/src/components/Filters/DnsAllowlist.tsx",
"chars": 5241,
"preview": "import React, { Component } from 'react';\nimport { withTranslation } from 'react-i18next';\n\nimport PageTitle from '../ui"
},
{
"path": "client/src/components/Filters/DnsBlocklist.tsx",
"chars": 5531,
"preview": "import React, { Component } from 'react';\nimport { withTranslation } from 'react-i18next';\n\nimport PageTitle from '../ui"
},
{
"path": "client/src/components/Filters/Examples.tsx",
"chars": 1833,
"preview": "import React, { Fragment } from 'react';\nimport { withTranslation, Trans } from 'react-i18next';\n\nconst Examples = () =>"
},
{
"path": "client/src/components/Filters/FiltersList.tsx",
"chars": 3332,
"preview": "import React from 'react';\nimport classNames from 'classnames';\nimport { Controller, useFormContext } from 'react-hook-f"
},
{
"path": "client/src/components/Filters/Form.tsx",
"chars": 6010,
"preview": "import React from 'react';\nimport { useForm, Controller, FormProvider } from 'react-hook-form';\nimport { useTranslation "
},
{
"path": "client/src/components/Filters/Modal.tsx",
"chars": 4622,
"preview": "import React, { Component } from 'react';\n\nimport ReactModal from 'react-modal';\nimport { withTranslation } from 'react-"
},
{
"path": "client/src/components/Filters/Rewrites/Form.tsx",
"chars": 5036,
"preview": "import React from 'react';\nimport { Controller, useForm } from 'react-hook-form';\nimport { Trans, useTranslation } from "
},
{
"path": "client/src/components/Filters/Rewrites/Modal.tsx",
"chars": 1896,
"preview": "import React from 'react';\nimport { Trans, withTranslation } from 'react-i18next';\n\nimport ReactModal from 'react-modal'"
},
{
"path": "client/src/components/Filters/Rewrites/Table.tsx",
"chars": 5216,
"preview": "import React, { Component } from 'react';\n\n// @ts-expect-error FIXME: update react-table\nimport ReactTable from 'react-t"
},
{
"path": "client/src/components/Filters/Rewrites/index.tsx",
"chars": 5265,
"preview": "import React, { Component, Fragment } from 'react';\nimport { Trans, withTranslation } from 'react-i18next';\nimport cn fr"
},
{
"path": "client/src/components/Filters/Services/Form.tsx",
"chars": 7399,
"preview": "import React, { useMemo } from 'react';\n\nimport { Trans, useTranslation } from 'react-i18next';\n\nimport { Controller, us"
},
{
"path": "client/src/components/Filters/Services/ScheduleForm/Modal.tsx",
"chars": 6633,
"preview": "import React, { useState, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport ReactModal f"
},
{
"path": "client/src/components/Filters/Services/ScheduleForm/TimePeriod.tsx",
"chars": 612,
"preview": "import React from 'react';\n\nimport { getTimeFromMs } from './helpers';\n\ninterface TimePeriodProps {\n startTimeMs: num"
},
{
"path": "client/src/components/Filters/Services/ScheduleForm/TimeSelect.tsx",
"chars": 1682,
"preview": "import React, { useState } from 'react';\n\nimport { getTimeFromMs, convertTimeToMs } from './helpers';\n\ninterface TimeSel"
},
{
"path": "client/src/components/Filters/Services/ScheduleForm/Timezone.tsx",
"chars": 1255,
"preview": "import React from 'react';\nimport ct from 'countries-and-timezones';\nimport { useTranslation } from 'react-i18next';\n\nim"
},
{
"path": "client/src/components/Filters/Services/ScheduleForm/helpers.ts",
"chars": 1254,
"preview": "export const getFullDayName = (t: any, abbreviation: any) => {\n const dayMap = {\n sun: t('sunday'),\n mo"
},
{
"path": "client/src/components/Filters/Services/ScheduleForm/index.tsx",
"chars": 4430,
"preview": "import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport cn from 'classnames';\n\ni"
},
{
"path": "client/src/components/Filters/Services/ScheduleForm/styles.css",
"chars": 2074,
"preview": ".schedule__row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;"
},
{
"path": "client/src/components/Filters/Services/ServiceField.tsx",
"chars": 1449,
"preview": "import React from 'react';\nimport cn from 'classnames';\nimport { FieldValues, ControllerRenderProps } from 'react-hook-f"
},
{
"path": "client/src/components/Filters/Services/index.tsx",
"chars": 2887,
"preview": "import React, { useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { useDispatch, useSele"
},
{
"path": "client/src/components/Filters/Table.tsx",
"chars": 5907,
"preview": "import React, { Component } from 'react';\n\n// @ts-expect-error FIXME: update react-table\nimport ReactTable from 'react-t"
},
{
"path": "client/src/components/Header/Header.css",
"chars": 3434,
"preview": ".nav-tabs .nav-link.active {\n border-color: var(--btn-success-bgcolor);\n color: var(--btn-success-bgcolor);\n ba"
},
{
"path": "client/src/components/Header/Menu.tsx",
"chars": 5080,
"preview": "import React, { Component } from 'react';\n\nimport { NavLink } from 'react-router-dom';\n\nimport enhanceWithClickOutside f"
},
{
"path": "client/src/components/Header/index.tsx",
"chars": 2587,
"preview": "import React, { useState } from 'react';\n\nimport { Link, useLocation } from 'react-router-dom';\nimport { shallowEqual, u"
},
{
"path": "client/src/components/Logs/AnonymizerNotification.tsx",
"chars": 533,
"preview": "import React from 'react';\nimport { Trans } from 'react-i18next';\n\nimport { HashLink as Link } from 'react-router-hash-l"
},
{
"path": "client/src/components/Logs/Cells/ClientCell.tsx",
"chars": 8449,
"preview": "import React, { useState } from 'react';\nimport { shallowEqual, useDispatch, useSelector } from 'react-redux';\nimport { "
},
{
"path": "client/src/components/Logs/Cells/DateCell.tsx",
"chars": 1152,
"preview": "import React from 'react';\nimport { useSelector } from 'react-redux';\n\nimport { formatDateTime, formatTime } from '../.."
},
{
"path": "client/src/components/Logs/Cells/DomainCell.tsx",
"chars": 5677,
"preview": "import React from 'react';\nimport { useSelector } from 'react-redux';\nimport classNames from 'classnames';\nimport { useT"
},
{
"path": "client/src/components/Logs/Cells/Header.tsx",
"chars": 2415,
"preview": "import { useTranslation } from 'react-i18next';\nimport { useDispatch, useSelector } from 'react-redux';\nimport className"
},
{
"path": "client/src/components/Logs/Cells/HeaderCell.tsx",
"chars": 624,
"preview": "import classNames from 'classnames';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\n\ninterfa"
},
{
"path": "client/src/components/Logs/Cells/IconTooltip.css",
"chars": 2812,
"preview": ".tooltip-custom__container {\n min-width: 150px;\n padding: 1rem 1.5rem 1.25rem 1.5rem;\n font-size: 16px !importa"
},
{
"path": "client/src/components/Logs/Cells/IconTooltip.tsx",
"chars": 2615,
"preview": "import React from 'react';\nimport { Trans } from 'react-i18next';\nimport classNames from 'classnames';\nimport PopperJS f"
},
{
"path": "client/src/components/Logs/Cells/ResponseCell.tsx",
"chars": 5119,
"preview": "import { useTranslation } from 'react-i18next';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport classNam"
},
{
"path": "client/src/components/Logs/Cells/helpers/index.ts",
"chars": 1053,
"preview": "import i18next from 'i18next';\nimport { splitByNewLine } from '../../../../helpers/helpers';\n\nexport const BUTTON_PREFIX"
},
{
"path": "client/src/components/Logs/Cells/index.tsx",
"chars": 10785,
"preview": "import React, { Dispatch, memo, SetStateAction } from 'react';\nimport classNames from 'classnames';\nimport { useTranslat"
},
{
"path": "client/src/components/Logs/Disabled.tsx",
"chars": 808,
"preview": "import React, { Fragment } from 'react';\nimport { Trans } from 'react-i18next';\n\nimport { HashLink as Link } from 'react"
},
{
"path": "client/src/components/Logs/Filters/Form.tsx",
"chars": 3851,
"preview": "import React, { useEffect } from 'react';\n\nimport { useTranslation } from 'react-i18next';\nimport { useDispatch } from '"
},
{
"path": "client/src/components/Logs/Filters/SearchField.tsx",
"chars": 1955,
"preview": "import React, { ComponentProps } from 'react';\nimport Tooltip from '../../ui/Tooltip';\n\ninterface Props extends Componen"
},
{
"path": "client/src/components/Logs/Filters/index.tsx",
"chars": 1396,
"preview": "import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useDispatch } from 'react-redux';\n\ni"
},
{
"path": "client/src/components/Logs/InfiniteTable.tsx",
"chars": 3160,
"preview": "import React, { Dispatch, SetStateAction, useCallback, useEffect, useRef } from 'react';\nimport { useDispatch, useSelect"
},
{
"path": "client/src/components/Logs/Logs.css",
"chars": 10060,
"preview": ":root {\n --blue: #e5effd;\n --green-pale: rgba(103, 178, 121, 0.1);\n --red: rgba(223, 56, 18, 0.05);\n --white"
},
{
"path": "client/src/components/Logs/index.tsx",
"chars": 8310,
"preview": "import React, { useEffect, useState } from 'react';\nimport { Trans } from 'react-i18next';\n\nimport Modal from 'react-mod"
},
{
"path": "client/src/components/ProtectionTimer/index.ts",
"chars": 1519,
"preview": "import { useEffect } from 'react';\nimport { connect } from 'react-redux';\n\nimport { ONE_SECOND_IN_MS } from '../../helpe"
},
{
"path": "client/src/components/Settings/Clients/AutoClients.tsx",
"chars": 3837,
"preview": "import React, { Component } from 'react';\nimport { withTranslation } from 'react-i18next';\n\n// @ts-expect-error FIXME: u"
},
{
"path": "client/src/components/Settings/Clients/ClientsTable/ClientsTable.tsx",
"chars": 14379,
"preview": "/* eslint-disable react/display-name */\n/* eslint-disable react/prop-types */\nimport React, { useEffect } from 'react';\n"
},
{
"path": "client/src/components/Settings/Clients/ClientsTable/index.ts",
"chars": 58,
"preview": "export { default as ClientsTable } from './ClientsTable';\n"
},
{
"path": "client/src/components/Settings/Clients/Form/components/BlockedServices.tsx",
"chars": 3501,
"preview": "import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Controller, useFormContext } "
},
{
"path": "client/src/components/Settings/Clients/Form/components/ClientIds.tsx",
"chars": 3298,
"preview": "import React from 'react';\nimport { Controller, useFieldArray, useFormContext } from 'react-hook-form';\nimport { useTran"
},
{
"path": "client/src/components/Settings/Clients/Form/components/MainSettings.tsx",
"chars": 4561,
"preview": "import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Controller, useFormContext } from 'r"
},
{
"path": "client/src/components/Settings/Clients/Form/components/ScheduleServices.tsx",
"chars": 809,
"preview": "import React from 'react';\nimport { Trans } from 'react-i18next';\nimport { useFormContext } from 'react-hook-form';\nimpo"
},
{
"path": "client/src/components/Settings/Clients/Form/components/UpstreamDns.tsx",
"chars": 3096,
"preview": "import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\n\nimport { Controller, useFormContext }"
},
{
"path": "client/src/components/Settings/Clients/Form/components/index.ts",
"chars": 241,
"preview": "export { BlockedServices } from './BlockedServices';\nexport { ClientIds } from './ClientIds';\nexport { ScheduleServices "
},
{
"path": "client/src/components/Settings/Clients/Form/index.tsx",
"chars": 8395,
"preview": "import React, { useState } from 'react';\nimport { useSelector } from 'react-redux';\nimport { Trans, useTranslation } fro"
},
{
"path": "client/src/components/Settings/Clients/Form/types.ts",
"chars": 763,
"preview": "export type ClientForm = {\n name: string;\n tags: { value: string; label: string }[];\n ids: { name: string }[];\n"
},
{
"path": "client/src/components/Settings/Clients/Modal.tsx",
"chars": 3079,
"preview": "import React from 'react';\nimport { Trans, withTranslation } from 'react-i18next';\n\nimport ReactModal from 'react-modal'"
}
]
// ... and 733 more files (download for full content)
About this extraction
This page contains the full source code of the AdguardTeam/AdGuardHome GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 933 files (7.1 MB), approximately 1.9M tokens, and a symbol index with 3787 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.